システム・PC

Javaファミリーのキモチが見えてきた

なんとなく毛嫌いしていたJavaですが、最近Javaの思想というのが最近見えてきたような気がします。と言っても、あ〜Javaならこう書けばいいのかとか、あ〜Javaならこう設計するといいな。といった感じですか。まぁ、この世界も奥が深そうなので、まだまだでしょうが。

でもって本題。

ン年ぶりにwebアプリを書いています。

要求仕様などもろもろの事情からJBoss3.2をたてて、その上で日本語を扱うwebアプリを書いているんですが、その中で日本語が正しくハンドルされないという問題点にぶち当たりました。JBossはデフォルトでTomcatを使用してるんで、そのあたりに問題があるんじゃないかと、いろいろ調べてみると どうもrequest.getParameter()で正しく encodeした文字列が取得できてないようです。

getParameter()する前にsetCharacterEncoding()で encodingをUTF-8にしているのでここで正しくStringが生成されそうなものですが、う〜む・・・

ワタシはServletプログラムの経験が薄いので、なかなかgoogle検索のカンどころがつかめず、この件かなり悩みました。Apacheならソースも何度も眺めてるし、perl CGIなら腐るほどプログラムしてるので慣れているんですがねぇ・・・

それでも、いろいろ探したらTomcatのBugzillaで次の記述にぶちあたりました。

http://issues.apache.org/bugzilla/show_bug.cgi?id=23929

まぁようするに、

1)URIにASCII文字列意外の文字があったらw3の規格的にはそれはUTF-8でencodingして、%xxに置き換えて送るというのが正しい。
2)しかし現実のクライアント(ブラウザ等)はそう実装されていないものが多々ある
3)そのため様々な問題が起きている
※いままで、このあたりマッタク気にしたことなかったなぁ〜(笑)

4)そこで、Tomcatでは(デフォルトでは)こう実装されている
- Tomcat4では(規格からは外れているが) Body(すなわち本文)と同じ Encodingを使用していると解釈してURIをdecodeする。
- Tomcat5ではBodyと同じEncodingをしない。デフォルトの Encodingは ISO-8859-1であるので、それでdecodeする。

で、最後にTIPSとして
・こういうことをしたいならPOSTを使えばいい。

ということで、POSTにしたら確かに直りました・・・バンザーイ!!

まぁようするに、Tomcat4ではワタシが思っていたように動作するようになっていたわけで(それは規格として間違っているのだが)、世の中にはTC4ベースの良解説ページが沢山あり、得てしてそういうページは上位にくるので、google検索の誤解スパイラルに陥ってしまっていたようです。

分かってしまえばそれをキーワードに検索すれば、解決法や同じことで悩んでる人がワラワラ出てくること出てくること。例えば、サーバ側の設定で解決する方法としては、以下のようなページがありました。

http://www.atmarkit.co.jp/fjava/rensai3/mojibake03/mojibake03.html

で、Bugzillaのページ見ておもったんですが、Tomcat5もURIパラメータの解釈は結局のところ規格外なんですよね。UTF-8で規格的に正しくエンコードされたURLでもISO8859-1で解釈するんですから。

このあたり、別なservletとの互換性も絡んでいるのでしょうか?なかなかJavaの世界も深いようで・・・

MacからPostgreSQLを操作する

PostgreSQLは普通にフリーソフトなので、クライアントだけインストールすれば普通に操作できるんですが、どうせならMS Access風味にODBCでリンクしてテーブルを操作したいというものです。

Mac OS XにもOfficeはあるんですが、Accessが無いので、別なソフトでいうことになるんですが、これはMacの世界のデーターベースソフトの決定版のFileMakerProでよさげな感じです。(ダメだったりしたらどうしよう・・・・)


あとはPostgreSQLのODBCドライバです。何かよいものがないかと探していたら、こんなものが見つかりました。

PostgreSQLでもMySQLでも使えるらしいです。お試し版があったので、さっそくダウンロードしてみました。

インストールは簡単でつつがなく終了。とらいえず iODBC Administratorを実行して確認してみたところ、無事組み込まれているようです。

SCR1.jpg

さっそくUser DSNを設定して MS Excelから

データ>外部データの取り込み>新しいデータベースクエリ

で、インポートしてみたところ、つつがなくPostgreSQLのサーバからテーブルを取り込むことができました。Excelだと取り込むだけで、編集しても元のデータベースが変化しないのでこれ以上試せませんでしたが、まぁここまで出来るなら普通に使えそうですね。

あとはFileMaker Proを買うだけ?

なお、ワタシはMicrosoft Office v. Xのバンドル版を使用しているのですが、Excelから取り込むときはQuery X for Macというものを別途インストールしないとできませんでした。ご参考まで。

