Oct 17, 2010

[Library] Apache Axis2 で SOAP Request/Response を GZIP 圧縮する方法

Apache Axis2 で SOAP Request/Response を GZIP 圧縮する方法をメモ。

コード

Options を生成し、Stub (実際には WSDL から自動生成された Stub のサブクラス) にセットする。 MC_GZIP_REQUEST が SOAP Request の圧縮可否。 MC_ACCEPT_GZIP が SOAP Response の圧縮可否。 詳細は下記のリンクを参照のこと。

Stub stub = 
Options options = new Options();
options.setProperty(HTTPConstants.MC_GZIP_REQUEST, true);
options.setProperty(HTTPConstants.MC_ACCEPT_GZIP, true);
stub._getServiceClient().setOverrideOptions(options);
Options#setProperty
http://ws.apache.org/axis2/1_5_1/api/org/apache/axis2/client/Options.html#setProperty(java.lang.String,%20java.lang.Object)
HTTPConstants
http://ws.apache.org/axis2/1_5_1/api/org/apache/axis2/transport/http/HTTPConstants.html

動作確認

Apache Axis2 で HTTP Request/Response を確認する方法 でログを出力すると、以下のヘッダを確認できる。

2010-10-17 23:56:29,026 DEBUG [main] (Wire.java:70) - >> "Accept-Encoding: gzip[\r][\n]"
2010-10-17 23:56:29,026 DEBUG [main] (Wire.java:70) - >> "Content-Encoding: gzip[\r][\n]"
ちなみに、某サービスの軽量 SOAP 通信で GZIP 圧縮を ON にしてみたところ通信速度が 30% 速くなった。 サービスが GZIP 圧縮に対応しており、クライアントの CPU に余裕があれが是非 ON にしておきたい。
但し、GZIP 圧縮を ON にするとログに出力される SOAP Request/Response の目視での確認は困難になる。 デバッグの際には OFF にする必要がある。

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

Oct 09, 2010

[Library] Apache Axis2 で HTTP Request/Response を確認する方法

Axis2 は通信に Apache HttpComponents を使用しているので Log4j で HTTP Request/Response を確認することができる。 SOAP 通信の内容を見られるのでデバッグの際にとても便利。

log4j.xml の設定方法

"httpclient.wire" カテゴリのログレベルを "debug" にするだけ。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
 
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>

  <!-- for Axis2 -->
  <category name="httpclient.wire">
    <priority value="debug" />
  </category>
  <!-- /for Axis2 -->

</log4j:configuration>

ログ出力例

2010-10-08 23:02:45,670 DEBUG [main] (Wire.java:70) - >> "POST /services/Soap/u/20.0 HTTP/1.1[\r][\n]"
2010-10-08 23:02:45,682 DEBUG [main] (Wire.java:70) - >> "Content-Type: text/xml; charset=UTF-8[\r][\n]"
2010-10-08 23:02:45,682 DEBUG [main] (Wire.java:70) - >> "SOAPAction: "urn:partner.soap.sforce.com:Soap:loginRequest"[\r][\n]"
2010-10-08 23:02:45,682 DEBUG [main] (Wire.java:70) - >> "User-Agent: Axis2[\r][\n]"
2010-10-08 23:02:45,683 DEBUG [main] (Wire.java:70) - >> "Host: test.salesforce.com[\r][\n]"
2010-10-08 23:02:45,683 DEBUG [main] (Wire.java:70) - >> "Transfer-Encoding: chunked[\r][\n]"
2010-10-08 23:02:45,683 DEBUG [main] (Wire.java:70) - >> "[\r][\n]"
2010-10-08 23:02:46,146 DEBUG [main] (Wire.java:70) - >> "143[\r][\n]"
2010-10-08 23:02:46,146 DEBUG [main] (Wire.java:84) - >> "<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body>(略)</soapenv:Body></soapenv:Envelope>"
2010-10-08 23:02:46,147 DEBUG [main] (Wire.java:70) - >> "[\r][\n]"
2010-10-08 23:02:46,147 DEBUG [main] (Wire.java:84) - >> "0"
2010-10-08 23:02:46,147 DEBUG [main] (Wire.java:70) - >> "[\r][\n]"
2010-10-08 23:02:46,148 DEBUG [main] (Wire.java:70) - >> "[\r][\n]"
2010-10-08 23:02:46,488 DEBUG [main] (Wire.java:70) - << "HTTP/1.1 200 OK[\r][\n]"
2010-10-08 23:02:46,488 DEBUG [main] (Wire.java:70) - << "HTTP/1.1 200 OK[\r][\n]"
2010-10-08 23:02:46,490 DEBUG [main] (Wire.java:70) - << "Server: [\r][\n]"
2010-10-08 23:02:46,490 DEBUG [main] (Wire.java:70) - << "Content-Type: text/xml; charset=utf-8[\r][\n]"
2010-10-08 23:02:46,491 DEBUG [main] (Wire.java:70) - << "Content-Length: 1626[\r][\n]"
2010-10-08 23:02:46,491 DEBUG [main] (Wire.java:70) - << "Date: Fri, 08 Oct 2010 23:02:46 GMT[\r][\n]"
2010-10-08 23:02:46,491 DEBUG [main] (Wire.java:70) - << "[\r][\n]"
2010-10-08 23:02:46,499 DEBUG [main] (Wire.java:84) - << "<?xm"
2010-10-08 23:02:46,502 DEBUG [main] (Wire.java:84) - << "l version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body>(略)</soapenv:Body></soapenv:Envelope>"

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

Sep 10, 2010

[Library] GWT で Date を文字列化する

GWT で java.util.Date を文字列化する方法をメモ。 Calendar、DateFormat 等が利用できないので Date の deprecated メソッドで年月日などをそれぞれ取得し文字列化するか、 GWT 提供のクラス DateTimeFormat を使用する必要がある。 DateTimeFormat の使用例は以下の通り(使用例を示す程のものでもないけれど・・・)。

import java.util.Date;
import com.google.gwt.i18n.client.DateTimeFormat;

Date date = new Date(dateAsLong);
DateTimeFormat formatter = DateTimeFormat.getFormat("yyyy/MM/dd HH:mm");
String str = formatter.format(date);

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

Dec 25, 2009

Dec 01, 2009

[Library] Lucene 3.0.0 Released!!

Java による全文検索エンジン Lucene がメジャーバージョンアップ。 今回はクリーンアップリリースと銘打っており、機能追加はせず内部のリファクタや JavaSE 5.0 への対応をメインとしているとのこと。

25 November 2009 - Lucene Java 3.0.0 available
http://lucene.apache.org/#25+November+2009+-+Lucene+Java+3.0.0+available
Lucene Change Log
http://lucene.apache.org/java/3_0_0/changes/Changes.html

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

May 26, 2009

[Library] iCal4j にチャレンジ

iCal4j とは

iCal4j は iCalendar を Java で扱うライブラリ。 公式サイトによると

iCal4j is a Java API that provides support for the iCalendar specification as defined in RFC2445. This support includes a Parser, Object Model and Generator for iCalendar data streams.
というものらしい。
iCal4j
http://ical4j.sourceforge.net/
iCal4j - API Documents
http://m2.modularity.net.au/projects/ical4j/apidocs/
iCal4j - Download
http://sourceforge.net/project/showfiles.php?group_id=107024
iCal4j - Source Repository
http://ical4j.cvs.sourceforge.net/viewvc/ical4j/iCal4j/

Maven2 での iCal4j の利用

iCal4j は Maven Central Repository に登録されている。便利。場所は こちら。 Maven2 で管理しているプロジェクトであれば pom.xml に

<project>
  <dependencies>
    <dependency>
      <groupId>ical4j</groupId>
      <artifactId>ical4j</artifactId>
      <version>0.9.20</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>
</project>
を追記するだけで利用出来るようになる。

サンプルコード

イベントを作成し、文字列として書き出すコードのサンプルはこちら。

// イベントの生成
VEvent event = new VEvent();
// UID
event.getProperties().add(new Uid("id"));
// タイムゾーン
TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance()
        .createRegistry();
net.fortuna.ical4j.model.TimeZone timezoneAsIcalTimeZone = registry
        .getTimeZone(this.timeZone.getValue());
VTimeZone tz = timezoneAsIcalTimeZone.getVTimeZone();
event.getProperties().add(tz.getTimeZoneId());
// サマリ
event.getProperties().add(new Summary("サマリ"));
// 詳細
event.getProperties().add(new Description("詳細"));
// 場所
event.getProperties().add(new Location("場所"));
// 最終更新日時
event.getProperties().add(
new LastModified(new DateTime(System.currentTimeMillis())));
// 開始日時
event.getProperties().add(
        new DtStart(new DateTime(System.currentTimeMillis())));
// 終了日時
event.getProperties().add(
        new DtEnd(new DateTime(System.currentTimeMillis() + 60 * 60 * 1000)));

// カレンダの生成
Calendar calendar = new Calendar();
calendar.getProperties().add(new ProdId("productId"));
calendar.getProperties().add(CalScale.GREGORIAN);
calendar.getProperties().add(Version.VERSION_2_0);

// カレンダにイベントを追加
calendar.getComponents().add(event);

// カレンダを文字列として書き出す
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CalendarOutputter outputter = new CalendarOutputter();
outputter.output(calendar, baos);
String calendarAsString = baos.toString("UTF-8");

公式サイトに様々なサンプルコードが紹介されている。

iCal4j - Examples
http://wiki.modularity.net.au/ical4j/index.php?title=Examples

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

Jun 19, 2008

[Library] QR コードクラスライブラリ for Java にチャレンジ

QR コードクラスライブラリ for Java とは

QR コードクラスライブラリ for Java は、文字列から QR コードのデータを作成する Java 用のライブラリ。 ライブラリに文字列を渡すと boolean[][] の配列を返してくれる。 良く見かける QR コードの画像は boolean[][] から自前で作成する。

QR コードクラスライブラリ for Java
http://www.swetake.com/qr/java/qr_java.html

QR コードクラスライブラリ for Java で QR コード画像を作成してみる。

とりあえず ↓ の情報だけは一通り目を通すと良い。

QR コードクラスライブラリ for Java - API Document
http://www.swetake.com/qr/java/docs/index.html
QR Code.com - バージョンの決定
http://www.denso-wave.com/qrcode/vertable1.html
QR Code.com - コード領域の確定
http://www.denso-wave.com/qrcode/qrgene4.html

作成した画像をテストするには ↓ のツールを使用すると便利。

Psytec - QR Code Editor
http://www.psytec.co.jp/docomo.html

サンプルコード

// QRコードクラスライブラリ for Java の準備。
Qrcode qrcodeLogic = new Qrcode();
qrcodeLogic.setQrcodeEncodeMode('*');
qrcodeLogic.setQrcodeErrorCorrect('M');
qrcodeLogic.setQrcodeVersion(7);

// QR コードデータを作成。
byte[] targetBytes = target.getBytes();
boolean[][] qrcodeData = qrcodeLogic.calQrcode(targetBytes);

// QR コード画像用の BufferedImage を準備。
//   周りに 4cell 分のマージンを用意する。
BufferedImage image = new BufferedImage(size.getCellSize()
        * (qrcodeData[0].length + 8), size.getCellSize()
        * (qrcodeData[0].length + 8), BufferedImage.TYPE_INT_BGR);
Graphics g = image.getGraphics();
g.setColor(QRCODE_IMAGE_BACKGROUNDCOLOR);
g.fillRect(0, 0, image.getWidth(), image.getHeight());

// QR コードデータを画像に変換。
for (int i = 0; i < qrcodeData.length; i++) {
    for (int j = 0; j < qrcodeData[i].length; j++) {
        boolean cellFilled = qrcodeData[i][j];
        Color cellColor = cellFilled ? QRCODE_IMAGE_FOREGROUNDCOLOR
                : QRCODE_IMAGE_BACKGROUNDCOLOR;
        g.setColor(cellColor);
        g.fillRect(size.getCellSize() * (i + 4), size.getCellSize()
                * (j + 4), size.getCellSize(), size.getCellSize());
    }
}
g.dispose();

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

Dec 26, 2007

[Library] Commons Logging 1.1.1 で Log4j の trace レベルを有効にする。

(2008/01/25) 致命的な間違いのため訂正

桜が咲く頃にふと想ふ さんの 「Commons Loggin + Log4jでTRACEレベルのログを出力CommentsAdd Star」 で、本エントリが根本的に間違っていることを指摘いただいた。ありがとうございます。

Commons Logging 1.1.1 + Log4j 1.2.12 で一切カスタマイズ無しで普通に Trace ログを出力できた。 ソースコード でも確認済み。 ・・・カスタマイズしたときに見たソースコードは一体何だったのだろう??

お詫びして訂正致します。取消線が入っている情報は間違っています。信じないで下さい。

Commons Logging 1.1.1 から Log4j を使用する場合、デフォルトでは Commons Logging の trace ログレベルは Log4j の debug ログレベルに対応付けられる。 Log4j では永らく trace ログレベルがサポートされていなかったので当然こういう実装になるだろう。

Log4j 1.2.12 で trace ログレベルがサポートされたのだけれど、残念ながら Commons Logging では未対応の様だ。 というわけで、自力で Commons Logging の trace ログレベルを Log4j の trace ログレベルに対応付けてみた。

Apache Logging Services
http://logging.apache.org/
ASF Bugzilla Bug 35711 Add TRACE level to 1.2 api
http://issues.apache.org/bugzilla/show_bug.cgi?id=35711
Apache Commons - Commons Logging
http://commons.apache.org/logging/

Commons Logging の設定

Commons Logging と Log4j の橋渡しは Log4JLogger というクラスが行っているので、Log4JLogger を拡張して差し替える。

Log4JLogger の拡張クラス


package jp.in_vitro.codelet.logging;

import org.apache.commons.logging.impl.Log4JLogger;
import org.apache.log4j.Logger;

public class TracableLogger extends Log4JLogger {

    public TracableLogger() {
        super();
    }

    public TracableLogger(final Logger logger) {
        super(logger);
    }

    public TracableLogger(final String name) {
        super(name);
    }

    @Override
    public boolean isTraceEnabled() {
        Logger logger = getLogger();
        return logger.isTraceEnabled();
    }

    @Override
    public void trace(final Object message, final Throwable t) {
        Logger logger = getLogger();
        logger.trace(message, t);
    }

    @Override
    public void trace(final Object message) {
        Logger logger = getLogger();
        logger.trace(message);
    }
}

Commons Logging の設定ファイル

クラスパスのルートに "commons-logging.properties" を作成する。


org.apache.commons.logging.Log=jp.in_vitro.codelet.logging.TracableLogger

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

Oct 23, 2007

[Library] jMock で java.sql.Connection のモックオブジェクト生成にチャレンジ

JMock で java.sql.Connection のモックオブジェクト作成に挑戦してみた。 ・・・と言っても、まだ jMock のサンプルを眺めただけ。

jMock
http://www.jmock.org/

サンプルコード - その1

とりあえず基礎の基礎。 単純な java.sql.Connection のモックオブジェクトを作成してみた。 example1 はテスト成功パターン。example2 はテスト失敗パターン。

package jp.in_vitro.codelets.jmock;

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

import org.jmock.Expectations;
import org.jmock.Mockery;

public class Codelet {

    public static void main(String[] args) throws SQLException {
        Codelet me = new Codelet();
        me.example0();
        me.example1();
    }

    protected void example0() throws SQLException {
        Mockery context = new Mockery();
        final Connection connection = context.mock(Connection.class);
        context.checking(new Expectations() {
            {
                one(connection).close();
            }
        });

        connection.close();
        context.assertIsSatisfied();
    }

    protected void example1() throws SQLException {
        Mockery context = new Mockery();
        final Connection connection = context.mock(Connection.class);
        context.checking(new Expectations() {
            {
                one(connection).close();
            }
        });

        // connection.close();
        context.assertIsSatisfied();
    }
}

サンプルコード - その2

次に java.sql.Connection から java.sql.Statement を返してみた。 とりあえず指定した java.sql.Statement を java.sql.Connection#createStatement から返すことに成功。

package jp.in_vitro.codelets.jmock;

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

import org.jmock.Expectations;
import org.jmock.Mockery;

public class Codelet {

    public static void main(String[] args) throws SQLException {
        Codelet me = new Codelet();
        me.example2();
    }

    protected void example2() throws SQLException {
        Mockery context = new Mockery();
        final Connection connection = context.mock(Connection.class);
        final Statement expected = context.mock(Statement.class);
        context.checking(new Expectations() {
            {
                one(connection).createStatement();
                will(returnValue(expected));
            }
        });

        Statement actual = connection.createStatement();
        System.out.println("expected: " + expected + "@" + expected.hashCode());
        System.out.println("actual: " + actual + "@" + actual.hashCode());
        context.assertIsSatisfied();
    }
}

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

