Mar 31, 2006

[Mustang] JapaneseImperialCalendar にチャレンジ

Mustang では遂に和暦がサポートされるらしい!!

JavaWorld 2006/05
を貰ったので何となく眺めていたら、とある記事で紹介されていた。 java.util.Calendar の実装クラスがパッケージプライベートなので API Document を眺めていても全く気付いていなかった。 Calendar の和暦サポートは Mustang でも流れたとばかり思っていた。 JavaWorld は久しぶりに開いたけれど、軽くでも毎月目を通すべきかもしれないな。

JavaWorld の記事中でも紹介されていた JapaneseImperialCalendar の紹介ページは↓

Java SE 6 Mustang じゃじゃ馬ならし 官公庁向けでも大丈夫 - 和暦
http://www.javainthebox.net/laboratory/JavaSE6/imperialcalendar/imperialcalendar.html

サンプルコード

package jp.in_vitro.codelets.util;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

public class Codelet {

    private Date date = new Date(System.currentTimeMillis());

    public Codelet() {
        super();
    }

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

    protected void execute00() {
        Locale locale = new Locale("ja", "JP");
        Calendar cal = Calendar.getInstance(locale);

        System.out
                .println("0*************************************************************");

        System.out.println("Default Locale : " + Locale.getDefault());
        System.out.println("Calendar#getInstance : " + locale);
        System.out.println();
        System.out.println("" + cal);
        DateFormat format0 = new SimpleDateFormat("GGGGyy年MMMMdd日");
        System.out.println("GGGGyy年MMMMdd日 : " + format0.format(this.date));
        DateFormat format1 = new SimpleDateFormat("GGGyy年MMMMdd日");
        System.out.println("GGGyy年MMMMdd日 : " + format1.format(this.date));
        DateFormat format2 = new SimpleDateFormat("GGGyy/MM/dd");
        System.out.println("GGGGyy/MM/dd : " + format2.format(this.date));
        DateFormat format3 = new SimpleDateFormat("GGGyy/MM/dd");
        System.out.println("GGGyy/MM/dd : " + format3.format(this.date));
        System.out.println();
    }

    protected void execute01() {
        Locale locale = new Locale("ja", "JP", "JP");
        Calendar cal = Calendar.getInstance(locale);

        System.out
                .println("1*************************************************************");

        System.out.println("Default Locale : " + Locale.getDefault());
        System.out.println("Calendar#getInstance : " + locale);
        System.out.println();
        System.out.println("" + cal);
        DateFormat format0 = new SimpleDateFormat("GGGGyy年MMMMdd日");
        System.out.println("GGGGyy年MMMMdd日 : " + format0.format(this.date));
        DateFormat format1 = new SimpleDateFormat("GGGyy年MMMMdd日");
        System.out.println("GGGyy年MMMMdd日 : " + format1.format(this.date));
        DateFormat format2 = new SimpleDateFormat("GGGyy/MM/dd");
        System.out.println("GGGGyy/MM/dd : " + format2.format(this.date));
        DateFormat format3 = new SimpleDateFormat("GGGyy/MM/dd");
        System.out.println("GGGyy/MM/dd : " + format3.format(this.date));
        System.out.println();
    }

    protected void execute02() {
        Locale.setDefault(new Locale("ja", "JP"));
        Calendar cal = Calendar.getInstance();

        System.out
                .println("2*************************************************************");

        System.out.println("Default Locale : " + Locale.getDefault());
        System.out.println("Calendar#getInstance : null");
        System.out.println();
        System.out.println("" + cal);
        DateFormat format0 = new SimpleDateFormat("GGGGyy年MMMMdd日");
        System.out.println("GGGGyy年MMMMdd日 : " + format0.format(this.date));
        DateFormat format1 = new SimpleDateFormat("GGGyy年MMMMdd日");
        System.out.println("GGGyy年MMMMdd日 : " + format1.format(this.date));
        DateFormat format2 = new SimpleDateFormat("GGGyy/MM/dd");
        System.out.println("GGGGyy/MM/dd : " + format2.format(this.date));
        DateFormat format3 = new SimpleDateFormat("GGGyy/MM/dd");
        System.out.println("GGGyy/MM/dd : " + format3.format(this.date));
        System.out.println();
    }

    protected void execute03() {
        Locale.setDefault(new Locale("ja", "JP", "JP"));
        Calendar cal = Calendar.getInstance();

        System.out
                .println("3*************************************************************");

        System.out.println("Default Locale : " + Locale.getDefault());
        System.out.println("Calendar#getInstance : null");
        System.out.println();
        System.out.println("" + cal);
        DateFormat format0 = new SimpleDateFormat("GGGGyy年MMMMdd日");
        System.out.println("GGGGyy年MMMMdd日 : " + format0.format(this.date));
        DateFormat format1 = new SimpleDateFormat("GGGyy年MMMMdd日");
        System.out.println("GGGyy年MMMMdd日 : " + format1.format(this.date));
        DateFormat format2 = new SimpleDateFormat("GGGGyy/MM/dd");
        System.out.println("GGGGyy/MM/dd : " + format2.format(this.date));
        DateFormat format3 = new SimpleDateFormat("GGGyy/MM/dd");
        System.out.println("GGGyy/MM/dd : " + format3.format(this.date));
        System.out.println();
    }
}

実行結果

0, 2, 3 の結果は理解できる。 1 は何故こうなるのだろう?? バグなのか仕様なのか・・・。 Mustang が正式にリリースされたら試してみるか。

0*************************************************************
Default Locale : ja_JP
Calendar#getInstance : ja_JP

java.util.GregorianCalendar[time=1143914626604,areFieldsSet=true,areAllFieldsSet
=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Tokyo",offset=324000
00,dstSavings=0,useDaylight=false,transitions=10,lastRule=null],firstDayOfWeek=1
,minimalDaysInFirstWeek=1,ERA=1,YEAR=2006,MONTH=3,WEEK_OF_YEAR=14,WEEK_OF_MONTH=
2,DAY_OF_MONTH=2,DAY_OF_YEAR=92,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOU
R=3,HOUR_OF_DAY=3,MINUTE=3,SECOND=46,MILLISECOND=604,ZONE_OFFSET=32400000,DST_OF
FSET=0]
GGGGyy年MMMMdd日 : 西暦06年4月02日
GGGyy年MMMMdd日 : 西暦06年4月02日
GGGGyy/MM/dd : 西暦06/04/02
GGGyy/MM/dd : 西暦06/04/02

