2009年 05月 29日

web.xml filter, 自分で Dispatch

Lift 見つつ最低限な部分を自分で再実装

  • 全部のリクエストを受け取ってなんかしたいなら filter を使う
  • filter では、何もせずに chain.doFilter すれば static ファイルとかをいい感じにやってくれる。

web.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
	<filter>
		<filter-name>HttpRequestDispatcher</filter-name>
		<filter-class>net.lowreal.skirts.HttpRequestDispatcher</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>HttpRequestDispatcher</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>
package net.lowreal.skirts

import javax.servlet._
import javax.servlet.http.{HttpServlet, HttpServletResponse, HttpServletRequest}

class HttpRequestDispatcher extends Filter {
	val static = """^/(?:css|js|images|static).*""".r

	def init (filterConfig: FilterConfig) = {
		println("init")
	}

	def doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) = {
		println("doFilter")
		(request, response) match {
			case (req: HttpServletRequest, res: HttpServletResponse) =>
				println("")
				println(req)
				req.getRequestURI match {
					case static() =>
						println("static")
						chain.doFilter(request, response)
					case _ =>
						println("dispatch")
						res.setContentType("text/html")
						res.getWriter.println { """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">""" }
						res.getWriter.println {
							<html>
								<head><title>Hello World</title></head>

								<link rel="stylesheet" type="text/css" href="/css/base.css" media="screen,tv"/>
								<!-- script type="text/javascript" src="/js/site-script.js"></script -->
							<body>
								<h1>Request</h1>
								<pre>Method: { req.getMethod }</pre>
								<pre>RequestURI: { req.getRequestURI }</pre>
								<pre>QueryString: { req.getQueryString }</pre>
								<h1>Raw</h1>
								<pre>{ req }</pre>
							</body>
							</html>
						}
				}
			case _ => chain.doFilter(request, response)
		}
	}

	def destroy () = {
		println("destroy")
	}
}

skirts っていう名前で簡単なフレームワークを作ろうと思ってる。とりあえず Lift は気にいらなかったので、コードは参考にしつつも使わない方向に……

skirts = scala / 周りをとりまく何か / 美少女

2009年 05月 28日

GDHM の「陽だまりを越えて」を買ってきた。これからも楽しみだなぁ。発売日を意識して買うアーティストは唯一 GDHM だけです。

したいことがあったら声に出せ、というのが印象に残っていて、微妙に実践しようと思ってどうすればいいかなーという感じだったけど、「GAE やるんよ、やりたいんよー」っていってたら datastore のクセのイメージをタイミングよく教えてもらえたらいしたので、こういうことなんだなぁと思った。

一番嫌なのはやっぱファイルが増える、ということなんだと実感した。Scala で Java ラップするために沢山クラス作っても別に嫌ではない。ファイルが増えるだけで普段の作業のオペレーションが増えるんだもんなぁ…… 開く・閉じる・選択する・grep する。

GAE はとりあえずローカルの開発サーバが起動して、Scala で書いた HttpServlet に dispatch は簡単にできた。java class の自動コンパイル・自動リロードとか、リクエストフィルタを使った URL の dispatch とかが解らなくてとまってる。Lift とか読みつつやってるけど、そもそも Java war の流儀がよくわからない。

Scala だと Java の資源が使えるのが本当にとてもよくて、Rhino とか使ってスクリプト実行させたりもできるし、JRuby をテンプレートエンジンのためだけに使う (謎の XML 書きたくないし……) とかいう贅沢もできそうで夢が広がる。

Java は単体で書きたいとは全く思わないけど、Scala は書いていてすごく楽しい。ピタっとハマっていく感じがする。Ruby とかにはない型厳密な関数っぽい感覚。でも関数型ほど新しい考えかたをしなくても書けるから気持ちいい。しかも Scala はコンパイルすると Java クラスに変換されて JVM で直接動くのだから、JVM もすごいなーと思った。