Jul 14, 2007

[Library] Ant から Subversion へのアクセスにチャレンジ

チャレンジというほどのものでもない。 単に SvnAnt を使ってみただけ。 Ant 1.7.0 と簡単に連携できた。 これは便利。 ちょっと Ant で簡単なスクリプトを書くときに重宝しそう。

SvnAnt
http://subclipse.tigris.org/svnant.html
Apache Ant
http://ant.apache.org/

build.xml

<?xml version="1.0" encoding="UTF-8"?>

<project name="my project" default="checkout" basedir=".">

  <property name="workspace.dir" value="c:\workspace\myproject" />
  <property name="svn.userid"    value="scott" />
  <property name="svn.password"  value="tiger" />
  <property name="svn.url"       value="https://svn.example.com/svn/myproject/trunk" />
  <property name="svn.revision"  value="HEAD" />

  <path id="svnant.class.path">
    <fileset dir="${env.ANT_HOME}/antsvn/">
      <include name="*.jar" />
    </fileset>
  </path>

  <typedef resource="org/tigris/subversion/svnant/svnantlib.xml"
           classpathref="svnant.class.path"/>

  <target name="checkout">
    <delete dir="${workspace.dir}" />
    <mkdir dir="${workspace.dir}" />
    <svn username="${svn.userid}"
         password="${svn.password}">
      <checkout url="${svn.url}"
                revision="${svn.revision}"
                destPath="${workspace.dir}" />
    </svn>
  </target>
</project>

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

Jul 10, 2007

[Library] Apache Struts の Upgrade 方法をメモ

既存アプリケーションで使用している Apache Struts を Upgrade するときに便利なドキュメントがあったのでメモ。

StrutsUpgradeNotes10to12
http://wiki.apache.org/struts/StrutsUpgradeNotes10to12
StrutsUpgradeNotes11to124
http://wiki.apache.org/struts/StrutsUpgradeNotes11to124
StrutsUpgradeNotes124to127
http://wiki.apache.org/struts/StrutsUpgradeNotes124to127
StrutsUpgradeNotes127to128
http://wiki.apache.org/struts/StrutsUpgradeNotes127to128
StrutsUpgradeNotes128to129
http://wiki.apache.org/struts/StrutsUpgradeNotes128to129
StrutsUpgradeNotes12to13
http://wiki.apache.org/struts/StrutsUpgradeNotes12to13

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

May 24, 2007

[Library] Log4j を使用してログを syslog に出力する

Debian Etch の syslog にリモートから Log4j を使用してログを出力する方法をメモ。

syslogd の設定

Debian Etch では、デフォルト状態の syslogd はリモートからのログを受け付けない設定になっている。 そのため、syslogd の設定を変更して syslogd をリブートする必要がある。 設定は /etc/default/syslogd で行う。

# diff /etc/default/syslogd.original /etc/default/syslogd
13c13
< SYSLOGD=""
---
> SYSLOGD="-r"
# /etc/init.d/sysklogd restart
#
設定が正常に反映されたか確認するために、syslog のポートが開いているかチェックする。
# netstat -an | grep -i udp | grep 514
udp        0      0 0.0.0.0:514             0.0.0.0:*
#
UDP の 514 が開いていたら設定は成功。

Log4j の設定

Log4j にはデフォルトで syslog にログを出力してくれる org.apache.log4j.net.SyslogAppender が用意されている。 しかし、残念なことに org.apache.log4j.PatternLayout が文字エンコーディングの変換機能を持っていないので、マルチバイト文字をメッセージに使用するとログが文字化けしてしまう。 そのため、PatternLayout を拡張して文字エンコーディングを変換する機能を持った Layout クラスを自作する必要がある。 Debian Etch の場合は(インストール時の設定にもよるけれど)、通常デフォルトの文字エンコーディングは EUC-JP になっていると思うので、EUC-JP に変換できればマルチバイト文字をログに出力できる。

文字エンコーディング変換機能付き PatternLayout

PatternLayout の拡張は非常に簡単。 単純に文字エンコーディングを設定内容からインジェクションしてもらい、PatternLayout でメッセージをフォーマットした後に変換処理をするだけ。

package jp.in_vitro.samplecode;

import java.io.UnsupportedEncodingException;

import org.apache.log4j.PatternLayout;
import org.apache.log4j.spi.LoggingEvent;

/**
 * メッセージのフォーマット後に文字エンコーディング変換を行う {@link PatternLayout}。
 */
public class CharsetSupportPatternLayout extends PatternLayout {

    /** メッセージをフォーマット後に変換する文字エンコーディング。 */
    private String charset;

    public CharsetSupportPatternLayout() {
        super();
    }

    public CharsetSupportPatternLayout(final String pattern) {
        super(pattern);
    }

    public void setCharset(final String charset) {
        this.charset = charset;
    }

    @Override
    public String format(final LoggingEvent event) {
        String message = super.format(event);
        if (this.charset != null) {
            try {
                message = new String(message.getBytes(this.charset));
            } catch (UnsupportedEncodingException e) {
            }
        }
        return message;
    }
}

Log4j の設定

log4j.properties に下記の様な感じで設定する。log4j.xml にする場合はこの内容に準じて XML に書き直せば良い。 Facility は syslog のカテゴリに相当するもので、デフォルトでは user、uucp などが規定されている。 システムにもよるけれど、専用の Facility を用意した方が分かり易いと個人的には思う。 前述の通り、Debian Etch の場合、charset は EUC-JP を指定する(と大抵は上手くいくと思う)。 ConversionPattern は通常と少し違い、時刻と改行コードを省略している。 時刻は syslogd が自動的に付加してくれるのと、改行コードはプラットフォーム毎に異なるのでメッセージには付加しないようにしている。 メッセージに改行コードが付いていなくても、syslogd が付加してくれる様なので特に問題はない(はず)。

log4j.appender.syslog=org.apache.log4j.net.SyslogAppender
log4j.appender.syslog.Facility=[facility]
log4j.appender.syslog.SyslogHost=[syslog server]
log4j.appender.syslog.layout=jp.in_vitro.samplecode.CharsetSupportPatternLayout
log4j.appender.syslog.layout.charset=[syslog server default character encoding]
log4j.appender.syslog.layout.ConversionPattern=%5p %c{1} - %m

実験

下記の様なテストコードを Windows XP 上で実行してみた。 面倒なので facility は uucp を間借りした。

Logger log = Logger.getLogger(CharsetSupportPatternLayoutTest.class);
log.fatal("Oh, my god!!");
log.error("緊急事態");
log.warn("気をつけて");
log.info("お知らせ");
log.debug("デバッグ");
リモートの Debian Etch では以下の様なログが出力された。
# tail -f /var/log/uucp.log
May 26 16:14:03 192.168.1.101 FATAL Hoge - Oh, my god!!
May 26 16:14:03 192.168.1.101 ERROR Hoge - 緊急事態
May 26 16:14:03 192.168.1.101  WARN Hoge - 気をつけて
May 26 16:14:03 192.168.1.101  INFO Hoge - お知らせ
May 26 16:14:04 192.168.1.101 DEBUG Hoge - デバッグ
というわけで、実験成功。 但し、何故か変な化け方をする文字が結構ある。 メッセージの 'る' が 'た' に変わってしまうといった感じ。 後で原因を調査しないと・・・。

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

May 21, 2007

[Library] Mock ライブラリを調査

Java で利用できる Mock ライブラリを調べてみた。 昔使用していた MockObjects は いつの間にか開発が停止して現在ではダウンロード出来なくなっているようだ。

Mock ライブラリ

EasyMock

現時点で一番情報が多そうなのが EasyMock か。 多少慣れるのに時間がかかりそうだが、結構使い出はありそう。 jMock とどちらを選択するかは好みの問題になるだろうか。

EasyMock
http://www.easymock.org/
EasyMock 2.2 Readme
http://www.easymock.org/EasyMock2_2_Documentation.html
EasyMock 2 License (MIT License)
http://www.easymock.org/License.html

jMock

EasyMock とどちらを選択するか悩むところ。 とりあえず両方試してみて自分に合う方を選択するということになりそう。

jMock
http://www.jmock.org/index.html
Getting Started
http://www.jmock.org/getting-started.html
jMock Project License
http://www.jmock.org/license.html

RMock

RMock testing framework
http://rmock.sourceforge.net/
The RMock 2.0.0 user guide
http://rmock.sourceforge.net/documentation/xdoc.html
Project License (Apache License Version 2.0)
http://rmock.sourceforge.net/documentation/license.html

mocquer

mocquer
https://mocquer.dev.java.net/
CPL
http://www.opensource.org/licenses/cpl1.0.php

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

Jun 18, 2006

[Library] JChart2D にチャレンジ

JChart2D とは

JChart2D はチャートを生成してくれる Java 用のライブラリ。 LGPL で提供されている。

JChart2D
http://jchart2d.sourceforge.net/
demo
http://jchart2d.sourceforge.net/applet.shtml

実行環境準備

  1. こちら から JChart2D をダウンロードする。ここでは jchart2d-2.0.0.jar を前提とする。
  2. jchart2d-2.0.0.jar をクラスパスに追加する。

サンプルコード

JChart2D を使用して JPEG のチャートを生成するサンプルを作成してみた。 残念なことに、ウィンドウを表示しない状態での動作は実現できなかった。 というわけで、X Window System がインストールされていない等でウィンドウ描画ができない環境では実行できない。 何か方法があるのだろうか・・・。

package jp.in_vitro.codelets.jchart2d;

import info.monitorenter.gui.chart.Chart2D;
import info.monitorenter.gui.chart.ITrace2D;
import info.monitorenter.gui.chart.traces.Trace2DSimple;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class Codelet {

    public Codelet() {
        super();
    }

    protected void execute() throws IOException {
        Chart2D chart = new Chart2D();
        ITrace2D trace = new Trace2DSimple();
        Random random = new Random();
        for (int i = 100; i >= 0; i--) {
            trace.addPoint(i, random.nextDouble() * 10.0 + i);
        }
        chart.addTrace(trace);
        chart.setSize(640, 480);
        chart.setPaintLabels(true);

        JFrame frame = new JFrame();
        frame.setSize(640, 480);
        frame.add(chart);
        frame.setVisible(true);

        BufferedImage image = chart.snapShot();

        frame.setVisible(false);
        frame.dispose();

        ImageIO.write(image, "JPEG", new File("c:\\chart.jpg"));
    }

    public static void main(String[] args) throws IOException {
        Codelet me = new Codelet();
        me.execute();
    }
}

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

Jun 05, 2006

[Library] JDiff にチャレンジ

JDiff とは

JDiff はプロジェクトのバージョン間で API の diff を取るツール。 カスタム Doclet として提供され、新旧 API Document の比較を行い、比較結果の API Document を生成する。 ソースコードではなく、API の比較というのは目新しいので試してみた。

JDiff
http://sourceforge.net/projects/javadiff/

サンプルの実行

サンプルは Ant から実行できる。 JDK、Ant にパスを通して Ant を実行する。 ↓の例では JDiff のバージョンを確認するために JDiff にもパスを通している。

>set JAVA_HOME=c:\_java\jdk\1.5.0_06
>set PATH=%JAVA_HOME%\bin;%PATH%
>set ANT_HOME=c:\_java\tool\ant\1.6.4
>set PATH=%ANT_HOME%\bin;%PATH%
>set JDIFF_HOME=c:\_java\tool\jdiff\1.0.10
>set PATH=%JDIFF_HOME%\bin;%PATH%
>java -version
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode, sharing)

>ant -version
Apache Ant version 1.6.4 compiled on May 19 2005

>jdiff -version
JDiff version: 1.0.10

>cd c:\_java\tool\jdiff\1.0.10\examples

>ant
Buildfile: build.xml

init:

create_javadoc_dirs:

javadoc_old:
  [javadoc] Generating Javadoc
  [javadoc] Javadoc execution
  [javadoc] パッケージ com.acme.sp のソースファイルを読み込んでいます...
  [javadoc] パッケージ com.acme.util のソースファイルを読み込んでいます...
  [javadoc] Javadoc 情報を構築しています...
  [javadoc] 標準 Doclet バージョン 1.5.0_06

  ...略

javadoc_new:
  [javadoc] Generating Javadoc
  [javadoc] Javadoc execution
  [javadoc] パッケージ com.acme.sp のソースファイルを読み込んでいます...
  [javadoc] パッケージ com.acme.spextra のソースファイルを読み込んでいます...
  [javadoc] Javadoc 情報を構築しています...
  [javadoc] 標準 Doclet バージョン 1.5.0_06

  ...略

jdiff_old_api:
  [javadoc] Generating Javadoc
  [javadoc] Javadoc execution
  [javadoc] パッケージ com.acme.sp のソースファイルを読み込んでいます...
  [javadoc] パッケージ com.acme.util のソースファイルを読み込んでいます...
  [javadoc] Javadoc 情報を構築しています...
  [javadoc] JDiff: doclet started ...
  [javadoc] JDiff: writing the API to file 'SuperProduct_1.0.xml'...
  [javadoc] JDiff: finished (took 0s, not including scanning the source files).

jdiff_new_api:
  [javadoc] Generating Javadoc
  [javadoc] Javadoc execution
  [javadoc] パッケージ com.acme.sp のソースファイルを読み込んでいます...
  [javadoc] パッケージ com.acme.spextra のソースファイルを読み込んでいます...
  [javadoc] Javadoc 情報を構築しています...
  [javadoc] JDiff: doclet started ...
  [javadoc] JDiff: writing the API to file 'SuperProduct_2.0.xml'...
  [javadoc] JDiff: finished (took 0s, not including scanning the source files).

jdiff_compare_apis:
  [javadoc] Generating Javadoc
  [javadoc] Javadoc execution
  [javadoc] ソースファイル C:\_java\tool\jdiff\1.0.10\lib\Null.java を読み込んで
います...
  [javadoc] Javadoc 情報を構築しています...
  [javadoc] JDiff: doclet started ...
  [javadoc] JDiff: reading the old API in from file 'SuperProduct_1.0.xml'... fi
nished
  [javadoc] JDiff: reading the new API in from file 'SuperProduct_2.0.xml'... fi
nished
  [javadoc] JDiff: comparing the old and new APIs ...
  [javadoc]  Approximately 64% difference between the APIs
  [javadoc] JDiff: reading the comments in from file 'C:\_java\tool\jdiff\1.0.10
\examples\sample_output\newdocs\user_comments_for_SuperProduct_1.0_to_SuperProdu
ct_2.0.xml'...
  [javadoc] JDiff: generating HTML report into the file 'C:\_java\tool\jdiff\1.0
.10\examples\sample_output\newdocs\changes.html' and the subdirectory 'C:\_java\
tool\jdiff\1.0.10\examples\sample_output\newdocs\changes'
  [javadoc] JDiff: writing the comments out to file 'C:\_java\tool\jdiff\1.0.10\
examples\sample_output\newdocs\user_comments_for_SuperProduct_1.0_to_SuperProduc
t_2.0.xml'...
  [javadoc] JDiff: finished (took 0s).

jdiff:

BUILD SUCCESSFUL
Total time: 14 seconds
>
Ant プロセス終了後、file:///C:/_java/tool/jdiff/1.0.10/examples/sample_output/newdocs/changes.html にアクセスする。

[JDiff 生成結果(1)] [JDiff 生成結果(2)]

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

May 28, 2006

[Library] JasperReports にチャレンジ

JasperReports とは

JasperReports はオープンソースの帳票ソリューション。 帳票印刷、PDF 生成はもちろんのこと、HTML、XLS、CSV、XML の生成が可能。 帳票のデザイナもオープンソースで提供されている、なかなかの優れもの。

JasperReports
http://jasperreports.sourceforge.net/index.html
Tutorial
http://jasperreports.sourceforge.net/tutorial/index.html
GUI Tools
http://jasperreports.sourceforge.net/tools.html
License
http://jasperreports.sourceforge.net/license.html

サンプル実行

実行環境準備

サンプルの実行には JDK、Ant が必要。

>set JAVA_HOME=c:\_java\jdk\1.5.0_06
>set ANT_HOME=c:\_java\tool\ant\1.6.4
>set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin;%PATH%

>java -version
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode, sharing)

>ant -version
Apache Ant version 1.6.4 compiled on May 19 2005
>cd .\jasperreports-1.2.2\demo\samples\csvdatasource

csvdatasource サンプルの実行

>ant clean javac compile fill pdf
Buildfile: build.xml

clean:

javac:
    [javac] Compiling 1 source file to C:\jasperreports-1.2.2\demo\samples\csvda
tasource
    [javac] 注: C:\jasperreports-1.2.2\demo\samples\csvdatasource\CsvDataSourceA