1*************************************************************
Default Locale : ja_JP
Calendar#getInstance : ja_JP_JP

java.util.JapaneseImperialCalendar[time=1143914626664,areFieldsSet=true,areAllFi
eldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Tokyo",offset
=32400000,dstSavings=0,useDaylight=false,transitions=10,lastRule=null],firstDayO
fWeek=1,minimalDaysInFirstWeek=1,ERA=4,YEAR=18,MONTH=3,WEEK_OF_YEAR=14,WEEK_OF_M
ONTH=2,DAY_OF_MONTH=2,DAY_OF_YEAR=92,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=1,AM_PM=
0,HOUR=3,HOUR_OF_DAY=3,MINUTE=3,SECOND=46,MILLISECOND=664,ZONE_OFFSET=32400000,D
ST_OFFSET=0]
GGGGyy年MMMMdd日 : 西暦06年4月02日
GGGyy年MMMMdd日 : 西暦06年4月02日
GGGGyy/MM/dd : 西暦06/04/02
GGGyy/MM/dd : 西暦06/04/02

2*************************************************************
Default Locale : ja_JP
Calendar#getInstance : null

java.util.GregorianCalendar[time=1143914626664,areFieldsSet=true,areAllFieldsSet
=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Tokyo",offset=324000
00,dstSavings=0,useDaylight=false,transitions=10,lastRule=null],firstDayOfWeek=1
,minimalDaysInFirstWeek=1,ERA=1,YEAR=2006,MONTH=3,WEEK_OF_YEAR=14,WEEK_OF_MONTH=
2,DAY_OF_MONTH=2,DAY_OF_YEAR=92,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOU
R=3,HOUR_OF_DAY=3,MINUTE=3,SECOND=46,MILLISECOND=664,ZONE_OFFSET=32400000,DST_OF
FSET=0]
GGGGyy年MMMMdd日 : 西暦06年4月02日
GGGyy年MMMMdd日 : 西暦06年4月02日
GGGGyy/MM/dd : 西暦06/04/02
GGGyy/MM/dd : 西暦06/04/02

3*************************************************************
Default Locale : ja_JP_JP
Calendar#getInstance : null

java.util.JapaneseImperialCalendar[time=1143914626664,areFieldsSet=true,areAllFi
eldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Tokyo",offset
=32400000,dstSavings=0,useDaylight=false,transitions=10,lastRule=null],firstDayO
fWeek=1,minimalDaysInFirstWeek=1,ERA=4,YEAR=18,MONTH=3,WEEK_OF_YEAR=14,WEEK_OF_M
ONTH=2,DAY_OF_MONTH=2,DAY_OF_YEAR=92,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=1,AM_PM=
0,HOUR=3,HOUR_OF_DAY=3,MINUTE=3,SECOND=46,MILLISECOND=664,ZONE_OFFSET=32400000,D
ST_OFFSET=0]
GGGGyy年MMMMdd日 : 平成18年4月02日
GGGyy年MMMMdd日 : H18年4月02日
GGGGyy/MM/dd : 平成18/04/02
GGGyy/MM/dd : H18/04/02

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

Mar 30, 2006

Mar 29, 2006

[Maven] Maven2 で API Document を生成する方法

Maven2 では maven-javadoc-plugin というプラグインが提供されており、このプラグインを使用することで簡単に API Document を生成できる。 但し、デフォルトの設定ではお約束のように 2 バイト文字が文字化けするので、多少設定が必要。

javadoc:javadoc
http://maven.apache.org/plugins/maven-javadoc-plugin/javadoc-mojo.html

maven-javadoc-plugin の設定方法

<pom>
  <organization>
    <name>in-vitro.jp</name>  ←改行コードが入るとエラー
    <url>http://www.in-vitro.jp/</url>
  </organization>
  <reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-javadoc-plugin</artifactId>
        <configuration>
          <charset>Shift_JIS</charset>
        </configuration>
      </plugin>
    </plugins>
  </reporting>
</pom>

maven-javadoc-plugin の実行方法

JDK と Maven2 にパスを通したコンソールから、下記のコマンドを実行する。 生成された API Document は target/site に出力される。

  > mvn site

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

Mar 27, 2006

[Misc] Named Capture メモ

最速インターフェース研究会さんのNamedCapture for JavaScriptでNamed Captureというものを知った。 日本語では「名前付きキャプチャ」と言うらしい。 Named Capture は正規表現の Syntax で、(?P<name>regexp) と言うように名前を指定することで今までマッチした順序を数値で指定していたところが名前でアクセスできるようになるらしい。 細かい改良だけれど、意外と便利そう。

.NET での正規表現の使用
http://japan.internet.com/developer/20050822/28.html
グループ化構成体
http://msdn.microsoft.com/library/ja/cpgenref/html/cpcongroupingconstructs.asp?frame=true
Named Capture Groups
http://regular-expressions.info/named.html
http://regular-expressions.info/ の情報を信じるならば、Named Capture は Python がオリジナルらしい。 そして、Microsoft は .Net で同様の機能を取り入れたが、その際に Syntax を独自のものにしてしまったようだ。いつものことだが迷惑極まりない。
The regular expression classes of the .NET framework also support named capture. Unfortunately, the Microsoft developers decided to invent their own syntax, rather than follow the one pioneered by Python.

Python で Named Capture にチャレンジ