gerry++

三日連続

スカラクロウラ - アクター

うーんよくわからない。while(true)/receive と loop/react の違いもよくわからない (スレッド作るかそうじゃないかだけの違い?)

クローラっぽいのを練習がてら書いてみた。あんまりわかりやすくはないなぁという気もする。もっといい書きかたあるのかな。

  • 一度に走るリクエストは2つまで
    • あらかじめ2つリクエストを出す Actor を作ってそれのキューにいれていく
  • List あたりが微妙にわかりにくい。普通に shift/push したい

http://gist.github.com/119257

あれこれ最初、スカラクロウラとかエントリで言いたかっただけだったのに、全くそんなこと忘れてエントリ書いてた

MP3 ID3 文字コード関係を仕様書にあたってみる

仕様がどうなっていようと使ってるやつが対応してないと意味ないですけどね!!

ID3v1

http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm#MPEGTAG

  • 文字コードについて記述なし
  • title, artist, album それぞれ 30bytes しか書けない

ID3v2

2.3

http://www.id3.org/id3v2.3.0

  • If nothing else is said a string is represented as ISO-8859-1 characters in the range $20 - $FF. Such strings are represented as , or if newlines are allowed, in the frame descriptions. All Unicode strings use 16-bit unicode 2.0 (ISO/IEC 10646-1:1993, UCS-2). Unicode strings must begin with the Unicode BOM ($FF FE or $FE FF) to identify the byte order.

要は

  • ISO-8859-1
  • UTF-16
  • UTF-16BE

でしか書けない。

2.4

http://www.id3.org/id3v2.4.0-structure

   Frames that allow different types of text encoding contains a text
   encoding description byte. Possible encodings:

     $00   ISO-8859-1 [ISO-8859-1]. Terminated with $00.
     $01   UTF-16 [UTF-16] encoded Unicode [UNICODE] with BOM. All
           strings in the same frame SHALL have the same byteorder.
           Terminated with $00 00.
     $02   UTF-16BE [UTF-16] encoded Unicode [UNICODE] without BOM.
           Terminated with $00 00.
     $03   UTF-8 [UTF-8] encoded Unicode [UNICODE]. Terminated with $00.
  • ISO-8859-1
  • UTF-16
  • UTF-16BE
  • UTF-8

で書ける。場合によっては ISO-8859-1 と UTF-8 でしか書けない場合がある? (Tag restriction あたり。よくわからない)

個人的なベスト

  • ID3v1 は書かない
    • 今時 ID3v2 に対応してないプレイヤーとか捨てればいい
    • 文字化けの元
  • ID3v2.3 にしておく
    • 文字コードは UTF-16(LE)
2009年 05月 27日

部分適用・メソッド呼びだしの syntax suger・デフォルト引数

メモメモ。簡単な Singleton Logger を実装してみる

//#!scala

object Logger {
	var level = 0

	def log (message: String, level: Int) {
		if (this.level <= level) {
			println(message)
		}
	}

	def log (message: String):Unit = log(message, 1)

	def debug = log(_: String, 0);
	def info  = log(_: String, 1);
	def warn  = log(_: String, 2);
	def error = log(_: String, 3);
	def fatal = log(_: String, 4);

	// この例の場合はこうしたほうがいい気がする
	// def log (message: String):Unit = info
}

Logger.level = 1

Logger debug "debug"
Logger info "info"
Logger warn "warn"

部分適用は _ と型さえ書けばいいっぽい? 引数の順番に制限はないようだ

Logger foo argLogger.foo(arg) の syntax sugar らしい。引数一つのときに省略ができるというルールではなくて、レシーバも含めた syntax sugar のようだ

デフォルト引数は Ruby とかのように仮引数に書くことはできなくて、overload で定義するっぽい。このとき overload する側のメソッドは、返り値の型の宣言が必要らしい

gerry++

二日連続