pp.java の操作は、未チェ
ックまたは安全ではありません。
    [javac] 注: 詳細については、-Xlint:unchecked オプションを指定して再コンパイ
ルしてください。

compile:
      [jrc] Compiling 1 report design files.
      [jrc] File : C:\jasperreports-1.2.2\demo\samples\csvdatasource\CsvDataSourc
eReport.jrxml ... OK.

fill:
     [java] Filling time : 1641

pdf:
     [java] PDF creation time : 1312

BUILD SUCCESSFUL
Total time: 8 seconds

fonts サンプルの実行

>ant clean javac compile fill pdf
Buildfile: build.xml

clean:

javac:
    [javac] Compiling 1 source file to C:\jasperreports-1.2.2\demo\samples\fonts
    [javac] 注: C:\jasperreports-1.2.2\demo\samples\fonts\FontsApp.java の操作は
、未チェックまたは安全ではありません。
    [javac] 注: 詳細については、-Xlint:unchecked オプションを指定して再コンパイ
ルしてください。

compile:
      [jrc] Compiling 1 report design files.
      [jrc] File : C:\jasperreports-1.2.2\demo\samples\fonts\FontsReport.jrxml .
.. OK.

fill:
     [java] Filling time : 2187

pdf:
     [java] PDF creation time : 2250

BUILD SUCCESSFUL
Total time: 10 seconds

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

May 18, 2006

[Library] Java Plugin Framework(JPF) にチャレンジ(2)

Plugin の構成

Plugin のディレクトリ構成は以下の通り。 このディレクトリ構成を ZIP、JAR でアーカイブ化すると Plugin になる。

PLUGIN_HOME
  ├classes/
  ├docs/
  │  └api/
  ├icons/
  ├lib/
  └plugin.xml

plugin.xml の DTD は以下にある。

Plug-in DTD
http://jpf.sourceforge.net/dtd.html

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

May 17, 2006

[Library] Java Plugin Framework(JPF) にチャレンジ

Java Plugin Framework(JPF) とは

JPF は、Plugin アーキテクチャをサポートするためのライブラリ。 ZIP や JAR 形式で Plugin を作成し、アプリケーションからその Plugin を読み込み利用する。

Java Plugin Framework(JPF)
http://jpf.sourceforge.net/
Tutorial
http://jpf.sourceforge.net/tutorial.html

デモアプリケーションの起動

JPF にはデモアプリケーションが用意されている。 デモアプリケーションは簡単に起動し、Plugin のロードを試すことができる。

jpf-demo
http://sourceforge.net/project/showfiles.php?group_id=110394&package_id=121489
jpf-demo-bin-0.8> set JAVA_HOME=c:\_java\jdk\1.5.0_06
jpf-demo-bin-0.8> set PATH=%JAVA_HOME%\bin;%PATH%
jpf-demo-bin-0.8> run.bat
[デモアプリケーションのウィンドウ]

サンプルコード

PluginManager を初期化し、Plugin をロードするサンプルコード。

package jp.in_vitro.codelets.jpf;

import java.io.InputStream;
import java.util.Collection;

import org.java.plugin.ObjectFactory;
import org.java.plugin.PluginManager;
import org.java.plugin.PluginManager.PluginLocation;
import org.java.plugin.boot.DefaultPluginsCollector;
import org.java.plugin.boot.PluginsCollector;
import org.java.plugin.registry.ExtensionPoint;
import org.java.plugin.registry.PluginDescriptor;
import org.java.plugin.util.ExtendedProperties;

public class Codelet {

    public Codelet() {
        super();
    }

    protected void execute() throws Exception {
        ExtendedProperties config = new ExtendedProperties(System
                .getProperties());
        InputStream is = null;
        try {
            String configFile = "/"
                    + this.getClass().getPackage().getName().replaceAll("\\.",
                            "/") + "/" + "config.properties";
            is = this.getClass().getResourceAsStream(configFile);
            config.load(is);
        } finally {
            if (is != null) {
                is.close();
            }
        }
        PluginManager pluginManager = ObjectFactory.newInstance(config)
                .createManager();

        PluginsCollector collector = new DefaultPluginsCollector();
        collector.configure(config);
        Collection pluginLocations = collector.collectPluginLocations();

        pluginManager.publishPlugins((PluginLocation[]) pluginLocations
                .toArray(new PluginLocation[pluginLocations.size()]));

        for (Object pdObj : pluginManager.getRegistry().getPluginDescriptors()) {
            PluginDescriptor pd = (PluginDescriptor) pdObj;
            System.out.println("" + pd);
            for (Object epObj : pd.getExtensionPoints()) {
                ExtensionPoint ep = (ExtensionPoint) epObj;
                System.out.println("    " + ep);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Codelet me = new Codelet();
        me.execute();
    }
}

config.properties

org.java.plugin.PathResolver=org.java.plugin.standard.ShadingPathResolver
org.java.plugin.standard.ShadingPathResolver.shadowFolder=${applicationRoot}/temp/.jpf-shadow
org.java.plugin.standard.ShadingPathResolver.unpackMode=smart
org.java.plugin.boot.pluginsRepositories=./plugins/

サンプルコードの実行結果

plugins ディレクトリにデモアプリケーションの Plugin をいくつか登録して読み込ませてみた。

2006/05/16 23:58:37 org.java.plugin.registry.xml.ManifestParser 
情報: got SAX parser factory - com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl@16a55fa
2006/05/16 23:58:37 org.java.plugin.registry.xml.PluginRegistryImpl configure
情報: configured, stopOnError=false, isValidating=true
2006/05/16 23:58:37 org.java.plugin.standard.ShadingPathResolver configure
情報: configured, shadow folder is C:\Codelets\${applicationRoot}\temp\.jpf-shadow
2006/05/16 23:58:37 org.java.plugin.registry.xml.PluginRegistryImpl register
情報: plug-in and fragment descriptors registered - 2
{PluginDescriptor: uid=org.jpf.demo.toolbox.pluginbrowser@0.0.4}
{PluginDescriptor: uid=org.jpf.demo.toolbox.core@0.0.4}
    {ExtensionPoint: uid=org.jpf.demo.toolbox.core@Tool}

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

May 12, 2006

[Library] Eclipse 3.1 で JUnit 4 のテストケースを一括実行する

JUnit 4 は JUnit 3 よりも楽にテストケースを作成できる。 最近はめっきり JUnit 4 に染まってしまった。 ただ、ツールのサポートが追いついていないところだけが玉に瑕。 Eclipse 3.1 の環境下で、JUnit 4 のテストケースを一括実行したいので簡単なコードを書いてみた。

JUnit 4 のテストケース一括実行用クラス

↓のコード (AllTests) をプロジェクトのルートパッケージに置いて実行する。 AllTests が置いてあるパッケージ以下の全テストケース("**/*Test.class") が実行される。 JVM は 5.0 以降が必要。

package jp.in_vitro.test;

import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import junit.framework.JUnit4TestAdapter;
import junit.framework.Test;
import junit.framework.TestSuite;

public class AllTests {

    public static Test suite() throws URISyntaxException,
            ClassNotFoundException {
        return AllTests.createTestSuite();
    }

    protected static TestSuite createTestSuite() throws URISyntaxException,
            ClassNotFoundException {
        TestSuite suite = new TestSuite();

        URL codeSourceUrl = AllTests.class.getProtectionDomain()
                .getCodeSource().getLocation();
        File codeSourceFile = new File(codeSourceUrl.toURI());
        String codeSourceName = codeSourceFile.getAbsolutePath().replaceAll(
                "\\\\", "\\\\\\\\");

        List<File> testCaseFiles = new ArrayList<File>();
        AllTests.listTestCase(testCaseFiles, codeSourceFile);

        for (File testCaseFile : testCaseFiles) {
            String fileName = testCaseFile.getAbsolutePath();
            String className = fileName.replaceAll(codeSourceName + "\\\\", "")
                    .replaceAll(".class", "").replaceAll("\\\\", ".");
            suite.addTest(new JUnit4TestAdapter(Class.forName(className)));
        }
        return suite;
    }

    protected static void listTestCase(final List<File> testCaseFiles,
            final File file) {

        for (File child : file.listFiles()) {
            if (child.isFile()) {
                if (child.getAbsolutePath().endsWith("Test.class")) {
                    testCaseFiles.add(child);
                }
            } else if (child.isDirectory()) {
                AllTests.listTestCase(testCaseFiles, child);
            }
        }
    }
}
Eclipse 3.2 では JUnit 4 はサポートされているだろうか??

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

May 08, 2006

[Library] JUnit 4.1 リリース

JUnit 4.1 がリリースされた。 README.html によると、4.0 からの変更点は

  • Bug fix: listeners now get a correct test running time, rather than always being told 0 secs.
  • The @RunWith annotation is now inherited by subclasses: all subclasses of an abstract test class will be run by the same runner.
  • The build script fails if the JUnit unit tests fail
  • The faq has been updated
  • Javadoc has been improved, with more internal links, and package descriptions added (Thanks, Matthias Schmidt!)
  • An acknowledgements.txt file has been created to credit outside contributions
  • The Enclosed runner, which runs all of the static inner classes of a given class, has been added to org.junit.runners.
だそうだ。 特に大きな変更は無い模様。

ついでに JUnit4 の素敵な紹介記事を発見したのでメモ。
developerWorks - JUnit 4の現状を紹介する
http://www-06.ibm.com/jp/developerworks/java/051007/j_j-junit4.shtml

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

Apr 24, 2006

[Library] JExcelAPI にチャレンジ(6)

チマチマと動作確認のために作成していたコードを貼っておく。 ここ数日の内容をまとめたもの。

package jp.in_vitro.codelets.jexcelapi;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import jxl.HeaderFooter;
import jxl.SheetSettings;
import jxl.Workbook;
import jxl.WorkbookSettings;
import jxl.format.Alignment;
import jxl.format.Border;
import jxl.format.BorderLineStyle;
import jxl.format.Colour;
import jxl.format.PageOrientation;
import jxl.format.PaperSize;
import jxl.write.Formula;
import jxl.write.Label;
import jxl.write.Number;
import jxl.write.WritableCellFeatures;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;

public class Codelet2 {

    public Codelet2() {
        super();
    }

    protected void execute() throws IOException, RowsExceededException,
            WriteException {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        WorkbookSettings settings = new WorkbookSettings();
        settings.setGCDisabled(true);
        WritableWorkbook book = Workbook.createWorkbook(baos, settings);

        WritableSheet sheet = book.createSheet("my sheet", 0);
        this.configureSheet(sheet);
        this.adjustColumnWidth(sheet);
        this.writeHeader(sheet, 1);
        this.writeBookmark(sheet, 2, 1, "Google", "http://www.google.com/",
                "サーチエンジン");
        this.writeBookmark(sheet, 3, 2, "CNN", "http://www.cnn.com/", "ニュース");
        this.writeBookmark(sheet, 4, 3, "Amazon", "http://www.amazon.co.jp/",
                "ショッピング");

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

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(new File("c:\\tmp.xls"));
            fos.write(baos.toByteArray());
            fos.flush();
        } finally {
            if (fos != null) {
                fos.close();
            }
        }
    }

    protected void configureSheet(final WritableSheet sheet) {

        SheetSettings settings = sheet.getSettings();

        HeaderFooter header = new HeaderFooter();
        header.getCentre().append("My Bookmarks");
        settings.setHeader(header);

        HeaderFooter footer = new HeaderFooter();
        footer.getCentre().appendPageNumber();
        footer.getCentre().append(" / ");
        footer.getCentre().appendTotalPages();
        settings.setFooter(footer);

        settings.setProtected(true);
        settings.setPassword("mypassword");

        settings.setFitHeight(2);
        settings.setFitWidth(0);
        settings.setFitToPages(true);

        settings.setHorizontalFreeze(1);
        settings.setVerticalFreeze(2);

        settings.setZoomFactor(75);

        sheet.setPageSetup(PageOrientation.LANDSCAPE, PaperSize.B5, 10, 10);
    }

    protected void adjustColumnWidth(final WritableSheet sheet) {

        int[] widths = new int[] { 10, 30, 50, 50 };

        for (int i = 0; i < widths.length; i++) {
            sheet.setColumnView(i, widths[i]);
        }
    }

    protected void writeHeader(final WritableSheet sheet, final int y)
            throws WriteException {

        String[] headers = new String[] { "No.", "Title", "URL", "Description" };
        String[] comments = new String[] { "番号", "タイトル", "", "備考" };

        WritableCellFormat format = new WritableCellFormat();
        format.setBorder(Border.ALL, BorderLineStyle.THIN);
        format.setBackground(Colour.LIGHT_ORANGE);
        format.setAlignment(Alignment.CENTRE);

        WritableFont font = new WritableFont(format.getFont());
        font.setBoldStyle(WritableFont.BOLD);
        format.setFont(font);

        for (int i = 0; i < headers.length; i++) {
            WritableCellFeatures feature = new WritableCellFeatures();
            if (!"".equals(comments[i])) {
                feature.setComment(comments[i]);
            }
            Label label = new Label(i, y, headers[i]);
            label.setCellFeatures(feature);
            label.setCellFormat(format);
            sheet.addCell(label);
        }
    }

    protected void writeBookmark(final WritableSheet sheet, final int y,
            final int no, final String title, final String url,
            final String description) throws RowsExceededException,
            WriteException {

        WritableCellFormat format = new WritableCellFormat();
        format.setBorder(Border.ALL, BorderLineStyle.THIN);

        Number noNumber = new Number(0, y, no);
        noNumber.setCellFormat(format);
        Label titleLabel = new Label(1, y, title);
        titleLabel.setCellFormat(format);
        Formula urlLabel = new Formula(2, y, "HYPERLINK(\"" + url + "\",\""
                + url + "\")");
        urlLabel.setCellFormat(format);
        Label descriptionLabel = new Label(3, y, description);
        descriptionLabel.setCellFormat(format);

        sheet.addCell(noNumber);
        sheet.addCell(titleLabel);
        sheet.addCell(urlLabel);
        sheet.addCell(descriptionLabel);
    }

    public static void main(String[] args) throws IOException,
            RowsExceededException, WriteException {
        Codelet2 me = new Codelet2();
        me.execute();
    }

}

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

Apr 23, 2006

[Library] JExcelAPI にチャレンジ(5)

JEXCELAPI にチャレンジ(4)の続き。

JExcelAPI 実行時の GC を抑制する

どうやら JExcelAPI はガベージコレクションを強制的に実行するらしい。 ガベージコレクションにより CPU に負荷がかかりすぎる様であれば、下記の方法で抑制する。

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        WorkbookSettings settings = new WorkbookSettings();
        settings.setGCDisabled(true);
        WritableWorkbook book = Workbook.createWorkbook(baos, settings);

ガベージコレクションの状況

実際に WorkbookSettings#setGCDisabled でどの程度ガベージコレクションの頻度が変わるのかチェックしてみた。 適当なブックを作成するサンプルコードを -verbose:gc 付きで実行してみた結果。 ガベージコレクションを抑制しないとかなり FULL GC が実行されていることが分かる。 サーバなどで JVM に大量のメモリを割り当てている環境では注意が必要になりそう。

-verbose:gc

setGCDisabled(true) setGCDisabled(false)
[GC 512K->219K(1984K), 0.0037125 secs]
[GC 731K->213K(1984K), 0.0013843 secs]
[GC 725K->355K(1984K), 0.0025442 secs]
[GC 485K->355K(1984K), 0.0008825 secs]
[Full GC 355K->355K(1984K), 0.0185440 secs]
[GC 5987K->5482K(7108K), 0.0007786 secs]
[GC 5994K->5489K(7108K), 0.0010468 secs]
[GC 6001K->5494K(7108K), 0.0008387 secs]
[GC 6006K->5510K(7108K), 0.0014418 secs]
[GC 5819K->5602K(7108K), 0.0015913 secs]
[GC 5940K->5604K(7108K), 0.0007699 secs]
[GC 6116K->5607K(7108K), 0.0007481 secs]
[GC 6118K->5644K(7108K), 0.0021126 secs]
[GC 5870K->5654K(7108K), 0.0005934 secs]
[Full GC 5654K->460K(7108K), 0.0228395 secs]
[GC 5946K->5605K(7108K), 0.0003456 secs]
[GC 5946K->5606K(7108K), 0.0003162 secs]
[GC 6116K->5649K(7108K), 0.0006051 secs]
[GC 5685K->5653K(7108K), 0.0005341 secs]
[Full GC 5653K->460K(7108K), 0.0227604 secs]
[GC 5946K->5605K(6612K), 0.0003417 secs]
[GC 5941K->5607K(6612K), 0.0002489 secs]
[GC 6117K->5649K(6612K), 0.0004610 secs]
[GC 5685K->5653K(6612K), 0.0005034 secs]
[Full GC 5653K->454K(6612K), 0.0246984 secs]
[GC 5940K->5600K(9932K), 0.0007546 secs]
[GC 5939K->5601K(9932K), 0.0002735 secs]
[GC 6111K->5644K(9932K), 0.0005029 secs]
[GC 5682K->5647K(9932K), 0.0005302 secs]
[Full GC 5647K->454K(9932K), 0.0233284 secs]
[GC 5940K->5600K(7220K), 0.0003615 secs]
[GC 5936K->5601K(7220K), 0.0002601 secs]
[GC 6111K->5644K(7220K), 0.0007819 secs]
[GC 5682K->5647K(7220K), 0.0005554 secs]
[Full GC 5647K->454K(7220K), 0.0346614 secs]
[GC 5939K->5600K(7220K), 0.0003635 secs]
[GC 5938K->5601K(7220K), 0.0002766 secs]
[GC 6111K->5644K(7220K), 0.0004685 secs]
[GC 5682K->5647K(7220K), 0.0005615 secs]
[Full GC 5647K->454K(7220K), 0.0334269 secs]
[GC 5939K->5600K(7220K), 0.0003344 secs]
[GC 5938K->5601K(7220K), 0.0002590 secs]
[GC 6108K->5638K(7220K), 0.0005610 secs]
[GC 5687K->5648K(7220K), 0.0005389 secs]
[Full GC 5648K->455K(7220K), 0.0241341 secs]
[GC 5941K->5601K(7220K), 0.0003498 secs]
[GC 5938K->5602K(7220K), 0.0003266 secs]
[GC 6109K->5638K(7220K), 0.0004643 secs]
[GC 5688K->5649K(7220K), 0.0005397 secs]
[Full GC 5649K->456K(7220K), 0.0234329 secs]
[GC 5942K->5602K(7224K), 0.0008445 secs]
[GC 5940K->5603K(7224K), 0.0002972 secs]
[GC 6114K->5646K(7224K), 0.0004772 secs]
[GC 5684K->5649K(7224K), 0.0005274 secs]
[Full GC 5649K->457K(7224K), 0.0240489 secs]
[GC 5942K->5602K(7228K), 0.0003386 secs]
[GC 5938K->5604K(7228K), 0.0002643 secs]
[GC 6113K->5646K(7228K), 0.0004836 secs]
[GC 5684K->5650K(7228K), 0.0005246 secs]
[Full GC 5650K->457K(7228K), 0.0248289 secs]
[GC 5941K->5602K(7228K), 0.0003587 secs]
[GC 5940K->5604K(7228K), 0.0002548 secs]
[GC 6114K->5646K(7228K), 0.0004914 secs]
[GC 5684K->5650K(7228K), 0.0005420 secs]
[Full GC 5650K->456K(7228K), 0.0240072 secs]
[GC 5940K->5602K(7224K), 0.0003609 secs]
[GC 5939K->5603K(7224K), 0.0002562 secs]
[GC 6113K->5645K(7224K), 0.0004696 secs]
[GC 5683K->5649K(7224K), 0.0005280 secs]
[Full GC 5649K->456K(7224K), 0.0239544 secs]
[GC 5940K->5602K(7224K), 0.0003447 secs]
[GC 5939K->5603K(7224K), 0.0002523 secs]
[GC 6113K->5645K(7224K), 0.0004699 secs]
[GC 5683K->5649K(7224K), 0.0005327 secs]
[Full GC 5649K->456K(7224K), 0.0233776 secs]
[GC 5940K->5602K(7224K), 0.0004629 secs]
[GC 5939K->5603K(7224K), 0.0002674 secs]
[GC 6113K->5645K(7224K), 0.0004660 secs]
[GC 5683K->5649K(7224K), 0.0005395 secs]
[Full GC 5649K->456K(7224K), 0.0236684 secs]
[GC 5940K->5602K(7224K), 0.0003498 secs]
[GC 5939K->5603K(7224K), 0.0002699 secs]
[GC 6113K->5645K(7224K), 0.0004730 secs]
[GC 512K->219K(1984K), 0.0030713 secs]
[GC 731K->213K(1984K), 0.0013647 secs]
[GC 725K->355K(1984K), 0.0024732 secs]
[GC 485K->355K(1984K), 0.0009328 secs]
[Full GC 355K->355K(1984K), 0.0186873 secs]
[GC 5987K->5482K(7108K), 0.0014714 secs]
[GC 5994K->5489K(7108K), 0.0010350 secs]
[GC 6001K->5494K(7108K), 0.0008428 secs]
[GC 6006K->5510K(7108K), 0.0013708 secs]
[GC 5819K->5602K(7108K), 0.0016069 secs]
[GC 5940K->5604K(7108K), 0.0007275 secs]
[GC 6116K->5607K(7108K), 0.0007294 secs]
[GC 6118K->5644K(7108K), 0.0020734 secs]
[Full GC 5850K->5654K(7108K), 0.0233583 secs]
[GC 5676K->5654K(10196K), 0.0002358 secs]
[Full GC 5654K->460K(10196K), 0.0228359 secs]
[GC 6284K->5606K(10196K), 0.0003883 secs]
[Full GC 6142K->5619K(10196K), 0.0328980 secs]
[GC 5639K->5620K(10196K), 0.0002173 secs]
[Full GC 5620K->454K(10196K), 0.0228797 secs]
[GC 6279K->5601K(10196K), 0.0004512 secs]
[Full GC 6135K->5648K(10196K), 0.0234963 secs]
[GC 5666K->5648K(10196K), 0.0002104 secs]
[Full GC 5648K->454K(10196K), 0.0328841 secs]
[GC 6274K->5601K(10196K), 0.0003517 secs]
[Full GC 6135K->5619K(10196K), 0.0401814 secs]
[GC 5637K->5620K(10196K), 0.0002282 secs]
[Full GC 5620K->454K(10196K), 0.0338029 secs]
[GC 6276K->5601K(10196K), 0.0003730 secs]
[Full GC 6134K->5648K(10196K), 0.0235197 secs]
[GC 5665K->5648K(10196K), 0.0002112 secs]
[Full GC 5648K->454K(10196K), 0.0232991 secs]
[GC 6275K->5601K(10196K), 0.0006495 secs]
[Full GC 6135K->5619K(10196K), 0.0410946 secs]
[GC 5637K->5620K(10196K), 0.0002313 secs]
[Full GC 5620K->454K(10196K), 0.0235823 secs]
[GC 6276K->5601K(10196K), 0.0003721 secs]
[Full GC 6143K->5648K(10196K), 0.0371251 secs]
[GC 5666K->5649K(10196K), 0.0002836 secs]
[Full GC 5649K->455K(10196K), 0.0232323 secs]
[GC 6278K->5602K(10196K), 0.0003699 secs]
[Full GC 6142K->5621K(10196K), 0.0310796 secs]
[GC 5638K->5621K(10196K), 0.0002299 secs]
[Full GC 5621K->456K(10196K), 0.0236888 secs]
[GC 6277K->5603K(10196K), 0.0005277 secs]
[Full GC 6137K->5649K(10196K), 0.0237972 secs]
[GC 5667K->5650K(10196K), 0.0002115 secs]
[Full GC 5650K->456K(10196K), 0.0231585 secs]
[GC 6276K->5603K(10196K), 0.0003615 secs]
[Full GC 6135K->5621K(10196K), 0.0310106 secs]
[GC 5638K->5621K(10196K), 0.0002330 secs]
[Full GC 5621K->456K(10196K), 0.0243056 secs]
[GC 6277K->5603K(10196K), 0.0003727 secs]
[Full GC 6137K->5649K(10196K), 0.0243352 secs]
[GC 5667K->5650K(10196K), 0.0002106 secs]
[Full GC 5650K->456K(10196K), 0.0239634 secs]
[GC 6276K->5603K(10196K), 0.0006238 secs]
[Full GC 6135K->5621K(10196K), 0.0313233 secs]
[GC 5638K->5621K(10196K), 0.0002310 secs]
[Full GC 5621K->456K(10196K), 0.0241263 secs]
[GC 6277K->5603K(10196K), 0.0003755 secs]
[Full GC 6136K->5649K(10196K), 0.0241584 secs]
[GC 5667K->5650K(10196K), 0.0002148 secs]
[Full GC 5650K->456K(10196K), 0.0233303 secs]
[GC 6276K->5603K(10196K), 0.0003743 secs]
[Full GC 6136K->5621K(10196K), 0.0304924 secs]
[GC 5638K->5621K(10196K), 0.0002355 secs]
[Full GC 5621K->456K(10196K), 0.0235848 secs]
[GC 6276K->5603K(10196K), 0.0005327 secs]
[Full GC 6136K->5649K(10196K), 0.0246543 secs]

-verbose:gc -Xmn16m

setGCDisabled(true) setGCDisabled(false)
[GC 10740K->455K(16192K), 0.0067553 secs]
[GC 13198K->455K(16192K), 0.0033887 secs]
[GC 13310K->455K(16192K), 0.0031920 secs]
[GC 13194K->455K(16192K), 0.0032965 secs]
[GC 13188K->456K(16192K), 0.0032487 secs]
[GC 13231K->456K(16192K), 0.0032934 secs]
[GC 13218K->456K(16192K), 0.0033169 secs]
[Full GC 10740K->5620K(16192K), 0.0376690 secs]
[Full GC 12104K->5625K(16192K), 0.0320728 secs]
[Full GC 12050K->5651K(16192K), 0.0320968 secs]
[Full GC 12031K->5619K(16192K), 0.0346910 secs]
[Full GC 11985K->5630K(16192K), 0.0324041 secs]
[Full GC 12034K->5639K(16192K), 0.0324170 secs]
[Full GC 12040K->5649K(16192K), 0.0326779 secs]
[Full GC 12043K->5621K(16192K), 0.0340462 secs]
[Full GC 11999K->5630K(16192K), 0.0329092 secs]
[Full GC 11992K->5635K(16192K), 0.0330936 secs]
[Full GC 12009K->5636K(16192K), 0.0325304 secs]
[Full GC 11999K->5621K(16192K), 0.0325377 secs]
[Full GC 11992K->5630K(16192K), 0.0431563 secs]
[Full GC 12000K->5638K(16192K), 0.0337579 secs]
[Full GC 12001K->5646K(16192K), 0.0353190 secs]

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

Apr 22, 2006

[Library] JExcelAPI にチャレンジ(4)

JEXCELAPI にチャレンジ(3)の続き。

シートの印刷サイズをセットする

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);