追記 FileMakerも基本的にインポートしかできないようです。(´・ω・`)

FreeBSDのバージョンアップ

自宅で使っているWindowsMEからFreeBSDにsambaでどうしてもつながりません。

まぁWindowsのバージョンをあげるという手もあるんですが、そもそも月に一回くらいしかつかわないマシンなんで、買い換える気もしません。

で、いろいろやっているうちに、別のサーバで動いている比較的最近のsambaには接続できるので、どうもsambaのバージョンが古いのが原因ではないかという結論に。

そのついでにOSがバージョンがFreeBSD4.3ちゅう、これまた前世紀のバージョンなので、こちらもあげることにしました。

とはいっても、作業としては、cvsupで /usr/srcを最新にして make worldをするだけなんですけどね。w インストールするときにuserやgroupがないという問題がありましたが、ここは手動追加で乗り切りました。(4.3のmergemasterには-pオプションがない・・・) で、/usr/ports/net/samba3 の下でガツンとmake・・・ 楽勝とおもわれましたが、configureでエラーが・・・

configure: error: libkrb5 is needed for Active Directory support
どうせ、使いもしないKerberosでのエラーというのがシャクです。w まぁADSをオプションから削除してmakeすればいいんでしょうが、そもそもこのエラーがでるのが不思議です。 そこで /usr/lib/libkerb*のタイムスタンプをみたら変わってない・・・なるほど make worldだけでは kerberosは更新されないんですね。 -DMAKE_KERBEROS5をつけてmake worldしたら無事更新されたようです。また勉強になりました。

static const char [100]


main()
{
static const char a[100] = "A";
}


a[0]だけが'A'で a[1]以降は全部0で初期化されそうな感じがしますが、実際はそうならない処理系があるようです。具体的にはMacOSX.2ですが・・・(gcc version 3.3)

なお、constを取れば私が期待した通りに初期化されます。


main()
{
static const char a[100] = "A";
static const char b[100] = {'Z'};
}


とすると、bは当然100個確保されますが、aは最初の4バイトのみA\0\0\0でその次にはbの中身がみえちゃってます。

つまりa[4]でb[0]が見えるという・・

仕様的にはどっちが正しいのだろう?

aio_read

aio_read()というのは非同期にreadするという関数です。普通のreadは一定のデータを読み終わるまで戻ってこないんですが、こいつは即座に戻ってきます。

したがって、戻ってきた直後はデータがない可能性もあるわけですが、その間ベツな処理をあらかじめしておいて、その後に読んだデータの処理をすることができます・・・というような関数なのでしょう。

これが使い道があるのかどうかはおいといて、調査する必要が出てきたので、軽くFreeBSDで調査をしてみました。

まずは、カンタンなサンプルを作成して実行してみました。

するとENOSYSというエラーが。つまり、サポートされていないと・・・

うーむとばかりにカーネルソースをみてみたら、VFS_AIOが定義されていないときは、全てエラーとなるようにコーディングされてました。

というわけで、早速

options VFS_AIO

を追加してカーネル再コンパイル。無事動きました。ソースがあるって素敵ですね。ふぅ

って本来の目的は全然進んでないやん・・・・

日付からEpochを求める

Epochとは FreeBSDのman 3 time で見てみると

1970/1/1 00:00:00 (UTC)からの経過秒数

と定義されているようです。

UTCには閏秒があったりして厄介です。また初期実装エンジニアの勘違い(!?)もあって上記のように実装されていないシステムが一般的で、閏秒はなかったこととして計算するのが主流のようです。いうなれば原子時(TAI)ベースといったところでしょうか?これについては語ると長くなりますので割愛します。詳細はここみてください。

今回は現在の日付からepochを求めるお話です。

ローカルタイムからepochを求めるには mktime()という関数を使えばよろしい。これはマニュアルに書いてあります。日本の場合はこれで終了です。

問題はサマータイムのある地域の場合です。業務で必要なので調べてみました。

簡単のためロンドンについて書きます。

ロンドンでは3月の最終日曜日の深夜1時から 10月の最終日曜日の1時までがサマータイムとなります。(どちらもGMT)

入るときは1時間だけ時間が飛びます。つまり00:59:59の次が02:00:00となります。その間の時刻は存在しません。

戻るときは1時間だけ時間が巻き戻ります。01:59:59の次が01:00:00になります。

厄介なのは後者です。前者は mktimeライブラリがよろしくやってくれますが、後者は時刻だけからでは、サマータイム終了前なのか後なのか判断できないので、わかりません。

これはプログラマが責任を持って渡してやらなければなりません。それが struct tmのtm_isdstメンバです。

tm_isdstを正にするとサマータイム内、0にするとサマータイム外として判断します。負の値を設定するとよろしくやってくれるようで、中間の30分の前後でわけてくれるようです。

なお、JSTで実行する場合はサマータイムが存在しないので、tm_isdstを正にしておくと、常にエラー(-1)になります。年月日、時分秒だけ代入しておいて変換しても一向に-1しかmktimeが返さないので、ちゃんと0とか-1を代入してからmktimeを実行しましょう。

通電。サーバ再起動

サーバのうちの1つ(FreeBSD)のシャットダウン画面を見ていたら

552d5h6m44s

と出ました。

どうもこのマシンは552日間も連続稼動していたもようです。ここまで、電源が切られていないと、起動時に何かトラブルがあるんじゃないかとおそるおそる起動したら・・・・

案の定起動後固まりやがりました。_| ̄|○ なんてお約束な・・・ 泣く泣くリセットして再起動したらなにやら安定した模様ですが・・・画面にHDのCRCエラーが。危険なニオイがします。CRCエラーが出ているところはRAID組んでてミラーになってるところなんですが、うーむ・・・・ とりあえずそろそろリプレースを考慮すべきですね。 続いて、次に問題が発覚したのがISDN。いまさらISDNかよ!といわれそうですが、問題になってるのは電話とFAXがつながっているISDN機器でして・・・こちらが電源が入らない!! 古今東西電源が入らないときは、しばらく休ませて、叩けばよいの風習により斜め45度よりチョップをかまし、無事電源が入りました。 こっちもリプレースせんといかんか・・・・(ホントいまさらながらなんですが・・・)

VAIO-Uで今時2万円

DSC00464.jpg


VAIO-Uの外付けのDVD-ROMドライブを買ってしまいました。というのも普通のiLinkで繋ぐドライブだとそのドライブから起動しないんです。まぁ普通iLinkからは起動しないので、そりゃそうかと思えばそうなんですが、例えば完全にパーティションをぶっ壊してしまった場合など、希にドライブから起動したいときというのがあります。

でもってこの専用ドライブ(PCGA-DVD1/A)の値段が2万円。高いですねぇ。

しかも、iLinkのコネクタの横に電源取得用のコネクタもくっついててACアダプタなしでも動くようなケーブルになってるんですが、これが使えるのは当然VAIOのノートだけ。

しかもこのケーブル以外のケーブルが同梱されていないから(別売りか?)VAIO以外では電源を取る手段がなく、使えないという・・・_| ̄|○

これでCDから起動しなければ暴れるところですが、試しにFreeBSDのインストールCDをつっこんでみたら、無事起動しました。

とりあえずよかったよかった・・・・でもFreeBSDはインストールしないけどね。

ところで、このACアダプタどこでうってるんでしょ?AC10Vとは書いていますが、SonyStyleでは売ってないようだし・・・別に買う気はないんですが、気になります。

慣れてないrubyプログラム

rubyの正規表現の^の挙動について数時間悩みました。詳しい人には既知なんでしょうが、perlと挙動が違うんですねぇ。

rubyの^は文字列の先頭および改行コードの次にマッチする。(確かに行頭だ!!)
perlは文字列の先頭だけ。

ですので、文字列のなかに改行コードがあると動作が異なります。私自信、perlスタイルで動作することを期待して何度もプログラムを書いているので、まさかこんな違いがあるとはヤラレました。

例えば次のプログラムはマッチします。


a = "123¥n456¥n789¥n"
p /^7/.match(a)


では、文字列の先頭で確実にマッチさせたいときはどうするのか?というと¥Aを使えば全て解決です。ちなみに後ろは¥zまたは¥z。大文字と小文字で最後の文字が改行のときの挙動が違います。

でもってperlのマニュアルの該当部分も読んでみました。rubyと同じ挙動にするにはmをつければいいようです。例えば次のプログラムはマッチします。


"123¥n456¥n789¥n" =~ /^7/m && print "match¥n"


perlにはまだまだ知らない機能が隠されているようです。奥深いですねぇ。

RMagickを使ってみた


フリーソフトにかかわらず、最近のドキュメントはhtmlで書いてあるのがあたりまえみたいです。というわけでman大好きのワタシはカナリ悲しい思いをしています。使いにくいったらありゃしない。w3mとかも入れてみましたが、TABで移動してリンクをたどるのがやっぱメンドい。結局HTMLをgrepしてキーワードをサーチしてlessで見ているワタシが気がついたらいました。



さて今日の目的はRMagickつかってイメージのwidthとheightを取得すること。まぁこんなカンタンなことくらいカンタンにできるでしょう。だいたいにおいてfileコマンドですらできます。


BTW。チャレンジすること1時間、どうにもカンタンに出来ませぬ。ドキュメントすみからすみまで読んでみましたが、らしきものがない・・・・

例えばこんな例

#!/usr/local/bin/ruby

require 'RMagick'

p Magick::Image.ping('wotaku2.gif')[0]

で、これを実行すると

"wotaku2.gif GIF 1188x910+0+0 PseudoClass 256c 8-bit 563172b"

となるわけでイメージのサイズの文字列は取得できます。しかし、どこを探してもズバリこの情報を取得する手法がなくて、結局この文字列から変換するしかないような・・・いやワタシが単純に間違っているだけかもしれませんが・・・

と再度ドキュメントを丹念に眺めていたらcolumnsとrowsというアヤシゲなメソッドが。。。ずばりこれでした。。。。ドキュメント単に見逃してた・・・_| ̄|○