$ python
Python 1.5.2 (#1, Jan 31 2003, 11:01:49)  [GCC 2.96 20000731 (Red Hat Linux 7.2 2 on linux-i386
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> import re
>>> search = re.compile("(?P[a-zA-Z]+)")
>>> line = "123abc456"
>>> result = search.search(line)
>>> print result.group('alphabet')
abc
>>> print result.group(0)
abc
>>>

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

[Subversion] FSFS の発音

Subversion のドキュメントを眺めていて面白い記述を発見した。

Jack Repenning が何も文句を言わないのなら「fuzz-fuzz」と発音することになっています
というわけで、FSFS は「ふぁずふぁず」と発音するらしい。 知らなかった。 ・・・日本国内で「ふぁずふぁず」と発音しても通じないだろうな。

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

Mar 23, 2006

[Subversion] Subversion のリポジトリ破損

Subversion のリポジトリ(FSFS)が破損した。 Commit は出来るのだが、Update や Log を実行すると

REPORT request failed on '/repository/!svn/vcc/default'
REPORT of '/repository/!svn/vcc/default': 200 OK
というエラーが発生して処理が中断してしまう。 TortoiseSVN でも Subclipse でも発生したので、サーバ側の問題の模様。

原因

原因はリビジョンファイルの破損。 HDD のセクタが破損したことで $SVN_HOME/svndb/db/revs/ の中にある特定のファイルにアクセスできなくなっていた。 壊れていたリビジョンは最新のものではなく、少し古い(数日前)のものだった。 "svnadmin verify" コマンドでリビジョンの状態をチェックできる。

# svnadmin verify /home/svn/svndb/
         (SNIP)
* Verified ▒・▒吾с??222▒
* Verified ▒・▒吾с??223▒
* Verified ▒・▒吾с??224▒
* Verified ▒・▒吾с??225▒
* Verified ▒・▒吾с??226▒
* Verified ▒・▒吾с??227▒
* Verified ▒・▒吾с??228▒
svn: Can't read file '/home/svn/svndb/db/revs/229': 入力/出力エラーです
#
コマンドの実行結果が文字化けしているのはご愛敬といったところか・・・。

対処方法

今回は破損したリビジョンが数日前と比較的最近のものだったので、破損したリビジョンの一つ前の状態に戻すことにした。 手順は以下の通り。

  1. $SVN_HOME/svndb/db/revs から破損したリビジョン以降のリビジョンファイルを削除
  2. $SVN_HOME/svndb/db/revprops から↑で削除したものと同じ名前のファイルを削除
  3. $SVN?HOME/svndb/db/current を編集して、現在のリビジョンを削除後の最新リビジョンに変更

備考

破損したリビジョンだけを無かったことに出来ないか、と思い色々調べてみたがどうも難しそう。 Subversion では各リビジョンはファイルの差分情報しか持っていない。 そのため、破損したリビジョンで変更が加えられているファイルがその後のリビジョンでも変更されていると、破損したリビジョンを削除することは出来ない。 ツールなどでも復旧は出来ないようだ。 リビジョンファイルを一つずつ手で修正すれば良いのかもしれないが、膨大な量の修正が必要になることとバイナリファイルを修正するという 2 点から容易な作業ではない。 バックアップはお早めに、といったところか。

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

Mar 22, 2006

[Mustang] Java 6 Revealed

もう Mustang に関する書籍が出版される。 発売予定日 は 2006/05/29。 このタイミングで出版とは、さすが米国。 日本も負けていられない。 誰か国産 Mustang 本書いてくれないかな。


Java 6 Revealed

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

Mar 21, 2006

[Mustang] Console にチャレンジ

Mustang では Console というクラスが新設された。 Console はその名の通りコンソールへのアクセスを提供してくれるクラス。 ちなみに、コンソール用なので Eclipse 上では使えない模様(System.console() が null を返す)。

Class Console
http://download.java.net/jdk6/docs/api/java/io/Console.html

サンプルコード

package jp.in_vitro.codelets.lang;

import java.io.Console;
import java.io.PrintWriter;

public class Codelet {

    public Codelet() {
        super();
    }

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

    protected void execute() {
        Console console = System.console();
        PrintWriter writer = console.writer();

        writer.print("name:");
        writer.flush();
        String name = console.readLine();
        writer.println("your name is " + name);
        writer.flush();

        writer.print("password:");
        writer.flush();
        char[] password = console.readPassword();
        writer.println("your password is " + new String(password));
        writer.flush();
    }
}

実行結果

> java -version
java version "1.6.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-beta-b59g)
Java HotSpot(TM) Client VM (build 1.6.0-beta-b59g, mixed mode, sharing)

> java -classpath classes jp.in_vitro.codelets.lang.Codelet
name:in-vitro.jp
your name is in-vitro.jp
password:     ←[ここでパスワードを入力しているがエコーバックされない]
your password is hogehoge

>

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

Mar 20, 2006

[Mustang] Mustang における File の 追加機能

Mustang では java.io.File も結構機能追加されていることに気付いた。 ディスクスペースの取得や、パーミッション関連の操作が追加されている。

Class File
http://download.java.net/jdk6/docs/api/java/io/File.html

Mustang で File に追加されたメソッド

public boolean setWritable(boolean writable,boolean ownerOnly)
Sets the owner's or everybody's write permission for this abstract pathname.
public boolean setWritable(boolean writable)
A convenience method to set the owner's write permission for this abstract pathname.
public boolean setReadable(boolean readable,boolean ownerOnly)
Sets the owner's or everybody's read permission for this abstract pathname.
public boolean setReadable(boolean readable)
A convenience method to set the owner's read permission for this abstract pathname.
public boolean setExecutable(boolean executable,boolean ownerOnly)
Sets the owner's or everybody's execute permission for this abstract pathname.
public boolean setExecutable(boolean executable)
A convenience method to set the owner's execute permission for this abstract pathname.
public boolean canExecute()
Tests whether the application can execute the file denoted by this abstract pathname.
public long getTotalSpace()
Returns the size of the partition named by this abstract pathname.
public long getFreeSpace()
Returns the number of unallocated bytes in the partition named by this abstract path name.
public long getUsableSpace()
Returns the number of bytes available to this virtual machine on the partition named by this abstract pathname.

サンプルコード(ディスクスペースの取得)

package jp.in_vitro.codelets.io;

import java.io.File;

public class Codelet {

    public Codelet(){
        super();
    }
    
    public static void main(String[] args) {
        Codelet me = new Codelet();
        me.execute();
    }
    
    protected void execute(){
        File file = new File("c:\\");
        System.out.println("" + file.getAbsolutePath());
        System.out.println("FREE SPACE   : " + file.getFreeSpace());
        System.out.println("TOTAL SPACE  : " + file.getTotalSpace());
        System.out.println("USABLE SPACE : " + file.getUsableSpace());
    }
}

実行結果

c:\
FREE SPACE   : 2151354368
TOTAL SPACE  : 15002906624
USABLE SPACE : 2151354368

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

Mar 19, 2006

[Mustang] Normalizer にチャレンジ

Normalizer とは

java.text.Normalize は Mustang から導入された文字列処理用のクラス。 Unicode 文字列の正規化を行ってくれる。 今まで独自のコードでやっていた処理を Normalizer に置き換えられそうなのでチェックしてみた。

Class Normalizer
http://download.java.net/jdk6/doc/api/java/text/Normalizer.html
Enum Normalizer.Form
http://download.java.net/jdk6/doc/api/java/text/Normalizer.Form.html
Normalization Charts
http://www.unicode.org/charts/normalization/

Normalizer では、以下の 4 つの Normalization Form が定義されている。

  • NFC - Canonical decomposition, followed by canonical composition.
  • NFD - Canonical decomposition.
  • NFKC - Compatibility decomposition, followed by canonical composition.
  • NFKD - Compatibility decomposition.
同じ文字でもそれぞれの Form で文字コード上の表現が変化する。

変換結果

日本語を使用するアプリケーションで頻繁に変換処理が行われる文字をチェックしてみた。 NFKC 変換が現在の独自ロジックでの変換の置き換えに使用できそう。 但し、色々試してみたところ多少不足があるので単純な置き換えは無理。

ORIGINAL ->      NFC        NFD          NFKC          NFKD
-------------------------------------------------------------
¢ (00A2) ->   ¢ (00A2)  ¢ (00A2)  ¢ (00A2)  ¢ (00A2)
¢ (FFE0) ->   ¢ (FFE0)  ¢ (FFE0)  ¢ (00A2)  ¢ (00A2)
£ (00A3) ->   £ (00A3)  £ (00A3)  £ (00A3)  £ (00A3)
£ (FFE1) ->   £ (FFE1)  £ (FFE1)  £ (00A3)  £ (00A3)
¬ (00AC) ->   ¬ (00AC)  ¬ (00AC)  ¬ (00AC)  ¬ (00AC)
¬ (FFE2) ->   ¬ (FFE2)  ¬ (FFE2)  ¬ (00AC)  ¬ (00AC)
- (002D) ->   - (002D)  - (002D)  - (002D)  - (002D)
- (FF0D) ->   - (FF0D)  - (FF0D)  - (002D)  - (002D)
| (007C) ->   | (007C)  | (007C)  | (007C)  | (007C)
| (FF5C) ->   | (FF5C)  | (FF5C)  | (007C)  | (007C)
~ (007E) ->   ~ (007E)  ~ (007E)  ~ (007E)  ~ (007E)
~ (FF5E) ->   ~ (FF5E)  ~ (FF5E)  ~ (007E)  ~ (007E)
が (304C) ->   が (304C)  か? (304B3099)  が (304C)  か? (304B3099)
ぎ (304E) ->   ぎ (304E)  き? (304D3099)  ぎ (304E)  き? (304D3099)
ぱ (3071) ->   ぱ (3071)  は? (306F309A)  ぱ (3071)  は? (306F309A)
ぴ (3074) ->   ぴ (3074)  ひ? (3072309A)  ぴ (3074)  ひ? (3072309A)
㍉ (3349) ->   ㍉ (3349)  ㍉ (3349)  ミリ (30DF30EA)  ミリ (30DF30EA)
㌔ (3314) ->   ㌔ (3314)  ㌔ (3314)  キロ (30AD30ED)  キロ (30AD30ED)
㎜ (339C) ->   ㎜ (339C)  ㎜ (339C)  mm (006D006D)  mm (006D006D)
㎡ (33A1) ->   ㎡ (33A1)  ㎡ (33A1)  m2 (006D0032)  m2 (006D0032)
㍻ (337B) ->   ㍻ (337B)  ㍻ (337B)  平成 (5E736210)  平成 (5E736210)
㍼ (337C) ->   ㍼ (337C)  ㍼ (337C)  昭和 (662D548C)  昭和 (662D548C)
№ (2116) ->   № (2116)  № (2116)  No (004E006F)  No (004E006F)
㏍ (33CD) ->   ㏍ (33CD)  ㏍ (33CD)  KK (004B004B)  KK (004B004B)
℡ (2121) ->   ℡ (2121)  ℡ (2121)  TEL (00540045004C)  TEL (00540045004C)
㊤ (32A4) ->   ㊤ (32A4)  ㊤ (32A4)  上 (4E0A)  上 (4E0A)
㊥ (32A5) ->   ㊥ (32A5)  ㊥ (32A5)  中 (4E2D)  中 (4E2D)
㈱ (3231) ->   ㈱ (3231)  ㈱ (3231)  (株) (0028682A0029)  (株) (0028682A0029)
㈲ (3232) ->   ㈲ (3232)  ㈲ (3232)  (有) (002867090029)  (有) (002867090029)

サンプルコード

package jp.in_vitro.codelets.text;

import java.text.Normalizer;

public class Codelet {

    public Codelet() {
        super();
    }

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

    protected void execute() {

        String targets = "\u00A2\uFFE0\u00A3\uFFE1\u00AC\uFFE2\u002D\uFF0D\u007C\uFF5C\u007E\uFF5Eがぎぱぴ㍉㌔㎜㎡㍻㍼№㏍℡㊤㊥㈱㈲";
        System.out
                .println("ORIGINAL ->      NFC        NFD          NFKC          NFKD");
        System.out
                .println("-------------------------------------------------------------");
        for (char ch : targets.toCharArray()) {
            this.normalize("" + ch);
        }
    }

    protected void normalize(final String target) {
        String normalized = null;
        String normalizedHex = null;

        System.out.print("" + target + " (" + this.toHex(target) + ") -> ");

        normalized = Normalizer.normalize(target, Normalizer.Form.NFC);
        normalizedHex = this.toHex(normalized);
        System.out.print("  " + normalized + " (" + normalizedHex + ")");

        normalized = Normalizer.normalize(target, Normalizer.Form.NFD);
        normalizedHex = this.toHex(normalized);
        System.out.print("  " + normalized + " (" + normalizedHex + ")");

        normalized = Normalizer.normalize(target, Normalizer.Form.NFKC);
        normalizedHex = this.toHex(normalized);
        System.out.print("  " + normalized + " (" + normalizedHex + ")");

        normalized = Normalizer.normalize(target, Normalizer.Form.NFKD);
        normalizedHex = this.toHex(normalized);
        System.out.print("  " + normalized + " (" + normalizedHex + ")");

        System.out.println();
    }

    protected String toHex(final String str) {

        StringBuffer buf = new StringBuffer();
        for (char ch : str.toCharArray()) {
            buf.append(Integer.toString((int) ((ch >> 12) & 0x0F), 16)
                    .toUpperCase());
            buf.append(Integer.toString((int) ((ch >> 8) & 0x0F), 16)
                    .toUpperCase());
            buf.append(Integer.toString((int) ((ch >> 4) & 0x0F), 16)
                    .toUpperCase());
            buf.append(Integer.toString((int) (ch & 0x0F), 16).toUpperCase());
        }
        return new String(buf);
    }
}

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

Mar 18, 2006

[Mustang] Java から Web ブラウザと MUA を起動

Mustang を眺めていたら、何と Web ブラウザと MUA を起動する API を発見!! 早速チャレンジ。
単純に API を呼んでみたところ何の障害もなく Web ブラウザの起動に成功した。
普段使いのメールアドレスが全て Gmail になっているため、MUA は起動確認できず。 そもそも MUA がインストールされていない orz
Mustang では Web ブラウザや MUA 以外にもファイルに関連づけられたアプリケーションの起動ができる。 試しに Explorer とテキストエディタを起動してみたが、どちらもうまくいった。

Class Desktop
http://download.java.net/jdk6/docs/api/java/awt/Desktop.html

サンプルコード

package jp.in_vitro.codelets.awt;

import java.awt.Desktop;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;

public class Codelet2 {

    public Codelet2() {
        super();
    }

    public static void main(String[] args) throws MalformedURLException,
            IOException, URISyntaxException {
        Codelet2 me = new Codelet2();
        me.runWebBrowser();
        me.runMailer();
        me.runExplorer();
        me.runTextEditor();
    }

    protected void runWebBrowser() throws MalformedURLException, IOException,
            URISyntaxException {
        Desktop.getDesktop().browse(
                new URL("http://www.in-vitro.jp/blog").toURI());
    }

    protected void runMailer() throws IOException {
        Desktop.getDesktop().mail();
    }

    protected void runExplorer() throws IOException {
        Desktop.getDesktop().open(new File("c:\\"));
    }

    protected void runTextEditor() throws IOException {
        File dummyTextFile = new File("c:\\hogehoge.txt");
        OutputStream os = null;
        try {
            os = new FileOutputStream(dummyTextFile);
            os.write("this is temporary file.".getBytes());
        } finally {
            if (os != null) {
                os.close();
            }
        }

        Desktop.getDesktop().open(dummyTextFile);
    }
}

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

Mar 12, 2006

[Derby] Derby を Tomcat 5.5 の DataSource に設定する方法

Server Mode で起動した Derby を Tomcat 5.5 に DataSource として登録する方法をメモ。 Tomcat 5.0 → 5.5 で設定方法が変わったことで、意外と設定に時間がかかってしまった。

The Apache Tomcat 5.5 Servlet/JSP Container JNDI Datasource HOW-TO
http://tomcat.apache.org/tomcat-5.5-doc/jndi-datasource-examples-howto.html

Derby を Server Mode で起動

Derby 10.1.2.1 を前提とする。

> set JAVA_HOME=c:\jdk1.5.0_06
> set DERBY_INSTALL=c:\db-derby-10.1.2.1-bin
> cd db-derby-10.1.2.1-bin\frameworks\NetworkServer\bin
db-derby-10.1.2.1-bin\frameworks\NetworkServer\bin>startNetworkServer.bat
サーバーは、ポート 1527 で接続を受け入れる準備ができました。

Tomcat 5.5 の設定

Tomcat 5.5.15 を前提とする。

  1. Tomcat に Derby の JDBC ドライバを登録する。 derbyclient.jar、derbynet.jar、derbytools.jar を %CATALINA_HOME%/common/lib/ にコピーする。
  2. DataSource の設定を行う。 %CATALINA_HOME%/conf/server.xml に下記の設定を追加する。
    <Host name="localhost" 
          appBase="webapps"
          unpackWARs="true" 
          autoDeploy="true"
          xmlValidation="false" 
          xmlNamespaceAware="false">
    
      <Context path="/myapp" 
               docBase="myapp"
               reloadable="false" 
               crossContext="true">
    
        <Resource name="jdbc/TestDB" 
                  auth="Container" 
                  type="javax.sql.DataSource"
                  driverClassName="org.apache.derby.jdbc.ClientDriver"
                  url="jdbc:derby://localhost:1527/derbyDB;create=true"/>
      </Context>
    <Host>
    
ちなみに、Host → Context → Resource という階層構造にしないと、何故か url や driverClassName が設定されないために
Cannot create JDBC driver of class '' for connect URL 'null' java.sql.SQLException: No suitable driver
という例外が発生する。

Web アプリケーションの設定

<web-app>
  <resource-ref>
    <description>DB Connection</description>
    <res-ref-name>jdbc/TestDB</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
  </resource-ref>
</web-app>

アプリケーションからの呼び出し

普通に JNDI 経由で DataSource を取得すれば良い。

Context context = new InitialContext();
Object obj = context.lookup("java:comp/env/jdbc/TestDB");
DataSource dataSource  = (DataSource)obj;
Connection connection = dataSource.getConnection();

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

Mar 11, 2006

[Misc] JavaScript 用デバッグコンソール

JavaScript 用のデバッグコンソールを作成してみた。 alert() を使用すると、誤って無限ループに陥った際に Web ブラウザを強制終了せざる得なくなることがある。 それを防ぐため & もう少し使いやすいインタフェースを用意するために DebugConsole クラスを作成した。

DebugConsole

HTML 内で適当に読み込んで呼び出すと、Web ブラウザのウィンドウ右上にデバッグコンソールが開く。 後は debug メソッドで適当に確認したいメッセージをデバッグコンソールに書き出すだけ。

/*******************************************************************************
 *
 *  DebugConsole
 *    copyright(c) 2006 in-vitro.jp, all rights reserved.
 *
 *
 *  REQUIRED
 *    +MS Windows XP
 *    +Internet Explorer 6
 *
 *  USAGE(1) - SIMPLE
 *    var debugConsole = new DebugConsole();
 *    debugConsole.open();
 *    debugConsole.debug("this is a debug message");
 *    debugConsole.close();
 *
 *  USAGE(2) - with initializer
 *    function myInitializer(debugConsole) {
 *      debugConsole.style.backgroundColor = "#ffffff";
 *      debugConsole.style.border = "1ps solid #000000";
 *      return "this is a header";
 *    }
 *    var debugConsole = new DebugConsole(myInitializer);
 *    debugConsole.open();
 *    debugConsole.debug("this is a debug message");
 *    debugConsole.close();
 *
 *  LICENSE
 *    Creative Commons Attribution-ShareAlike 2.1
 *    @see http://creativecommons.org/licenses/by-sa/2.1/jp/
 *
 *******************************************************************************/

/**
 * Construct DebugConsole
 *
 * @param initializer [optional] function which initialize DebugConsole.
 */
function DebugConsole(initializer) {
  document.getElementsByTagName('body')[0].innerHTML += "<div id=\"debugConsole\"></div>";
  this.debugConsole = document.getElementById('debugConsole');

  if(initializer == undefined || initializer == null) {
    this.header = DebugConsole_initializer(this.debugConsole);
  } else {
    this.header = initializer(this.debugConsole);
  }

  this.debugConsole.style.position = "absolute";
  this.debugConsole.style.display = 'none';
  this.debugConsole.style.top = "0px";
  this.debugConsole.style.right = "0px";
}

/* register member functions to DebugConsole */
DebugConsole.prototype.open = DebugConsole_open;
DebugConsole.prototype.close = DebugConsole_close;
DebugConsole.prototype.debug = DebugConsole_debug;
DebugConsole.prototype.clear = DebugConsole_clear;
DebugConsole.prototype.move = DebugConsole_move;
DebugConsole.prototype.moveInternal = DebugConsole_moveInternal;

/**
 * Default DebugConsole Initializer
 */
function DebugConsole_initializer(debugConsole) {
  debugConsole.style.backgroundColor = "#eeeeee";
  debugConsole.style.border = "3px solid #cccccc";
  debugConsole.style.width = "250px";
  debugConsole.style.height = "300px";
  debugConsole.style.padding = "0.5em";
  return "【DEBUG CONSOLE】";
}

/**
 * Open DebugConsole
 */
function DebugConsole_open() {
  // move DebugConsole periodically.
  this.timerId = setInterval(this.move, 1000);
  // show DebugConsole
  this.debugConsole.style.display = 'block';
  this.clear();
}

/**
 * Close DebugConsole
 */
function DebugConsole_close() {
  this.debugConsole.style.display = 'none';
  clearInterval(this.timerId);
}

/**
 * Append message to DebugConsole
 */
function DebugConsole_debug(message) {
  this.debugConsole.innerHTML += message + "<br>";
}

/**
 * Clear DebugConsole
 */
function DebugConsole_clear() {
  if(this.header == undefined || this.header == null) {
    this.debugConsole.innerHTML = "";
  } else {
    this.debugConsole.innerHTML = this.header + "<br>";
  }
}

/**
 * Move DebugConsole to NORTH-EAST corner (INTERNAL USE ONLY)
 */
function DebugConsole_move() {
  this.debugConsole.moveInternal()
}

/**
 * Move DebugConsole to NORTH-EAST corner (INTERNAL USE ONLY)
 */
function DebugConsole_moveInternal() {
  this.debugConsole.style.top = document.body.scrollTop + "px";
  this.debugConsole.style.right = "0px";
}

ダウンロード

余りニーズがあるとも思えないけれど、とりあえず。
debugconsole.js

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

Mar 10, 2006

[Blosxom] Bloxsom のエントリーを一覧表示する

Blosxom のエントリー一覧を確認したくなることが結構あるので、簡単なスクリプトを作成してみた。 このスクリプトは Blosxom starter kit 環境下で、エントリーファイルの一覧を HTML で表示する。 Blosxom starter kit の設定ファイルを参照している都合で、ノーマルの Blosxom 環境下では動作しないかもしれない(未確認)。

Blosxom エントリー一覧表示スクリプト

$BLOG_HOME 直下に適当な名前でスクリプトを設置し、パーミッションを 755 にすると動作する。

#!/usr/bin/perl

package blosxom;

eval { require './config.cgi'; };
die "Failed to load configuration file.\n$@" if $@;

use vars qw! $datadir $url $depth $file_extension %files !;

use strict;
use FileHandle;
use File::Find;
use File::stat;
use Time::localtime;
use Time::Local;
use CGI qw/:standard :netscape/;
use CGI::Carp;

my $fh = new FileHandle;

# Use the stated preferred URL or figure it out automatically
$url ||= url();
$url =~ s/^included:/http:/; # Fix for Server Side Includes (SSI)
$url =~ s!/$!!;

# Drop ending any / from dir settings
$datadir =~ s!/$!!;
  
# Fix depth to take into account datadir's path
$depth and $depth += ($datadir =~ tr[/][]) - 1;

# find entry files
my @files;
find(
  sub {
    my $d; 
    my $curr_depth = $File::Find::dir =~ tr[/][]; 
    return if $depth and $curr_depth > $depth; 
    my $file = $File::Find::name;
    if($file =~ m/(.)*\.$file_extension$/i) {
      push(@files, $file);
    }
  }, $datadir
);

# soft entry files
@files = sort {
  $a =~ /.*\/(.+)/;
  my $filename_a = $1;
  $b =~ /.*\/(.+)/;
  my $filename_b = $1;
  $filename_b cmp $filename_a;
} @files;

# print results;
print "Content-type: text/html\n\n";
print "<html>";
print "<head><title>";
print "list entries in ";
print $datadir;
print "</title></head>";
print "<body>";
print "list entries in ";
print $datadir;
print "<ol>";
foreach my $file (@files) {
  $file =~ /.*\/(.+)/;
  my $filename = $1;
  my $fileurl = $file;
  $fileurl =~ s/$datadir//g;
  $fileurl =~ s/\.$file_extension/\.html/g;
  $fileurl = $url . $fileurl;
  print "<li>";
  print "<a href=\"";
  print $fileurl;
  print "\">";
  print $filename;
  print "</a>";
  print " <span style=\"font-size: x-small;\">(";
  print $file;
  print ")</span>";
  print "</li>";
}
print "</ol>";
print "</body></html>";

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

Mar 09, 2006

[Misc] AJAX におけるクライアントサイドのキャッシュ機構

作り方にもよるが、非AJAX よりも AJAX の方がサーバサイドへのリクエスト数が増える。 HTML で問題になりがちな部分更新を AJAX で解決しようとすればするほどリクエスト数が増えてしまう。 というわけで、サーバサイドの負荷を減らすべく AJAX でクライアントサイドのキャッシングを実施する方法を思案中。
ちなみに、考えているだけで実際に試したわけではないので要注意。

AJAX におけるキャッシング

Cookie

Cookie にデータを保持する。JavaScript がローカルのファイルシステムにアクセスできる唯一の方法。

非表示レイヤー

JavaScript で表示されない(display: none)レイヤーを作成し、その中にデータを保存する。

  • 永続化できない(HTMLリロードで消える)
    →但し、サーバサイドと連携すれば多少は永続化出来る。
  • (一応)サイズ制限はない
  • オンメモリで保持されるため、クライアントの負荷が大きい?

Cookie のサイズ制限を考えると、非表示レイヤーを使う方が現実的か。 実際に運用されているサービスはどうしているのだろう?? 今度調べてみよう。

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

Mar 08, 2006

[Misc] MTASC にチャレンジ

MTASC とは

MTASC は、Motion-Twin ActionScript 2 Compiler の略。 名前の通り、ActionScript2 のコンパイラ。 オープンソースで提供されている。 MTASC を使用することで Flash の swf ファイルを簡単に費用をかけずに生成できる。

MTASC 公式サイト
http://www.mtasc.org/#download
MTASC ダウンロード
http://www.mtasc.org/#download

ActionScript に関する資料

ActionScript に関する知識が全く無いので、参考になりそうなサイトをメモ。

FLASH-jp フォーラム
http://www.flash-jp.com/
ActionScript ガイド
http://www.macromedia.com/jp/support/flash/technotes.html#actionScript
ActionScript 2.0 の学習
http://livedocs.macromedia.com/flash/8_jp/main/00001214.html
Flash の ActionScript チュートリアル集
http://www.3enhancedesigners.com/tutorials/flash/flash_actionscript.asp
Flash ActionScript Helper
http://homepage3.nifty.com/ginga-b/
Flash ActionScript 講座
http://www.game3rd.com/flash/action/
ActionScriptPlugin plugin
http://xdoclet.codehaus.org/ActionScriptPlugin

サンプルコード

とりあえず Hello World だけチャレンジ。

class HelloWorld {
  static var me : HelloWorld;

  function HelloWorld() {
    _root.createTextField("textfield",0,0,0,800,600);
    _root.textfield.text = "Hello ActionScript World !!";
  }

  static function main(mc) {
    me = new HelloWorld();
  }
}
コンパイルはコマンドラインから実行する。
> mtasc -swf helloworld.swf -main -header 800:600:20 HelloWorld.as

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

Mar 07, 2006

[Misc] ジェノグラフィック・プロジェクトに参加

ジェノグラフィック・プロジェクトとは

ジェノグラフィック・プロジェクトとは、「はるか遠い祖先がたどった遺伝学的な旅や実際にこの地球上を移動したルートなどについて知ることが目的」のプロジェクトらしい。 参加者は自分の DNA 情報をプロジェクトに送付すると、自分の祖先がどの大陸からどこを経由して自分へとつながっているのかを知ることができる。 プロジェクトのサイトによると、

男性参加者:Y染色体による分析。父方の直系の祖先が誕生した起源を明らかにできます。
女性参加者:ミトコンドリアDNAによる分析。母方の直系の祖先が昔に移動する際の起源を明らかにできます。
だそうだ。 これは面白そうだということで、早速参加してみることに。
ジェノグラフィック・プロジェクト
http://nng.nikkeibp.co.jp/nng/genographic/project.shtml
Genographic Project Public Participation Kit Non-U.S. and Non-Canada Delivery
http://shop.nationalgeographic.com/shopping/product/detailmain.jsp?itemID=2346&itemType=PRODUCT

Genographic Project Public Participation Kit

申し込んで 1 週間程でキットが送られてきた。 キットにはプロジェクト解説の DVD や DNA 採取器具などが含まれている。 DNA 採取は頬の内側を付属の器具でこするだけなので、手間要らずで痛みもない。 そういえば、小学校か中学校の実験でも頬の内側から細胞を採取したことがあったっけ。 返送して 4 ~ 6 週間で結果が分かるそうだ。楽しみだ。

[Genographic Project Public Participation Kit]
パッケージ
[キットの中身]
キットの中身
[DNA 採取器具]
DNA 採取器具
[採取した DNA]
採取した DNA

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

Mar 06, 2006

[Book] 初めてのアジャイル開発

書籍情報


初めてのアジャイル開発

レビュー

内容的には
アジャイルと規律の方
が良い感じがする。 ただ、多少視点が異なるのでどちらも読んで損はないと思う。 スクラム、XP、UP、Evoというアジャイル手法を単純に紹介するだけでなく、それぞれの手法の良いところを組み合わせる方法も紹介されており興味深い。

書籍内で紹介されていたThe New New Product Development Gameも併せて読んでみた。 この記事は 1986年にHarvard Business Reviewに掲載されたものなのだが今でもオンラインで入手可能。

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

Mar 05, 2006

[Subversion] Subversion 管理用ディレクトリの ".svn" と "_svn"

Subversion 管理下のファイルをチェックアウトすると、管理用ディレクトリとして ".svn" が作成される。 それが、TortoiseSVN をバージョンアップした途端に "_svn" に変わってしまったという話を聞いた。 となると、TortoiseSVN をバージョンアップするわけにいかなくなってしまうので原因を調べてみた。 原因は Subversion 1.3 のリリースノートに記載されていた。

The "_svn" hack is now officially supported: since some versions of ASP.NET don't allow directories beginning with dot (e.g., ".svn", the standard Subversion working copy administrative directory), the svn command line client and svnversion now treat the environment variable SVN_ASP_DOT_NET_HACK specially on Windows. If this variable is set (to any value), they will use "_svn" instead of ".svn". We recommend that all Subversion clients running on Windows take advantage of this behaviour. Note that once the environment variable is set, working copies with standard ".svn" directories will stop working, and will need to be re-checked-out to get "_svn" instead.

".svn" が "_svn" に変わった環境で環境変数を調べてみてもらったところ、SVN_ASP_DOT_NET_HACK=1 となっていた。 結局、SVN_ASP_DOT_NET_HACK を設定しなければ今まで通り ".svn" のママだということが分かった。 TortoiseSVN をバージョンアップしても問題は無さそうということで一安心。

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

Mar 04, 2006

[VMWare] VMWare と Xen の違い

VMWareXen はどちらも仮想化ソフト。 同じ仮想化ソフトではあるけれど、仮想化の実現方式は結構異なるらしい。 Interview on Xen with Manuel Bouyerで Xen と VMWare の実装の違いが紹介されていた (vimrc diaryさんのXenとVmwareの違い [xen]経由)。

VMware will emulate real hardware so that an unmodified OS can run on top of the virtualizer. Just run an OS in VMware, and this OS will see some kind of VGA adapter for the console along with the usual PS/2 keyboards and mouse, some kind of network interface (a DEC tulip if my memory is right), and some kind of IDE or SCSI adapter for mass storage. To achieve this, the virtualizer will have to emulate these devices. This means emulating the registers and interrupts, quite often with MMU faults when these fake registers are accessed. This means that a single I/O operation will most likely require several context switches. The same goes for the MMU: accesses to privileged CPU registers, page tables and use of privileged instruction will all generate context switches.

The Xen's virtualizer (the hypervisor) doesn't emulate real hardware but offers an interface to the guest OS for these operations. This means that the guest OS will have to be modified to use these interfaces. But then these interfaces can be optimized for the task, allowing it to batch large numbers of operations in a single communication with the hypervisor, and so limiting the number of context switches required for I/O or MMU operations.

ということは、VMWare より Xen の方が高速なのだろうか?? 調べてみると、Xen のサイトに Xen と VMWare のパフォーマンスの比較が載っていた。 確かに、VMWare より Xen の方が高速の様だ。 とは言え、気軽に使うには普通の OS がそのままゲスト OS として使用できる VMWare の方が楽なので、個人的には VMWare を使っていくつもり。

ついでに少し調べていたら仮想化技術の実現方式の違いを解説したページを発見した。

仮想化技術のアプローチと実装 ~ VMwareから要注目技術Xenまで ~
http://www.atmarkit.co.jp/flinux/special/vm/vm02.html

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

Mar 03, 2006

[Maven] リモートリポジトリをローカルのストレージに置く方法

Maven2 のリモートリポジトリをプロジェクトホームの下に置く方法をメモ。 リモートリポジトリをサーバに置くことができないこともあるので。 pom.xml に下記の設定を行うと、$PROJECT_HOME/repository がリモートリポジトリとして認識される。

<pom>
  <repositories>
    <repository>
      <id>softwareframework-repository</id>
      <name>software framework repository</name>
      <url>file://${basedir}/repository</url>
    </repository>
  </repositories>
</pom>

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

Mar 02, 2006

[Maven] Maven2 で J2SE 5.0 のソースコードをコンパイルする方法

Maven2 で J2SE 5.0 のソースコードをコンパイルするためには pom.xml に下記の設定を行う必要がある。 至る所で紹介されている情報だけれど、頻繁に行う設定なのでメモしておく。

<build>
  <plugins>
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
      </configuration>
    </plugin>
  </plugins>
</build>

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

Mar 01, 2006

[Maven] CARGO にチャレンジ

CARGO とは

CARGO は、アプリケーションサーバをラッピングするオープンソースのライブラリ。 Maven、Maven2、Ant 用のプラグインが提供されており、それらから簡単にアプリケーションサーバの起動、停止などを実現することができる。 Maven2 から CARGO を使用して Tomcat の起動とアプリケーションのディプロイを行ってみた。

CARGO 公式サイト
http://www.geotools.org/display/CARGO
CARGO Maven2 plugin
http://www.geotools.org/display/CARGO/Maven2+plugin
Container Support
http://docs.codehaus.org/display/CARGO/Home#Home-Containersupport

pom.xml の設定

CARGO で Tomcat 5 を扱うためには、pom.xml に下記の設定を行う。

<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.cargo</groupId>
      <artifactId>cargo-maven2-plugin</artifactId>
      <executions>
        <execution>
          <id>tomcat-execution</id>
          <phase>package</phase>
          <goals>
            <goal>start</goal>
          </goals>
          <configuration>
            <wait>false</wait>
            <container>
              <containerId>tomcat5x</containerId>
              <zipUrlInstaller>
                <url>
                  http://www.apache.org/dist/tomcat/tomcat-5/v5.5.15/bin/apache-tomcat-5.5.15.zip
                </url>
                <installDir>
                  ${installDir}
                </installDir>
              </zipUrlInstaller>
            </container>
            <configuration>
              <dir>
                ${project.build.directory}/tomcat5x/container
              </dir>
            </configuration>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
この設定を行った後 "mvn package" を実行すると Tomcat 5 の起動とディプロイを CARGO が自動的に行ってくれる。 Tomcat 5 は CARGO が勝手にダウンロードして、$PROJECT_HOME/target/tomcat5x/container にインストールしてくれる。 "mvn clean" で target が削除されてもその次の実行時に再度ダウンロードされる。 Tomcat が起動しているかどうかは "http://localhost:8080/cargocpc/" にアクセスすることで確認できる。

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