sheet.setPageSetup(PageOrientation.LANDSCAPE, PaperSize.B5, 10, 10);

シート印刷時のページ数を指定する

シートを印刷するときに指定したページ枚数にフィットするように拡大縮小させることができる。

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);

SheetSettings settings = sheet.getSettings();


settings.setFitHeight(1);
settings.setFitWidth(1);
settings.setFitToPages(true);

シートを保護する

以下の方法でシート編集時にパスワードを問い合わせるようにすることができる。

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);

SheetSettings settings = sheet.getSettings();


settings.setProtected(true);
settings.setPassword("mypassword");

ウィンドウ枠を固定する

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);

SheetSettings settings = sheet.getSettings();


settings.setHorizontalFreeze(1);
settings.setVerticalFreeze(2);

シート表示のズームをセットする

SheetSettings#setZoomFactor でズームを指定できる。 パラメータとして渡す数値はズームの %。 例えば、50 を指定すると 50% で表示される。

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);

SheetSettings settings = sheet.getSettings();


settings.setZoomFactor(75);

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

Apr 21, 2006

[Library] JExcelAPI にチャレンジ(3)

JEXCELAPI にチャレンジ(2)の続き。

文字を BOLD にする

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);

WritableCellFormat format = new WritableCellFormat();

WritableFont font = new WritableFont(format.getFont());
font.setBoldStyle(WritableFont.BOLD);

format.setFont(font);

Label label = new Label(0, 0, "hoge");
label.setCellFormat(format);
sheet.addCell(label);

文字をセンタリングする

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);

WritableCellFormat format = new WritableCellFormat();

format.setAlignment(Alignment.CENTRE);


Label label = new Label(0, 0, "hoge");
label.setCellFormat(format);
sheet.addCell(label);

罫線を引く

セル単位で罫線を引くことができる。 使用できる線種は以下の通り。

  • DASH_DOT
  • DASH_DOT_DOT
  • DASHED
  • DOTTED
  • DOUBLE
  • HAIR
  • MEDIUM
  • MEDIUM_DASH_DOT
  • MEDIUM_DASH_DOT_DOT
  • MEDIUM_DASHED
  • NONE
  • SLANTED_DASH_DOT
  • THICK
  • THIN
ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);

WritableCellFormat format = new WritableCellFormat();

format.setBorder(Border.ALL, BorderLineStyle.THIN);


Label label = new Label(0, 0, "hoge");
label.setCellFormat(format);
sheet.addCell(label);

セルの背景色をセットする

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);

WritableCellFormat format = new WritableCellFormat();

format.setBackground(Colour.LIGHT_ORANGE);


Label label = new Label(0, 0, "hoge");
label.setCellFormat(format);
sheet.addCell(label);

シートにヘッダをセットする

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);

SheetSettings settings = sheet.getSettings();


HeaderFooter header = new HeaderFooter();
header.getCentre().append("My Bookmarks");
settings.setHeader(header);

シートにフッタをセットする

フッタもヘッダと同じ方法でセットできる。

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);

SheetSettings settings = sheet.getSettings();


HeaderFooter footer = new HeaderFooter();
footer.getCentre().appendPageNumber();
footer.getCentre().append(" / ");
footer.getCentre().appendTotalPages();
settings.setFooter(footer);

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

Apr 20, 2006

[Library] JExcelAPI にチャレンジ(2)

JExcelAPI を実際に使用する可能性が出てきた。 というわけで、JExcelAPI で出来ることを簡単に調べてメモしておく。 JExcelAPI のバージョンは 2.5.9 を前提とする。

JExcelAPI にチャレンジ
http://www.in-vitro.jp/blog/index.cgi/Library/20051105_01.html
JExcelAPI のクラス図
http://www.in-vitro.jp/blog/index.cgi/Library/20051106_01.html

ブックを生成する

ブックは Workbook#createWorkbook(File) で簡単に生成できる。 Servlet から Stream で Web ブラウザに流すといった用途の場合は下記の様に一度オンメモリで生成する。

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

// ここで book を編集する。

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

OutputStream fos = null;
try {
    fos = new FileOutputStream(new File("c:\\mybook.xls"));
    fos.write(baos.toByteArray());
    fos.flush();
} finally {
    if (fos != null) {
        fos.close();
    }
}

シートを生成する

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);


WritableSheet sheet = book.createSheet("my sheet", 0);

カラムの幅を変更する

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);

sheet.setColumnView(0, 100);

セルに数値を書く

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);


Number number = new Number(0, 0, 999);
sheet.addCell(number);

セルに文字列を書く

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);


Label label = new Label(0, 0, "hoge");
sheet.addCell(label);

セルに式を書く

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);


Formula formula = new Formula(0, 0, "10 * 10");
sheet.addCell(formula);

セルにリンクを書く

WritableHyperlink を使用するとリンクを作成できる。 ただ、WritableHiperlink を使用したセルにフォーマット(罫線等)を指定する方法が見つからなかった。 仕方が無いので、関数を使用してリンクを作成してみた。

ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableWorkbook book = Workbook.createWorkbook(baos);

WritableSheet sheet = book.createSheet("my sheet", 0);


Formula formula = new Formula(0, 0, "HYPERLINK(\"http://www.google.com/\", \"Google\")");
sheet.addCell(formula);

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

Apr 18, 2006

[Library] JBoss jBPM Process Designer にチャレンジ(2)

JBoss jBPM Process Designer でプロセスを記述してみた。

Process Project の作成、設定など

まずはプロジェクト作成ウィザードを使用して "Process Project" を作成する。 "Process Project" を作成したら、次に "Process" を作成する。 作成された XML をエディタで開くと、プロセス定義をすることができる。

[Process Designer 01]
Process Project の作成
[Process Designer 02]
作成された Process Project
[Process Designer 03]
jBPM の設定
[Process Designer 04]
Process の作成

プロセスの記述

[Process Designer 05]
プロセスエディタ

プロセスエディタが生成した XML は↓

<?xml version="1.0" encoding="UTF-8"?>

<process-definition
  xmlns="http://jbpm.org/3/jpdl"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://jbpm.org/3/jpdl http://jbpm.org/xsd/jpdl-3.0.xsd"
  name="sample-process">
   <start-state name="start">
      <transition name="tr1" to="state1"></transition>
   </start-state>
   <end-state name="end1"></end-state>
   <state name="state1">
      <transition name="tr1" to="decision1"></transition>
   </state>
   <decision name="decision1">
      <transition name="tr1" to="state2"></transition>
      <transition name="tr2" to="state3"></transition>
   </decision>
   <state name="state2">
      <transition name="tr1" to="end1"></transition>
   </state>
   <state name="state3">
      <transition name="tr1" to="end1"></transition>
   </state>
</process-definition>

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

Apr 17, 2006

[Library] JBoss jBPM Process Designer にチャレンジ

JBoss jBPM Process Designer とは

JBoss jBPM Process Designer は、JBoss jBPM 用のプロセス定義ツール。 GUI でプロセスを定義することができるので便利。 JBoss 謹製で、Eclipse Plugin として提供されている。

JBoss jBPM Process Designer ドキュメント
http://docs.jboss.com/jbpm/v3/gpd/

JBoss jBPM Process Designer の実行環境構築

JBoss jBPM Process Designer は Eclipse Plugin なので、まず Eclipse を用意する。 ドキュメントによると

This release should work with all Eclipse 3.1 releases starting from M7.
ということなので、現時点(2006/04/17) で最新のプロダクトリリースである 3.1.2 を使用することにする。 JBoss jBPM Process Designer は最新の 3.0.4 を使用する。
  1. Eclipse 3.1.2 をここからダウンロードする
  2. Eclipse をインストールする。以降、インストール先ディレクトリを %ECLIPSE_HOME% と記述する。
  3. JBoss jBPM Process Designer Plugin 3.0.4 をここからダウンロードする
  4. JBoss jBPM Process Designer をインストールする。JBoss jBPM Process Designer のアーカイブ内の plugins, features をそれぞれ%ECLIPSE_HOME%/plugins, %ECLIPSE_HOME%/features にコピーする
  5. Eclipse 3.1.2 の起動確認を行う。
JBoss jBPM Process Designer のアーカイブには EMF や GEF、JEM などの Plugin も同梱されている。 EMF や GEF は Plugin も依存しているので、念のため Eclipse は JBoss jBPM Process Designer 専用のものを用意した。

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

Apr 16, 2006

[Library] JBoss jBPM + Hibernate + Derby 連携方法をメモ

JBoss jBPM は DBMS に情報を格納することができる。 この機能をお手軽に試すために Derby と連携させてみた。

jbpm.properties

クラスパスルートに jbpm.properties を作成する。

jbpm.hibernate.cfg.xml=hibernate.cfg.xml

hibernate.cfg.xml

クラスパスルートに hibernate.cfg.xml を作成する。

<?xml version="1.0" ?>

<!DOCTYPE hibernate-configuration PUBLIC 
    "-//Hibernate/Hibernate Configuration DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd" >

<hibernate-configuration>
  <session-factory>
    <property name="connection.driver_class">
      org.apache.derby.jdbc.EmbeddedDriver
    </property>
    <property name="connection.url">jdbc:derby:derbyDB</property>
    <property name="dialect">
      org.hibernate.dialect.DerbyDialect
    </property>
    <property name="show_sql">true</property>
    <property name="use_outer_join">true</property>
    <mapping resource="DummyEntity.hbm.xml" />
  </session-factory>
</hibernate-configuration>

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

Apr 15, 2006

[Library] JBoss jBPM にチャレンジ

先日調べたワークフローエンジンの中から JBoss jBPM を試してみた。

JBoss jBPM
http://labs.jboss.com/portal/index.html?ctrl:id=page.default.info&project=jbossjbpm

JBoss jBPM の環境構築

JBoss jBPM 3.0.1 の実行環境構築方法は以下の通り。

  1. クラスパスのルートに jbpm.properties を設置する。
    • antlr-2.7.5H3.jar
    • asm-attrs.jar
    • asm.jar
    • bsh-2.0b2.jar
    • cglib-2.1.jar
    • commons-collections-2.1.1.jar
    • commons-logging-1.0.4.jar
    • converter.jar
    • dom4j-1.6.jar
    • ehcache-1.1.jar
    • hibernate3.jar
    • jaxen-1.1-beta-4.jar
    • jbpm-3.0.1.jar
    • jbpm-identity-3.0.1.jar
    • jdbc2_0-stdext.jar
    • jta.jar
  2. クラスパスに以下の jar を追加する。

jbpm.properties は JbpmConfiguration が自動的に読み込む。 jbpmConfiguration が jbpm.properties を探すサーチパスは
  1. クラスパス内の /jbpm.properties
  2. クラスパス内の /org/jbpm/jbpm.properties
となっている。 そのため、クラスパスルートに jbpm.properties を置いておくと JBoss jBPM の設定を変更できる。

とっかかり

とりあえずこの辺りを読めばとりあえず使えるというドキュメントをメモ。

チュートリアル
http://docs.jboss.com/jbpm/v3/userguide/tutorial.html
Graph Oriented Programming
http://docs.jboss.com/jbpm/v3/userguide/graphorientedprogramming.html
jPDL xml schema
http://docs.jboss.com/jbpm/v3/userguide/jpdl.html#d0e4520
Expressions
http://docs.jboss.com/jbpm/v3/userguide/jpdl.html#expressions
Expression Language
http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JSPIntro7.html
Script
http://docs.jboss.com/jbpm/v3/userguide/processmodelling.html#script
beanshell
http://www.beanshell.org/

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

Apr 13, 2006

[Library] Java で利用可能なワークフローエンジンをメモ

Google 先生に教えてもらったワークフローエンジンをメモ。 Java 用の API が存在する(と思われる)もののみ。

オープンソース製品

ActiveBPEL (ActiveBPEL, LLC., GPL/Commercial License)
http://www.activebpel.org/
Bonita (ECOO Team., LGPL)
http://bonita.objectweb.org/
con:cern
http://con-cern.org/
Dalma
https://dalma.dev.java.net/nonav/maven/index.html
Enhydra Workflow Platform (Together Teamlösungen, LGPL 2.1)
http://www.enhydra.org/workflow/
Enhydra JaWE
http://www.enhydra.org/workflow/jawe/index.html
Enhydra Shark
http://www.enhydra.org/workflow/shark/index.html
Freefluo
http://freefluo.sourceforge.net/
JBoss jBPM
http://labs.jboss.com/portal/index.html?ctrl:id=page.default.info&project=jbossjbpm
JFlower (?, GPL)
http://sourceforge.net/projects/jflower/
Nautica Worklfow (アルゴ21 研究開発センター, LGPL 2.1)
http://nautica.sourceforge.jp/main.html
OpenWFE (?, BSD License)
http://web.openwfe.org/display/openwfe/Home
OSWorkflow (OpenSymphony, The OpenSymphony Software License, Version 1.1)
http://www.opensymphony.com/osworkflow/
S2Buri (まこたん, ASL 2.0)
http://s2buri.sandbox.seasar.org/
Taverna (?, LGPL)
http://taverna.sourceforge.net/
Twister (?, LGPL)
http://www.smartcomps.org/twister/
XFLOW (Rob Tan, ?)
http://xflow.sourceforge.net/
werkflow
http://sourceforge.net/projects/werkflow/

商用製品

j-Flow (関西日本電気)
http://www.scs.co.jp/product/gaiyo/jflow.html
Flux Workflow (Flux Corporation.)
http://www.fluxcorp.com/workflow/
Global Flow (Panasonic Solution Technologies Co.)
http://panasonic.co.jp/pss/pstc/products/gf/flow/index.html
Green Office Workflow (京セラコミュニケーションシステム株式会社)
http://www.kccs.co.jp/products/workflow/index.html
Groupmax (日立)
http://www.hitachi.co.jp/Prod/comp/soft1/groupmax/
MajorFlow (松下ネットソリューションズ株式会社)
http://www.mnes.co.jp/Home/products.nsf/ContentsByKey/MajorFlow_Top
MELDandy (三菱電機情報ネットワーク株式会社)
http://www.mind.co.jp/service/application/appli_package/meldandy/index.html
OptimalFlow (株式会社NTTデータビジネスブレインズ)
http://www.nttd-bb.com/solution/total/solution4/index.html
WebLogic Integration (BEA Systems, Inc.)
http://www.beasys.co.jp/products/weblogic/integration/index.html

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

Apr 03, 2006

[Library] NGramJ にチャレンジ

NGramJ とは

NGramJ は、Natural Language Processing(NLP)用のライブラリ。 与えられたバイト配列の言語、文字エンコーディングを判別してくれる。 たとえば、"竹やぶに竹立てかけた。"という文字列を Shift_JIS のバイト配列で NGramJ に引き渡すと、「Shift_JIS の日本語」であることを判断してくれる。

NGramJ
http://ngramj.sourceforge.net/index.html
API Document
http://ngramj.sourceforge.net/javadoc/index.html

NGramJ の実行環境構築

  1. こちらから NGramJ をダウンロードする。ここでは ver.1.0-0.060327 を前提とする。
  2. アーカイブの中にある以下の ngramj.jar をクラスパスに追加する。

サンプルコード

とりあえず日本語と英語の判別を試してみた。

package jp.in_vitro.codelets.ngramj;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;

import de.spieleck.app.ngramj.Categorizer;
import de.spieleck.app.ngramj.EntryProfile;
import de.spieleck.app.ngramj.Profile;
import de.spieleck.app.ngramj.lm.CategorizerImpl;

public class Codelet {

    public Codelet() {
        super();
    }

    public static void main(final String[] args) throws IOException {
        Codelet me = new Codelet();
        me.execute01();
        me.execute02();
        me.execute03();
        me.execute04();
    }

    protected void execute01() throws IOException {
        String target = "竹やぶに竹立てかけた。";
        InputStream is = new ByteArrayInputStream(target
                .getBytes("Shift_JIS"));
        Profile profile = this.match(is);
        
        Logger.global.info("" + target + " -> " + profile);
    }

    protected void execute02() throws IOException {
        String target = "竹やぶに竹立てかけた。";
        InputStream is = new ByteArrayInputStream(target
                .getBytes("EUC-JP"));
        Profile profile = this.match(is);
        
        Logger.global.info("" + target + " -> " + profile);
    }

    protected void execute03() throws IOException {
        String target = "竹やぶに竹立てかけた。";
        InputStream is = new ByteArrayInputStream(target
                .getBytes("UTF-8"));
        Profile profile = this.match(is);
        
        Logger.global.info("" + target + " -> " + profile);
    }

    protected void execute04() throws IOException {
        String target = "This is a pen. Who cares?";
        InputStream is = new ByteArrayInputStream(target
                .getBytes("ISO-8859-1"));
        Profile profile = this.match(is);
        
        Logger.global.info("" + target + " -> " + profile);
    }


    protected Profile match(final InputStream is) throws IOException {

        Categorizer categorizer = new CategorizerImpl();
        EntryProfile entryProfile = new EntryProfile(is);
        Profile profile = categorizer.match(entryProfile);

        return profile;
    }
}

実行結果

日本語の UTF-8 は判別できなかった。調べてみると標準で用意されている日本語プロファイルは Shift_JIS と EUC-JP だけだった。 Shift_JIS、EUC-JP 以外の文字エンコーディングを使用する場合は、自分でプロファイルを作成する必要がある。

2006/04/03 2:05:59 jp.in_vitro.codelets.ngramj.Codelet execute01
情報: 竹やぶに竹立てかけた。 -> japanese-shift_jis.lm
2006/04/03 2:05:59 jp.in_vitro.codelets.ngramj.Codelet execute02
情報: 竹やぶに竹立てかけた。 -> japanese-euc_jp.lm
2006/04/03 2:06:00 jp.in_vitro.codelets.ngramj.Codelet execute03
情報: 竹やぶに竹立てかけた。 -> armenian.lm
2006/04/03 2:06:00 jp.in_vitro.codelets.ngramj.Codelet execute04
情報: This is a pen. Who cares? -> english.lm

標準提供されるプロファイル

今回使用したバージョンでは下記のプロファイルが添付されていた。 実際に使用するのであれば、日本語関連で文字エンコーディングをいくつか追加する必要がありそう。

afrikaans.lm
albanian.lm
amharic-utf.lm
arabic-iso8859_6.lm
arabic-windows1256.lm
armenian.lm
basque.lm
belarus-windows1251.lm
bosnian.lm
breton.lm
bulgarian-iso8859_5.lm
catalan.lm
chinese-big5.lm
chinese-gb2312.lm
croatian-ascii.lm
czech-iso8859_2.lm
danish.lm
dutch.lm
english.lm
esperanto.lm
estonian.lm
finnish.lm
french.lm
frisian.lm
georgian.lm
german.lm
greek-iso8859-7.lm
hawaian.lm
hebrew-iso8859_8.lm
hindi.lm
hungarian.lm
icelandic.lm
indonesian.lm
irish.lm
italian.lm
japanese-euc_jp.lm
japanese-shift_jis.lm
korean.lm
latin.lm
latvian.lm
lithuanian.lm
malay.lm
manx.lm
marathi.lm
middle_frisian.lm
mingo.lm
nepali.lm
norwegian.lm
persian.lm
polish.lm
portuguese.lm
quechua.lm
romanian.lm
rumantsch.lm
russian-iso8859_5.lm
russian-koi8_r.lm
russian-windows1251.lm
sanskrit.lm
scots.lm
scots_gaelic.lm
serbian-ascii.lm
slovak-ascii.lm
slovak-windows1250.lm
slovenian-ascii.lm
slovenian-iso8859_2.lm
spanish.lm
swahili.lm
swedish.lm
tagalog.lm
tamil.lm
thai.lm
turkish.lm
ukrainian-koi8_r.lm
vietnamese.lm
welsh.lm
yiddish-utf.lm

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

Mar 26, 2006

[Library] MockObjects

MockObjects とは

MockObjects は、Javaのテスト用ライブラリで様々なモックの詰め合わせ。 単体テストを真面目に行おうとすると、とかくモックだの何だのが必要になるのでこれがあると便利。 類似のライブラリには SpringFrameworkPackage org.springframework.mock.webPackage org.springframework.mock.jndi がある。

MockObjects
http://www.mockobjects.com/FrontPage.html
http://www.mockobjects.com/ (2007.05.23 変更)
API Document
http://mockobjects.sourceforge.net/javadoc/1.4/
Using Mock Objects in Java
http://javaboutique.internet.com/tutorials/mock_objects/
MockObjects ってなに?
http://genjo9.lit.let.hokudai.ac.jp/keita/read.cgi?MockObjects

MockObjects が提供するモック

  • com.mockobjects.beans
    • MockPropertyChangeListener
  • com.mockobjects.io
    • MockFile
    • MockFileInputStream
    • MockIOFactory
    • MockOutputStream
    • MockPrintStream
    • MockPrintWriter
    • MockWriter
  • com.mockobjects.jms
    • MockConnection
    • MockMapMessage
    • MockMessage
    • MockMessageConsumer
    • MockMessageProducer
    • MockMessagePublisher
    • MockObjectMessage
    • MockQueue
    • MockQueueConnection
    • MockQueueConnectionFactory
    • MockQueueReceiver
    • MockQueueSender
    • MockQueueSession
    • MockSession
    • MockTemporaryQueue
    • MockTextMessage
    • MockTopic
    • MockTopicConnection
    • MockTopicConnectionFactory
    • MockTopicPublisher
    • MockTopicSession
    • MockTopicSubscriber
  • com.mockobjects.mail
    • MockMessage
    • MockService
    • MockSession
    • MockTransport
  • com.mockobjects.mail.internet
    • MockMimeMessage
    • MockMimeMessageFactory
  • com.mockobjects.naming
    • MockContext
  • com.mockobjects.naming.directory
    • MockAttribute
    • MockAttributes
    • MockDirContext
    • MockNamingEnumeration
  • com.mockobjects.net
    • MockSocket
    • MockSocketFactory
  • com.mockobjects.rmi
    • MockNaming
  • com.mockobjects.servlet
    • MockBodyContent
    • MockFilterChain
    • MockFilterConfig
    • MockHttpServletRequest
    • MockHttpServletResponse
    • MockHttpSession
    • MockJspWriter
    • MockPageContext
    • MockRequestDispatcher
    • MockServletConfig
    • MockServletContext
    • MockServletInputStream
    • MockServletOutputStream
  • com.mockobjects.sql
    • MockArray
    • MockConnection
    • MockConnection2
    • MockDatabaseMetaData
    • MockDataSource
    • MockDriver
    • MockMultiRowResultSet
    • MockPreparedStatement
    • MockResultSetMetaData
    • MockSingleRowResultSet
    • MockStatement

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

Mar 17, 2006

[Library] Smack にチャレンジ

Smack とは

Smack は Java 用の Jabber ライブラリ。 Google Talk 用の API が用意されているのが嬉しい。

Smack
http://www.jivesoftware.org/smack/

Smack の実行環境構築

  1. こちらから Smack をダウンロードする。ここでは ver.2.2.0 を前提とする。
  2. アーカイブの中にある以下の jar をクラスパスに追加する
    • smack.jar
    • smackx.jar

サンプルコード

Smack を使用して Google Talk のアカウントに IM のメッセージを送信してみた。 Smack はGoogle Talk 用のインターフェースを提供してくれているので非常に簡単。

package jp.in_vitro.codelets.smack;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.GoogleTalkConnection;
import org.jivesoftware.smack.XMPPException;

public class Codelet {

    public Codelet() {
        super();
    }

    public static void main(final String[] args) throws XMPPException {
        Codelet me = new Codelet();
        me.execute();
    }

    protected void execute() throws XMPPException {
        GoogleTalkConnection con = new GoogleTalkConnection();
        con.login("[MY ID]", "[PASSWORD]");
        Chat chat = con.createChat("[MY FRIEND ID]@gmail.com");
        chat.sendMessage("ASCII");
        chat.sendMessage("ひらがな");
        chat.sendMessage("漢字");
        chat.sendMessage("ハンカクカタカナ");
    }
}
[メッセージを受信したところ]

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

Mar 16, 2006

[Library] XMPP/Jabber メモ

XMPP/Jabber に関する情報をメモ。

Jabber Software Foundation
http://www.jabber.org/
Jabber Protocols
http://www.jabber.org/protocol/
<xmpp/>.org
http://www.xmpp.org/
XMPP Specs
http://www.xmpp.org/specs/
History of XMPP
http://www.xmpp.org/history.html
Summary of XMPP
http://www.xmpp.org/summary.html

Java の Jabber ライブラリ

Code Libraries に掲載されているものの内、Java から利用可能なものをリストアップしてみた。

Echomine Muse
http://open.echomine.org/confluence/display/MUSE/
JabberBeans
http://jabberbeans.jabberstudio.org/
JabberWookie
http://www.jabberwookie.com/
JSO
http://jso.jabberstudio.org/
micro-jabber
http://sourceforge.net/projects/micro-jabber
Smack
http://www.jivesoftware.org/smack/
tweeze
http://www.ipster.org/tweeze/
Yaja
http://yaja.sourceforge.net/

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

Mar 15, 2006

[Library] iText にチャレンジ(3)

日本語フォントを利用した PDF を作成してみた。 日本語フォントを読み込めたのでかなり期待していたが、期待通り簡単に日本語を扱うことができた。

サンプルコード

package jp.in_vitro.codelets.itext;

import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfWriter;

public class Codelet2 {

    public Codelet2() {
        super();
    }

    public static void main(final String[] args) throws DocumentException,
            IOException {
        Codelet2 me = new Codelet2();
        me.createPDF();
    }

    protected void createPDF() throws DocumentException, IOException {

        BaseFont baseFont = BaseFont.createFont(
                "c:\\windows\\fonts\\msgothic.ttc,1", BaseFont.IDENTITY_H,
                BaseFont.EMBEDDED);
        Font font = new Font(baseFont, 12);

        Document document = new Document();
        PdfWriter.getInstance(document, new FileOutputStream(
                "c:\\Japanese.pdf"));

        document.open();
        String text1 = "こんにちは";
        document.add(new Paragraph(text1, font));
        document.close();
    }
}
[作成された PDF]

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

Mar 14, 2006

[Library] iText にチャレンジ(2)

今日は日本語フォントの取り扱いにチャレンジ。

サンプルコード

日本語フォントを読み込んで情報を表示してみた。 チュートリアルに記載されている通りのコードで簡単に動作した。 とりあえず MS P ゴシックを読み込んでみた。

package jp.in_vitro.codelets.itext;

import java.io.IOException;

import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.BaseFont;

public class Codelet1 {

    public Codelet1() {
        super();
    }

    public static void main(final String[] args) throws DocumentException,
            IOException {
        Codelet1 me = new Codelet1();
        me.viewFontInfo();
    }

    protected void viewFontInfo() throws IOException, DocumentException {
        BaseFont baseFont = BaseFont.createFont(
                "c:\\windows\\fonts\\msgothic.ttc,1", BaseFont.IDENTITY_H,
                BaseFont.EMBEDDED);

        System.out.println("[Postscript Font Name] "
                + baseFont.getPostscriptFontName());
        System.out.println("[Direct Text to Byte] "
                + baseFont.isDirectTextToByte());
        System.out.println("[Embedded] " + baseFont.isEmbedded());
        System.out.println("[Font Specific] " + baseFont.isFontSpecific());
        System.out.println("[Force Widths Output] "
                + baseFont.isForceWidthsOutput());
        System.out.println("[Subset] " + baseFont.isSubset());
        System.out.println("[Code Pages Supported]");
        for (String codePage : baseFont.getCodePagesSupported()) {
            System.out.println("  " + codePage);
        }
        System.out.println("[Full Font Name]");
        for (String[] tmp : baseFont.getFullFontName()) {
            System.out.print("  ");
            for (String defference : tmp) {
                System.out.print(defference + ", ");
            }
            System.out.println();
        }
    }
}

実行結果

[Postscript Font Name] MS-PGothic
[Direct Text to Byte] false
[Embedded] true
[Font Specific] false
[Force Widths Output] false
[Subset] true
[Code Pages Supported]
  1252 Latin 1
  1250 Latin 2: Eastern Europe
  1251 Cyrillic
  1253 Greek
  1254 Turkish
  1257 Windows Baltic
  932 JIS/Japan
  OEM Character Set
  869 IBM Greek
  866 MS-DOS Russian
  865 MS-DOS Nordic
  863 MS-DOS Canadian French
  861 MS-DOS Icelandic
  860 MS-DOS Portuguese
  857 IBM Turkish
  855 IBM Cyrillic; primarily Russian
  852 Latin 2
  775 MS-DOS Baltic
  737 Greek; former 437 G
  850 WE/Latin 1
  437 US
[Full Font Name]
  1, 0, 0, MS PGothic, 
  3, 1, 1033, MS PGothic, 
  3, 1, 1041, MS Pゴシック, 

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

Mar 13, 2006

[Library] iText にチャレンジ

iText とは

iText は Java から PDF を扱うライブラリ。 ライセンスは MPLLGPL のデュアルライセンス。

iText
http://www.lowagie.com/iText/
API Document
http://itextdocs.lowagie.com/docs/
Tutorial: iText by Example
http://itext.sourceforge.net/tutorial/

サンプルコード

とりあえずお決まりの Hello World。

package jp.in_vitro.codelets.itext;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

public class Codelet {

    public Codelet() {
        super();
    }

    public static void main(final String[] args) throws FileNotFoundException,
            DocumentException {
        Codelet me = new Codelet();
        me.execute();
    }

    protected void execute() throws FileNotFoundException, DocumentException {
        Document document = new Document();
        PdfWriter.getInstance(document, new FileOutputStream("c:\\HelloWorld.pdf"));
        document.open();
        document.add(new Paragraph("Hello World"));
        document.close();
    }
}
[作成された PDF]

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

Feb 21, 2006

[Library] Struts 1.3 メモ

オレンジニュース さんの Apaxhe Struts 1.3.0 リリース で Struts 1.3 のリリースを知った。 結構たくさんアーカイブがあったので、とりあえず中身をざっと眺めてみた。

Struts ダウンロードサイト
http://svn.apache.org/dist/struts/

アーカイブの概要

各アーカイブの docs/index.html の内容をリスト化しておく。

struts-action
Struts Action Framework is a flexible control layer based on standard technologies like Java Servlets, JavaBeans, ResourceBundles, and XML, as well as various Jakarta Commons packages, like BeanUtils and Chain of Responsibility. Struts Action Framework helps you create an extensible development environment for your application, based on published standards and proven design patterns.
struts-el
This subproject is an extension of the Struts tag library. Each JSP custom tag in this library is a subclass of an associated tag in the Struts tag library.
struts-extras
The purpose of this subproject is to provide a separate and common location to provide optional but often useful extension classes to Struts Action Framework.
struts-taglib
This library simplifies development of a JSP-based view layer of a Struts Action Framework Application. These tags were previously packaged as part of the base Struts 1.2 distribution, but have been extracted into a separate library.
struts-tiles
Tiles is a templating framework. It can be used to create a common look & feel for a web site or application and to create reusable view components.

アーカイブの中身

action-library_1.3_00.zip

action-library_1.3_00
│  struts-config_1_3.dtd
│  web-app_2_3.dtd
└─action-library_1.3.0
        antlr-2.7.2.jar
        cactus-12-1.4.1.jar
        cactus-ant-1.4.1.jar
        commons-beanutils-1.7.0.jar
        commons-chain-1.0.jar
        commons-digester-1.6.jar
        commons-fileupload-1.1.jar
        commons-io-1.1.jar
        commons-logging-1.0.4.jar
        commons-validator-1.2.0.jar
        httpunit-1.5.4.jar
        junit-3.8.1.jar
        oro-2.0.8.jar
        struts-action-1.3.0.jar
        struts-el-1.3.0.jar
        struts-extras-1.3.0.jar
        struts-mailreader-dao-1.3.0.jar
        struts-taglib-1.3.0.jar
        struts-tiles-1.3.0.jar

struts-action-1.3.0.tar.gz

struts-action-1.3.0
│  struts-action-1.3.0.jar
├─conf
│      chain-config.xml
│      struts-config_1_0.dtd
│      struts-config_1_1.dtd
│      struts-config_1_2.dtd
│      struts-config_1_3.dtd
│      validator-rules.xml
│      web-app_2_2.dtd
│      web-app_2_3.dtd
└─docs
    ├─apidocs
    ├─faqs
    ├─images
    ├─jcoverage
    ├─style
    ├─userGuide
    ├─xref
    └─xref-test

struts-action-1.3.0-src.tar.gz

struts-action-1.3.0
│  build.xml
│  maven.xml
│  project.xml
├─build
│      maven.xml
│      pom.xml
│      project.properties
│      project.xml
│      struts.jsl
│      struts_checks.xml
│      struts_jalopy.xml
├─conf
│  └─java
│          chain-config.xml
│          struts-config_1_0.dtd
│          struts-config_1_1.dtd
│          struts-config_1_2.dtd
│          struts-config_1_3.dtd
│          validator-rules.xml
│          web-app_2_2.dtd
│          web-app_2_3.dtd
└─src
    ├─java
    ├─java
    │  └─org
    │      └─apache
    │          └─struts
    │              ├─action
    │              ├─chain
    │              │  ├─commands
    │              │  │  ├─generic
    │              │  │  ├─servlet
    │              │  │  └─util
    │              │  └─contexts
    │              ├─config
    │              │  └─impl
    │              ├─mock
    │              ├─upload
    │              ├─util
    │              └─validator
    │                  └─validwhen
    └─test

struts-el-1.3.0

struts-el-1.3.0
│  struts-el-1.3.0.jar
└─docs
    ├─apidocs
    ├─images
    ├─jcoverage
    ├─style
    ├─tlddoc
    ├─xref
    └─xref-test

struts-el-1.3.0-src.tar.gz

struts-el-1.3.0
│  build.xml
│  maven.xml
│  project.properties
│  project.xml
├─build
│      maven.xml
│      pom.xml
│      project.properties
│      project.xml
│      struts.jsl
│      struts_checks.xml
│      struts_jalopy.xml
└─src
    ├─exercise-taglib
    ├─java
    │  └─org
    │      └─apache
    │          └─strutsel
    │              └─taglib
    │                  ├─bean
    │                  ├─html
    │                  ├─logic
    │                  ├─tiles
    │                  └─utils
    ├─test
    └─tld
            struts-bean-el.tld
            struts-html-el.tld
            struts-logic-el.tld
            struts-tiles-el.tld

struts-extras-1.3.0.tar.gz

struts-extras-1.3.0
│  struts-extras-1.3.0.jar
└─docs
    ├─apidocs
    ├─images
    ├─jcoverage
    ├─style
    ├─xref
    └─xref-test

struts-extras-1.3.0-src.tar.gz

struts-extras-1.3.0
│  build.xml
│  project.properties
│  project.xml
├─build
│      maven.xml
│      pom.xml
│      project.properties
│      project.xml
│      struts.jsl
│      struts_checks.xml
│      struts_jalopy.xml
└─src
    ├─conf
    ├─java
    │  └─org
    │      └─apache
    │          └─struts
    │              ├─actions
    │              ├─plugins
    │              └─validator
    └─test

struts-site-1.3.0.tar.gz

struts-site-1.3.0
│  struts-site-1.3.0.jar
└─docs
    ├─images
    ├─legacy
    ├─proposals
    ├─struts-doc-1.0.2
    ├─struts-doc-1.1
    ├─style
    ├─stylesheets
    └─uml

struts-site-1.3.0-src.tar.gz

struts-site-1.3.0
│  maven.xml
│  project.properties
│  project.xml
└─build
        maven.xml
        pom.xml
        project.properties
        project.xml
        struts.jsl
        struts_checks.xml
        struts_jalopy.xml

struts-taglib-1.3.0

struts-taglib-1.3.0
│  struts-taglib-1.3.0.jar
└─docs
    ├─apidocs
    ├─images
    ├─jcoverage
    ├─style
    ├─tlddoc
    ├─xref
    └─xref-test

struts-taglib-1.3.0-src.tar.gz

struts-taglib-1.3.0
│  build.xml
│  maven.xml
│  project.properties
│  project.xml
├─build
│      maven.xml
│      pom.xml
│      project.properties
│      project.xml
│      struts.jsl
│      struts_checks.xml
│      struts_jalopy.xml
└─src
    ├─conf
    ├─java
    │  └─org
    │      └─apache
    │          └─struts
    │              └─taglib
    │                  ├─bean
    │                  ├─html
    │                  ├─logic
    │                  └─nested
    │                      ├─bean
    │                      ├─html
    │                      └─logic
    ├─test
    ├─test-cactus
    ├─tld
    └─webapp

struts-tiles-1.3.0.tar.gz

struts-tiles-1.3.0
│  struts-tiles-1.3.0.jar
└─docs
    ├─apidocs
    ├─images
    ├─jcoverage
    ├─style
    ├─tlddoc
    ├─xref
    └─xref-test

struts-tiles-1.3.0-src.tar.gz

struts-tiles-1.3.0
│  build.xml
│  maven.xml
│  project.properties
│  project.xml
├─build
│      maven.xml
│      pom.xml
│      project.properties
│      project.xml
│      struts.jsl
│      struts_checks.xml
│      struts_jalopy.xml
└─src
    ├─java
    │  └─org
    │      └─apache
    │          └─struts
    │              └─tiles
    │                  ├─actions
    │                  ├─beans
    │                  ├─commands
    │                  ├─definition
    │                  ├─taglib
    │                  │  └─util
    │                  └─xmlDefinition
    ├─resource
    │  └─org
    │      └─apache
    │          └─struts
    │              ├─resources
    │              │      tiles-config_1_1.dtd
    │              │      tiles-config_1_3.dtd
    │              └─tiles
    │                      chain-config.xml
    ├─test
    └─tld
            struts-tiles.tld

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

Feb 19, 2006

[Library] JUnit 4.0 にチャレンジ

今日は JUnit 4.0 をもう少し細かく掘り下げてみる。 ざっとソースコードを眺めてみた。

JUnitCore

JUnit 4 のテストケースを自分で実行する場合、JUnitCore を使うのが一番楽だと思う。 JUnitCore は Request や Runner を作成してテストケースを実行してくれる。
[JUnitCore周辺のクラス図]

Runner

細かい作業が必要で JUnitCore が使えない場合は Runner を自分で制御する必要がある。 そういう状況は余り無いと思うけれど。
[Runnerとサブクラス]

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

Feb 18, 2006

[Library] JUnit 4.0 にチャレンジ

長らく 3.x の時代が続いていた JUnit だけれど、遂に 4.0 がリリースされた。 というわけで、とりあえず軽く触ってみた。 4.0 がリリースされたというニュースが出ているのだが、2006/02/18 現在公式サイトには情報がなかった。 ダウンロードも 3.8.1 が最新のママ。 公式サイトで 4.0 が見つからない場合は、↓のダウンロードサイトをチェックすると良い。

JUnit 公式サイト
http://junit.org/index.htm
JUnit ダウンロードサイト
http://prdownloads.sourceforge.net/junit/
@Test でユニットテスト - 新生 JUnit 4.0 公開
http://pcweb.mycom.co.jp/news/2006/02/16/347.html

JUnit 4 の Annotation

JUnit 3 → 4 の大きな変更は Annotation の導入らしい。 というわけで、JUnit 4 で用意されている Annnotation をリストアップしてみた。

@After
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface After {
}
@AfterClass
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterClass {
}
@Before
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Before {
}
@BeforeClass
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface BeforeClass {
}
@Ignore
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Ignore {
  /**
   * The optional reason why the test is ignored.
   */
  String value() default ""; 
}
@Test
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test {
  static class None extends Throwable {
    private static final long serialVersionUID= 1L;    
    private None() {
    }
  }
  /**
   * Optionally specify <code>expected</code>, a Throwable, to cause a test method to succeed iff 
   * an exception of the specified class is thrown by the method.
   */
  Class<? extends Throwable> expected() default None.class;
  /** 
   * Optionally specify <code>timeout</code> in milliseconds to cause a test method to fail if it
   * takes longer than that number of milliseconds.*/
  long timeout() default 0L; 
}
Annotation の実行タイミング

↑に挙げた Annotation は全て Target が METHOD になっている。 これら Annotation が指定されたメソッドの実行タイミングは以下の通り。

package jp.in_vitro.codelets.junit4;

import java.util.logging.Logger;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.JUnitCore;

public class Codelet {

    public static void main(String[] args) {
        JUnitCore.runClasses(new Class[] { Codelet.class });
    }

    @BeforeClass
    public static void beforeClass() {
        Logger.global.info("beforeClass");
    }

    @Before
    public void before() {
        Logger.global.info("before");
    }

    @Test
    public void mytest01() {
        Logger.global.info("mytest01");
    }

    @Test
    public void mytest02() {
        Logger.global.info("mytest02");
    }

    @Test @Ignore
    public void mytest03() {
        Logger.global.info("mytest03");
    }

    @After
    public void after() {
        Logger.global.info("after");
    }

    @AfterClass
    public static void afterClass() {
        Logger.global.info("afterClass");
    }

}
2006/02/18 17:24:32 jp.in_vitro.codelets.junit4.Codelet beforeClass
情報: beforeClass
2006/02/18 17:24:32 jp.in_vitro.codelets.junit4.Codelet before
情報: before
2006/02/18 17:24:32 jp.in_vitro.codelets.junit4.Codelet mytest01
情報: mytest01
2006/02/18 17:24:32 jp.in_vitro.codelets.junit4.Codelet after
情報: after
2006/02/18 17:24:32 jp.in_vitro.codelets.junit4.Codelet before
情報: before
2006/02/18 17:24:32 jp.in_vitro.codelets.junit4.Codelet mytest02
情報: mytest02
2006/02/18 17:24:32 jp.in_vitro.codelets.junit4.Codelet after
情報: after
2006/02/18 17:24:32 jp.in_vitro.codelets.junit4.Codelet afterClass
情報: afterClass

Assert

JUnit 4 ではテストケースが TestCase クラスを継承する必要は無くなった。 そのため、assert* メソッドは Assert クラスで定義されているものを使用する。 Assert クラスには↓のメソッドが用意されている。 これくらいの数なら static import を使っても良さそう。

static public void assertTrue(String message, boolean condition)
static public void assertTrue(boolean condition)
static public void assertFalse(String message, boolean condition)
static public void assertFalse(boolean condition)
static public void fail(String message)
static public void fail()
static public void assertEquals(String message, Object expected, Object actual)
static public void assertEquals(Object expected, Object actual)
public static void assertEquals(String message, Object[] expecteds, Object[] actuals)
public static void assertEquals(Object[] expecteds, Object[] actuals)
static public void assertEquals(String message, double expected, double actual, double delta)
static public void assertEquals(double expected, double actual, double delta)
static public void assertEquals(String message, float expected, float actual, float delta)
static public void assertEquals(float expected, float actual, float delta)
static public void assertNotNull(String message, Object object)
static public void assertNotNull(Object object)
static public void assertNull(String message, Object object)
static public void assertNull(Object object)
static public void assertSame(String message, Object expected, Object actual)
static public void assertSame(Object expected, Object actual)
static public void assertNotSame(String message, Object expected, Object actual)
static public void assertNotSame(Object expected, Object actual)

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

Feb 14, 2006

[Library] Jetty にチャレンジ

Jetty とは

Jetty はオープンソースの Servlet Engine。 Tomcat と同カテゴリのソフトウェア。 Servlet Engine なので当然 Servlet をディプロイすることも可能なのだけれど、 今回は Jetty そのものをアプリケーション内に取り込んでみる。 Servlet を登録するよりもコーディングは面倒になるが、色々融通が利くようになる。

Jetty 公式サイト
http://jetty.mortbay.org/jetty/index.html

Jetty の初期化 & 起動

まずは Jetty を初期化する。今回使用している Jetty のバージョンは 6.0 beta8。

InputStream is = null;
Server server = null;
try {
  is = this.getClass().getResourceAsStream("/jetty.xml");
  XmlConfiguration configuration = new XmlConfiguration(is);
  Object obj = configuration.newInstance();
  server = (Server) obj;
} finally {
  if (is != null) {
    is.close();
  }
}

MyHandler myHandler = new MyHandler();
server.setHandler(myContextHandler);
server.start();
jetty.xml はこんな↓感じ。
<?xml version="1.0"?>

<!DOCTYPE Configure PUBLIC 
          "-//Mort Bay Consulting//DTD Configure//EN" 
          "http://jetty.mortbay.org/configure.dtd">

<Configure id="Server" class="org.mortbay.jetty.Server">
    <Set name="ThreadPool">
      <New class="org.mortbay.thread.BoundedThreadPool">
        <Set name="minThreads">10</Set>
        <Set name="maxThreads">100</Set>
      </New>
    </Set>
    <Set name="connectors">
      <Array type="org.mortbay.jetty.Connector">
        <Item>
          <New class="org.mortbay.jetty.nio.SelectChannelConnector">
            <Set name="port">80</Set>
            <Set name="maxIdleTime">50000</Set>
            <Set name="Acceptors">10</Set>
          </New>
        </Item>
      </Array>
    </Set>
</Configure>

ハンドラの作成

リクエストを受け取ったときに実行されるハンドラを用意する。 但し、この時点では HttpSession は使えないので要注意。

public class MyHandler extends AbstractHandler {

  public MyHandler() {
    super();
  }

  public boolean handle(final String target,
         final HttpServletRequest request,
         final HttpServletResponse response, final int dispatch)
           throws IOException, ServletException {

    // TODO: ここで何か処理をする
  }
}

HttpSession の準備

HttpSession を使う場合はもう少し面倒なコーディングが必要。 ハンドラを ContextHandler と SessionHandler でラッピングすると HttpSession が使用できるようになる。 ハンドラのの登録は jetty.xml を使って行っても良い。

  SessionManager sessionManager = new HashSessionManager(new Random(
          System.currentTimeMillis()));
  sessionManager
          .setMetaManager(new AbstractSessionManager.NullMetaManager());

  MyHandler myHandler = new MyHandler();
  SessionHandler sessionHandler = new SessionHandler();
  sessionHandler.setHandler(myHandler);
  sessionHandler.setSessionManager(sessionManager);
  MyContextHandler myContextHandler = new MyContextHandler();
  myContextHandler.setContextPath("/");
  myContextHandler.setHandler(sessionHandler);

  this.server.setHandler(myContextHandler);

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

Feb 09, 2006

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

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

Jan 27, 2006

[Library] クラスの依存関係チェックツールをメモ

クラスの依存関係をチェックできるツールをメモ。 コードレビューなどで重宝する。 とは言うものの、パッケージ間の依存に関する規約がプロジェクト毎にマチマチだったり、パッケージの数が膨大だったりするので、こういうアリモノのツールだと開発標準との摺り合わせが大変だったりする。 なので、個人的にはニーズに合わせて自作した方が手っ取り早いだろう派。

JDepend
http://www.clarkware.com/software/JDepend.html
Byecycle
http://byecycle.sourceforge.net/

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

Jan 16, 2006

[Library] Restlet にチャレンジ (2)

サンプルコード(1)

まずはリクエストの内容を表示するサンプル。

package jp.in_vitro.codelets.restletsample;

import org.restlet.AbstractRestlet;
import org.restlet.Restlet;
import org.restlet.RestletCall;
import org.restlet.RestletException;
import org.restlet.component.DefaultRestletContainer;
import org.restlet.component.RestletContainer;
import org.restlet.data.MediaTypes;
import org.restlet.data.Preference;

import com.noelios.restlet.data.StringRepresentation;
import com.noelios.restlet.ext.jetty.JettyServer;

public class RestletContainerSample {

    public static void main(String[] args) throws Exception {
        RestletContainerSample me = new RestletContainerSample();
        me.initialize();
        me.execute();
    }

    public RestletContainerSample() {
        super();
    }

    protected void initialize() {
        // Restlet API に Restlet 実装を登録。
        com.noelios.restlet.Engine.register();
    }

    protected void execute() throws Exception {
        // Jetty と Restlet コンテナの準備
        RestletContainer restletContainer = new DefaultRestletContainer(
                "My container");
        JettyServer httpServer = new JettyServer("Web Server", 8080,
                restletContainer);
        restletContainer.addServer(httpServer);

        // Restlet コンテナに Restlet を登録して、Restlet コンテナを開始。
        Restlet myRestlet = new MyRestlet(restletContainer);
        restletContainer.attach("http://localhost:8080/restlet", myRestlet);
        restletContainer.start();
    }

    protected static class MyRestlet extends AbstractRestlet {

        public MyRestlet(final RestletContainer restletContainer) {
            super(restletContainer);
        }

        public void handle(final RestletCall call) throws RestletException {
            StringBuffer message = new StringBuffer();
            message.append("<html><body>");
            message.append("<dl>");
            message.append("<dt>Client Address</dd>");
            message.append("<dd>" + call.getClientAddress() + "</dd>");
            message.append("<dt>Client Name</dd>");
            message.append("<dd>" + call.getClientName() + "</dd>");
            message.append("<dt>Method</dd>");
            message.append("<dd>" + call.getMethod() + "</dd>");
            if (call.getReferrerRef() != null) {
                message.append("<dt>Referrer Ref</dd>");
                message.append("<dd>" + call.getReferrerRef().getPath()
                        + "</dd>");
            }
            if (call.getResourceRef() != null) {
                message.append("<dt>Resource Ref</dd>");
                message.append("<dd>" + call.getResourceRef().getPath()
                        + "</dd>");
            }
            if (call.getSecurity() != null) {
                message.append("<dt>Security (description)</dd>");
                message.append("<dd>" + call.getSecurity().getDescription()
                        + "</dd>");
                message.append("<dt>Security (challenge request)</dd>");
                message.append("<dd>"
                        + call.getSecurity().getChallengeRequest() + "</dd>");
                message.append("<dt>Security (challenge response)</dd>");
                message.append("<dd>"
                        + call.getSecurity().getChallengeResponse() + "</dd>");
            }
            if (call.getStatus() != null) {
                message.append("<dt>Status</dd>");
                message.append("<dd>" + call.getStatus() + "</dd>");
            }
            if (call.getMatches() != null) {
                message.append("<dt>Matches</dd>");
                message.append("<dd>");
                for (String match : call.getMatches()) {
                    message.append(match);
                    message.append(",");
                }
                message.append("</dd>");
            }
            if (call.getPaths() != null) {
                message.append("<dt>Paths</dd>");
                message.append("<dd>");
                for (String path : call.getPaths()) {
                    message.append(path);
                    message.append("<br>");
                }
                message.append("</dd>");
            }
            if (call.getMediaTypePrefs() != null) {
                message.append("<dt>Media Type Prefs</dd>");
                message.append("<dd>");
                for (Preference preference : call.getMediaTypePrefs()) {
                    message.append(preference.getMetadata());
                    message.append(",");
                }
                message.append("</dd>");
            }
            if (call.getLanguagePrefs() != null) {
                message.append("<dt>Language Prefs</dd>");
                message.append("<dd>");
                for (Preference preference : call.getLanguagePrefs()) {
                    message.append(preference.getMetadata());
                    message.append(",");
                }
                message.append("</dd>");
            }
            if (call.getCharacterSetPrefs() != null) {
                message.append("<dt>Character Set Prefs</dd>");
                message.append("<dd>");
                for (Preference preference : call.getCharacterSetPrefs()) {
                    message.append(preference.getMetadata());
                    message.append(",");
                }
                message.append("</dd>");
            }
            if (call.getConditions() != null) {
                message.append("<dt>Conditions (description)</dd>");
                message.append("<dd>" + call.getConditions().getDescription()
                        + "</dd>");
                message.append("<dt>Conditions (modified since)</dd>");
                message.append("<dd>" + call.getConditions().getModifiedSince()
                        + "</dd>");
                message.append("<dt>Conditions (unmodified since)</dd>");
                message.append("<dd>"
                        + call.getConditions().getUnmodifiedSince() + "</dd>");
            }
            message.append("</dl>");
            message.append("</body></html>");
            call.setOutput(new StringRepresentation(new String(message),
                    MediaTypes.TEXT_HTML));
        }
    }
}

サンプルコード(2)

URL に従ってファイルを返すサンプル。

package jp.in_vitro.codelets.restletsample;

import org.restlet.component.DefaultRestletContainer;
import org.restlet.component.RestletContainer;
import org.restlet.data.MediaTypes;

import com.noelios.restlet.DirectoryRestlet;
import com.noelios.restlet.ext.jetty.JettyServer;

public class DirectoryRestletSample {

    public static void main(final String[] args) throws Exception {
        DirectoryRestletSample me = new DirectoryRestletSample();
        me.initialize();
        me.execute();
    }

    public DirectoryRestletSample() {
        super();
    }

    protected void initialize() {
        // Restlet API に Restlet 実装を登録。
        com.noelios.restlet.Engine.register();
    }

    protected void execute() throws Exception {
        // Jetty と Restlet コンテナの準備
        RestletContainer restletContainer = new DefaultRestletContainer(
                "My container");
        JettyServer httpServer = new JettyServer("Web Server", 8080,
                restletContainer);
        restletContainer.addServer(httpServer);

        // リクエストのパスに従ってファイルを返す Restlet
        DirectoryRestlet dirRestlet = new DirectoryRestlet(restletContainer,
                "c:/tmp", true, "index");
        dirRestlet.addExtension("txt", MediaTypes.TEXT_PLAIN);

        // Restlet コンテナに Restlet を登録して、Restlet コンテナを開始。
        restletContainer.attach("http://localhost:8080/", dirRestlet);
        restletContainer.start();
    }
}

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

Jan 15, 2006

[Library] Restlet にチャレンジ

Restlet とは

Restlet は、Java の Webアプリケーション用フレームワーク。 REST アーキテクチャの考え方をベースにしているフレームワークでちょっと目新しい。

Restlet
http://www.restlet.org/
Restlet Tutorial
http://www.restlet.org/tutorial
Java開発をWeb 2.0に対応させる「Restlet」プロジェクト
http://www.itmedia.co.jp/enterprise/articles/0601/10/news022.html
RESTアーキテクチャとは? SOAPとの関係は?
http://www.goodpic.com/mt/archives/000185.html

Restlet の実行環境構築

  1. こちらから Restlet をダウンロードする。ここでは ver.0.19 を前提とする。
  2. アーカイブの中の lib ディレクトリにある以下の jar をクラスパスに追加する。
    • com.noelios.restlet.jar
    • freemarker.jar
    • javax.servlet.jar
    • mail.jar
    • org.apache.commons.logging.jar
    • org.mortbay.jetty.jar
    • org.restlet.jar
    • restlet.freemarker.jar
    • restlet.javamail.jar
    • restlet.jetty.jar

サンプルコード

Web ブラウザに "Hello Restlet World" という文字列を送るサンプルコード。 Jetty を使うと気軽に Web アプリケーションが作成できる。 アプリケーションサーバをわざわざ用意したくないような小規模な Web アプリで使うと便利かも。

package jp.in_vitro.codelets.restletsample;

import org.restlet.UniformCall;
import org.restlet.UniformInterface;
import org.restlet.data.MediaTypes;

import com.noelios.restlet.data.StringRepresentation;
import com.noelios.restlet.ext.jetty.JettyServer;

public class UniformInterfaceSample {

    public static void main(final String[] args) {
        UniformInterfaceSample me = new UniformInterfaceSample();
        me.execute();
    }

    public UniformInterfaceSample() {
        super();
    }

    protected void execute() {
        // Web ブラウザに "Hello Restlet World" という文字列を text/plain で返す。
        UniformInterface handler = new UniformInterface() {
            public void handle(final UniformCall call) {
                call.setOutput(new StringRepresentation("Hello Restlet World!",
                        MediaTypes.TEXT_PLAIN));
            }
        };
        // HTTP サーバを起動する。
        new JettyServer("Web Server", 8080, handler).start();
    }
}

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

Jan 06, 2006

[Library] jLHA にチャレンジ

jLHA とは

jLHA は、名前の通り Java で LHA を扱うためのライブラリ。 J2SE にある ZIP 用 API と似通ったインターフェースを持っているため使いやすい。 ライセンスは独自ライセンスになっている。

LHA Library for Java
http://homepage1.nifty.com/dangan/Content/Program/Java/jLHA/LhaLibrary.html

jLHA の実行環境構築

  1. こちらから jLHA のソースコードをダウンロードする(ここでは version 0.06-05 を使用)。
  2. compile.xml 内の javac.target のvalue="1.1"をvalue="1.5"に変更する。
  3. jLHA をコンパイルして jar を生成する。ここでは、JDK 1.5.0_05 と Ant 1.6.2 を使用した。
    > ant -f compile.xml compileRelease
    > jar cvf jlha-0.06-05.jar jp
  4. jlha-0.06-05.jar をクラスパスに指定する。

サンプルコード

package jp.in_vitro.codelets.jlha;

import java.io.IOException;
import java.io.InputStream;

import jp.gr.java_conf.dangan.util.lha.LhaFile;
import jp.gr.java_conf.dangan.util.lha.LhaHeader;

public class Codelet {

    public Codelet() {
        super();
    }

    public static void main(String[] args) throws IOException {
        Codelet me = new Codelet();
        me.execute();
    }

    protected void execute() throws IOException {
        LhaFile file = new LhaFile("c:\\sample.lzh");
        LhaHeader[] entries = file.getEntries();
        String path = null;
        for (LhaHeader entry : entries) {
            path = entry.getPath();
            System.out.println("" + path);

            InputStream is = null;
            try {
                is = file.getInputStream(path);
                int ch = 0;
                while ((ch = is.read()) >= 0) {
                    System.out.print((char) ch);
                }
                System.out.println();
            } finally {
                if (is != null) {
                    is.close();
                }
            }
        }
    }
}

Posted in Library | このエントリーをはてなブックマークに追加 | この記事をクリップ! 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 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 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 クリップ |

Oct 09, 2005

[Library] JCIFS の概要

JCIFS のクラス図

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

[JCIFS 1.2.6 のクラス図]

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

Oct 08, 2005

[Library] JCIFS にチャレンジ

JCIFS とは

JCIFS は CIFS/SMB の Java 用ライブラリ。 要するに Java から Windows のファイルシステムにアクセスできる。

JCIFS
http://jcifs.samba.org/

JCIFS の実行環境構築

  1. JCIFS(jcifs-1.2.6.jar) をクラスパスに追加

サンプルコード

package jp.in_vitro.codelets.jcifs;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Date;
import java.util.Properties;

import jcifs.Config;
import jcifs.smb.SmbException;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileInputStream;

public class Codelet {

    public Codelet() {
        super();
    }

    public static void main(final String[] args) throws Exception {
        Codelet me = new Codelet();
        me.initializeJcifs();
        me.printFileList("smb://myclient/c$/");
        me.printFile("smb://myclient/SharedDocs/tmp.txt");
    }

    protected void initializeJcifs() {
        Config.setProperties(this.prepareSystemConfiguration());
    }

    protected Properties prepareSystemConfiguration() {

        Properties props = new Properties();

        props.setProperty("jcifs.netbios.wins", "192.168.1.1");
        props.setProperty("jcifs.smb.client.username", "myname");
        props.setProperty("jcifs.smb.client.password", "mypassword");

        return props;
    }

    public void printFileList(final String target)
            throws MalformedURLException, SmbException {

        SmbFile dir = new SmbFile(target);
        if (!dir.isDirectory()) {
            return;
        }

        SmbFile[] children = dir.listFiles();
        for (SmbFile child : children) {
            if (child.isDirectory()) {
                System.out.print("[DIR]");
            }
            System.out.print(" ");
            System.out.print("" + child.getCanonicalPath());
            System.out.print(" ");
            System.out.print("" + new Date(child.getDate()));
            System.out.println();
        }
    }

    public void printFile(final String target) throws IOException {

        SmbFileInputStream in = new SmbFileInputStream(target);
        int ch = 0;
        while ((ch = in.read()) >= 0) {
            System.out.print("" + (char) ch);
        }
    }
}

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

Sep 28, 2005

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

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

Sep 26, 2005

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

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

Sep 25, 2005

[Library] JavaSVN の概要

JavaSVN のクラス図

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

[JavaSVN 0.9.3 のクラス図]

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

Sep 23, 2005

[Library] JavaSVN にチャレンジ

JavaSVN とは

Java から Subversion にアクセスできるライブラリ。 Subversion のクライアントを Pure Java で実装しているツワモノ。 お馴染み Eclipse 用 Subversion Plugin の Subclipse でも内部で利用されている。

JavaSVN
http://tmate.org/svn/
JavaSVN サンプルコード
http://tmate.org/svn/kb/examples/index.php
類似のツールに JSVN があるが、JSVN はネイティブの svn コマンドを呼び出すだけなので使いづらい。

JavaSVN の実行環境構築

  1. JavaSVN (ganymed.jar, javasvn.jar, javasvn-cli.jar, javasvn-javahl.jar) をクラスパスに追加する

サンプルコード

package jp.in_vitro.codelets.javasvn;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

public class Codelet {

    public Codelet() {
        super();
    }

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

        String url = "http://example.com/repos/";
        String username = "myname";
        String password = "mypassword";

        Codelet me = new Codelet();
        me.initializeJavaSVN();
        SVNRepository repository = me.prepareSVNRepository(url, username,
                password);
        me.printInfo(repository, "projects/");
        me.printInfo(repository, "projects/pom.xml");

        repository.closeSession();
    }

    protected void initializeJavaSVN() {
        DAVRepositoryFactory.setup();
        SVNRepositoryFactoryImpl.setup();
    }

    protected void printInfo(final SVNRepository repository, final String path)
            throws SVNException {

        SVNNodeKind nodeKind = repository.checkPath(path, -1);
        if (nodeKind == SVNNodeKind.NONE) {
            System.out.println("NONE");
        } else if (nodeKind == SVNNodeKind.UNKNOWN) {
            System.out.println("UNKNOWN");
        } else if (nodeKind == SVNNodeKind.DIR) {
            Map properties = new HashMap();
            List children = new ArrayList();
            repository.getDir(path, -1, properties, children);

            System.out.println("*** properties ***");
            for (Object key : properties.keySet()) {
                System.out.println("" + key + " - " + properties.get(key));
            }
            System.out.println("*** children ***");
            for (Object child : children) {
                System.out.println("" + child);
            }

        } else if (nodeKind == SVNNodeKind.FILE) {
            Map properties = new HashMap();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            repository.getFile(path, -1, properties, baos);

            System.out.println("*** properties ***");
            for (Object key : properties.keySet()) {
                System.out.println("" + key + " - " + properties.get(key));
            }
        }

    }

    protected SVNRepository prepareSVNRepository(final String url,
            final String username, final String password) throws SVNException {

        SVNRepository repository = SVNRepositoryFactory.create(SVNURL
                .parseURIEncoded(url));

        ISVNAuthenticationManager authenticationManager = SVNWCUtil
                .createDefaultAuthenticationManager(username, password);
        repository.setAuthenticationManager(authenticationManager);

        return repository;
    }
}

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

Sep 20, 2005

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

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

Sep 19, 2005

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

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

Sep 17, 2005

[Library] Pure Java DBMS

Pure Java の RDBMS を探してみた。 探してみると結構な数がある。 hsqldb は以前試してみたことがあるが、イマイチ使い勝手が良くなかった。 というわけで、他の RDBMS を試してみよう。

hsqldb - Original License
http://hsqldb.org/
Derby - Apache License, Version 2.0
http://db.apache.org/derby/
Mckoi - GPL
http://mckoi.com/database/
QED - Original License
http://www.quadcap.com/home.html
tinySQL - LGPL
http://sourceforge.net/projects/tinysql/
One$DB - LGPL
http://daffodildb.com/one-dollar-db.html

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

Sep 15, 2005

[Library] Jsch にチャレンジ

JCIFS とは

SSH2 用の Java ライブラリ。 SFTP、SCPなどにも対応している優れもの。

Jsch
http://www.jcraft.com/jsch/index.html
Jsch のサンプルコード
http://www.jcraft.com/jsch/examples/

JCIFS の実行環境構築

  1. Jsch(jsch-0.1.23.jar) をクラスパスに追加。

サンプルコード

package jp.in_vitro.codelets.jsch;

import java.lang.reflect.Field;
import java.util.Vector;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.HostKey;
import com.jcraft.jsch.HostKeyRepository;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

public class Codelet {

    public Codelet() {
        super();
    }

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

        Codelet me = new Codelet();
        me.connectSsh("192.168.1.1", "myname", "mypassword");
    }

    public void connectSsh(final String hostname, final String username,
            final String password) throws SecurityException,
            NoSuchFieldException, IllegalArgumentException,
            IllegalAccessException, JSchException {

        JSch jsch = new JSch();

        Session session = null;
        while (true) {
            try {
                session = jsch.getSession(username, hostname, 22);
                session.setPassword(password);
                session.connect(3000);
                break;
            } catch (JSchException e) {
                if (e.getLocalizedMessage().indexOf("UnknownHostKey") >= 0) {
                    // 無理矢理 known_host に登録。ホントはマズい。
                    HostKey hostkey = session.getHostKey();
                    HostKeyRepository hostkeyRepo = jsch.getHostKeyRepository();
                    Field field = hostkeyRepo.getClass().getDeclaredField(
                            "pool");
                    field.setAccessible(true);
                    System.out.println("" + field.getType());
                    Vector hostkeyRepoPool = (Vector) field.get(hostkeyRepo);
                    hostkeyRepoPool.add(hostkey);
                    session.disconnect();
                    continue;
                }
                break;
            }
        }

        Channel channel = session.openChannel("shell");
        channel.setInputStream(System.in);
        channel.setOutputStream(System.out);
        channel.connect();
    }

}

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

Aug 27, 2005

[Library] JCAPTCHA にチャレンジ

JCAPTCHA とは

CAPTCHA を Java で実現するためのライブラリ。 CAPTCHA というのは、completely automated public Turing test to tell computers and humans apart の略で通信相手が人間かコンピュータかを判断するための機構のこと。 Hotmail やら GMail やらを登録する際に表示されるクネクネした画像とかでお馴染みのアレ。 この辺りに解説がある。

Captcha - Wikipedia, the free encyclopediaの翻訳(2005年2月27日版)
http://www.memb.jp/~deq/voice/captcha/wikipedia-captcha.html
はてなダイアリー - CAPTCHA とは
http://d.hatena.ne.jp/keyword/CAPTCHA

JCAPTCHA は簡単に CAPTCHA を実現できるらしいのでチャレンジ。 内部で EHCACHE という別のライブラリに依存しているらしいので、それも必要。

JCAPTCHA
http://jcaptcha.sourceforge.net/
EHCACHE
http://ehcache.sourceforge.net/

JCAPTCHA の実行環境構築

  1. JCAPTCHA (jcaptcha-all-1.0-RC2.0.1.jar) をクラスパスに追加
  2. EHCACHE (ehcache-1.2beta2.jar) をクラスパスに追加
  3. その他必要なライブラリ (commons-collections-2.1.1.jar, commons-logging-1.0.4.jar) をクラスパスに追加

実行例

↓のサンプルコードを動かしてみたところ。 [↓のサンプルコードの実行例(1)] [↓のサンプルコードの実行例(2)]

サンプルコード

package jp.in_vitro.codelets.jcaptcha;

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.util.Locale;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;

import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;

import com.octo.captcha.service.image.DefaultManageableImageCaptchaService;
import com.octo.captcha.service.image.ImageCaptchaService;

public class Codelet {

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

    public static void main(final String[] args) throws Exception {
        CaptchaImageCreator creator = new CaptchaImageCreator("my id", Locale
                .getDefault());

        ImageViewer viewer = new ImageViewer(creator);
        viewer.setVisible(true);
    }

    public static class CaptchaImageCreator {
        private String captchaId;
        private Locale locale;

        public CaptchaImageCreator(final String captchaId, final Locale locale)
                throws CacheException {
            super();

            this.captchaId = captchaId;
            this.locale = locale;

            this.initializeEhcache();
        }

        protected void initializeEhcache() throws CacheException {
            // ehcache-1.2beta2.jar 内にある XML ファイルで EHCACHE を初期化する。
            InputStream is = this.getClass().getResourceAsStream(
                    "/ehcache-failsafe.xml");
            CacheManager.create(is);
        }

        public BufferedImage createImage() {
            // イメージを生成する。
            ImageCaptchaService service = new DefaultManageableImageCaptchaService();
            BufferedImage image = service.getImageChallengeForID(
                    this.captchaId, this.locale);
            return image;
        }
    }

    public static class ImageViewer extends JFrame {
        private BufferedImage image;
        private CaptchaImageCreator creator;
        private Canvas canvas;
        private JButton nextButton;

        public ImageViewer(final CaptchaImageCreator creator) {
            super();

            this.creator = creator;
            this.initComponents();
        }

        protected void initComponents() {
            // ウィンドウ終了方法の指定。
            super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            // 初回イメージの生成。
            this.image = creator.createImage();

            // ContentPane の設定。
            Container contentPane = super.getContentPane();
            contentPane.setLayout(new BorderLayout());

            // イメージ表示用キャンバスの準備。
            this.canvas = new Canvas() {
                @Override
                public void paint(Graphics g) {
                    g.drawImage(ImageViewer.this.image, 0, 0, this);
                }

                @Override
                public Dimension getPreferredSize() {
                    return new Dimension(ImageViewer.this.image.getWidth(),
                            ImageViewer.this.image.getHeight());
                }
            };
            contentPane.add(this.canvas, BorderLayout.CENTER);

            // "次のイメージに進む"ボタンの準備。
            this.nextButton = new JButton(new AbstractAction("next image") {
                public void actionPerformed(final ActionEvent evt) {
                    ImageViewer.this.image = ImageViewer.this.creator
                            .createImage();
                    ImageViewer.this.canvas.repaint();
                }
            });
            contentPane.add(this.nextButton, BorderLayout.SOUTH);

            // ウィンドウサイズの自動調整。
            super.pack();
        }
    }
}

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

Aug 16, 2005

[Library] PDFBox を試してみる

PDFBox とは

PDF の読み書きから暗号化、復号化までしてくれるスグレモノの Java 用ライブラリ。 基本機能で少し遊んでみた。

PDFBox
http://www.pdfbox.org/

PDFBox の実行環境構築

  1. PDFBox(pdfbox-0.7.2.jar) をクラスパスに追加。

サンプルコード

既存 PDF の読み込み
1 byte 文字のみで構成されている PDF を読み込んで JPEG に書き出してみた。 何とも簡単に出来た。
日本語 PDF の書き出し
1 byte 文字のみの PDF 書き出しはサンプルにあったので、2 byte 文字の書き出しにチャレンジ。 TTC 形式のフォント(TTF ファイルの集合) は読み込めないので、予め BREAKTTC というツールで TTF を作成しておいた。 結局、上手く行かないまま時間切れ。(↓のコードは文字化けした PDF を出力する)。
package jp.in_vitro.codelets.pdfbox;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

import org.pdfbox.exceptions.COSVisitorException;
import org.pdfbox.pdmodel.PDDocument;
import org.pdfbox.pdmodel.PDPage;
import org.pdfbox.pdmodel.edit.PDPageContentStream;
import org.pdfbox.pdmodel.font.PDFont;
import org.pdfbox.pdmodel.font.PDTrueTypeFont;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class Codelet {

    public Codelet() {
        super();
    }

    public static void main(final String[] args) throws COSVisitorException,
            IOException {

        Codelet me = new Codelet();
        me.createJapanesePDF(new File("c:\\workspace\\japanese.pdf"), new File(
                "c:\\workspace\\MSGOTHIC_FONT00.ttf"));
        me.convertPDFtoJPEG(new File("c:\\workspace\\english.pdf"));
    }

    public void convertPDFtoJPEG(final File target) throws IOException {

        PDDocument document = null;
        try {
            document = PDDocument.load(target);
            List pages = document.getDocumentCatalog().getAllPages();

            int count = 0;
            for (PDPage page : pages) {
                BufferedImage image = page.convertToImage();
                FileOutputStream fos = new FileOutputStream(target
                        .getAbsolutePath()
                        + "." + count++ + ".jpg");
                JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fos);
                encoder.encode(image);
                fos.close();
            }
        } finally {
            if (document != null) {
                document.close();
            }
        }
    }

    public void createJapanesePDF(final File target, final File fontFile)
            throws IOException, COSVisitorException {

        String message = "日本語だよ。";

        PDDocument document = null;
        try {
            PDPage page = new PDPage();
            document = new PDDocument();
            document.addPage(page);

            PDFont font = PDTrueTypeFont.loadTTF(document, fontFile);

            PDPageContentStream contentStream = new PDPageContentStream(
                    document, page);
            contentStream.beginText();
            contentStream.setFont(font, 10);
            contentStream.moveTextPositionByAmount(50, 50);
            contentStream.drawString(message);
            contentStream.endText();
            contentStream.close();
            document.save(target.getAbsolutePath());

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

    }
}

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