2011年12月29日木曜日

Go言語のErrorオブジェクトの変更


$ 8l -V
8l version weekly.2011-12-22 11086

12/22時点のGolang本体の変更点(気がついた分)のメモです。

「Go言語プログラミング入門 on Google App Engine」では、エラーオブジェクトの内容を出力する時に、
err.String()を利用していました。現在のGo言語本体の安定版リリースだと、
Stringメソッドは無くなっていて、代わりに、err.Error()のように、
Errorメソッドを呼び出さないとコンパイルエラーになってしまいます。

現時点のGAE/G SDKでは、書籍のまま、Stringメソッドを呼び出せば良いですが、
そのうち、本体の変更に合わせることになるかもしれません。

書くのを忘れていたので追記(18:00)
httpパッケージがnetパッケージの下に移動していました。
書籍ではimport "http"ですが、Go言語本体で利用するためには"net/http"と宣言する必要があります。


2011年12月28日水曜日

Go言語のtemplate.Setを使う

書籍「Go言語プログラミング入門 on Google App Engine」でも記述していない事なので
Blogに残しておこうと思います。

Google App EngineのアプリケーションはWebアプリケーションなので、HTMLを
出力する事が多いと思います。(WebAPIを作成する場合はテキストベースかもしれませんが)
HTMLのタグで面倒なヘッダ部分、フッタ部分など共通化したい所があったりすると
思います。
書籍では、Templateパッケージを利用して、HTMLファイルに変換タグを追加し、プログラムで変換タグを置き換えるというアプローチでHTMLを出力させています。しかも、Templateが一つの例が載っていますが、複数ページを作成するという事がなかったので
登場することがありませんでした。

前置きはこの辺にして、複数のページを作成する場合、ヘッダとフッタに関しては共通化される事が多いかと思います。Go言語でもその機能は提供されていますので、サンプルを書き残しておきたいと思います。

まず、HTMLの部分です。

ヘッダ
  
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>Set Sample</title>
</head>
<body>

フッタ
<hr>
Footer
</body>
</html>

ボディ(全体)
{{define "body"}}{{template "header"}}
<h1>Set Sample</h1>
{{template "footer"}}{{end}}

ソースコード
package setsample

import (
 "http"
 "template"
)

func init() {
 http.HandleFunc("/", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
 header := template.Must(template.New("header").ParseFile("header.html"))
 footer := template.Must(template.New("footer").ParseFile("footer.html"))
 body := template.SetMust(template.ParseSetFiles("body.html"))

 body = body.Add(header, footer)

 if err := body.Execute(w, "body", "no data needed"); err != nil {
  http.Error(w, err.String(), http.StatusInternalServerError)
 }
}

ポイントは、headerとfooterはtemplateとして読み込み、bodyをSetとして読み込む所です。
Setにはtemplateを追加する事ができるので、bodyにheaderとfooterのtemplateのタグを追加しておき、プログラムでAddします。

最後、Setに関しては名前を指定しないと出力(Execute)できないようなので、defineタグをbodyに追加しています。

これにより、HTML出力の処理が1回で済むようになります。

2011年12月27日火曜日

Slim3 Source Code Reading #2

今日は、Slim3 Source Code Reading #2を開催してきました。
今回はModel関連でDatastore#putを読み進めました。

読み進めたソースコードは以下のファイルです。

  • Datastore.java
  • DatastoreDelegate.java
  • FutureUtil.java
  • AsyncDatastoreService.java
  • DatastoreUtil.java


以下、その時のメモです。
DatastoreUtil.java 952行目
modelmeta.assignKeyToModelRefIfNecessary(ds, model);

エンティティ間の紐付けを行うための処理を個別に実装する。
(自動生成された時点では、中身は空)
※現時点では紐付けたサンプルコードがないので確認できず。。

ModelMeta.java 518行目
prePut()

データストアに格納する前に何か処理をしたい場合は、個別に実装する。
(自動生成された時点では、中身は空)
多分、postGet()とペアで見せる時とデータの中身が変換されないと
いけないケースが記述する?

DatastoreUtil.java 532行目
assignKeyIfNecessary()
エンティティにキーがなければキーを生成している。
ここで、親エンティティが存在している場合は、親のキーを設定して
紐付けしたキーを生成する。
Idは自動生成。

Datastore.put()で例外が発生した場合、(データストアのPutで例外が発生した時)
どうするの?(例えば、データストアの書き込みタイムアウトなど)

Slim3本のP.212中段にデータストアのリトライをSlim3が行うとなっているが?

DatastoreTimeoutException.javaはSDKに存在しているが、
RuntimeExceptionの扱いになっているのでドキュメントにthrowsの記述がない。

Slim3 1.0.6の時点ではリトライ処理(最大10回)が存在したようだが、
今日のソースコードを読んだ範囲では見つけられなかった。
(どこにもcatchがない?)

------

解散後の話題として@sinmetalさんが、Slim3のリポジトリから過去のソースコードを
取得して確認してくれたのですが、メモにある記事のように10回のリトライの処理は
確かに存在していました。しかし、現時点ではその処理は存在していません。
恐らく、AsyncDatastoreServiceの中(よりネイティブに近い所)でリトライ処理と
等しい事が行われていると予想されます。
(そうでなければ、処理を削除する理由がない)

次回#3は1/10(火)19:00〜の予定で、トランザクションに行く前に、Getを読みすすめます。

2011年12月26日月曜日

2011年を振り返る

だんだんと、今年(2011年)を振り返るというBlog記事が増えてきました。

という事で、私も同じように2011年を振り返ってみたいと思います。

参考までに、2010年の振り返りと目標の記事へのリンクを張っておきたいと思います。

2010年を振り返る
http://hobby.txt-nifty.com/t1000/2010/12/post-fe5a.html
今年の抱負?
http://hobby.txt-nifty.com/t1000/2011/01/post-4404.html

まず、2010年を振り返る記事に対して。

よく考えるとオープンセミナー@岡山の実行委員長をしていたのは昨年の事だったんですね。オープンセミナー@岡山は開催が5月頃なので半年ぐらいカレンダーとずれる感じなのですが、ずっと前のような感覚でした。
今年のオープンセミナー@岡山も130人ぐらいの参加があり、大変盛り上がりました。
来年はまた実行委員長が交代しますので、今年とは違ったものになりそうです。

また、来年はいい意味で「しがらみ」がなくなったので、勉強会も
「行きたい」と思う勉強会に参加しようと思います。
これに関しては、ある程度、達成できたのかな?と思っていますが、今年は行きたい勉強会に都合が合わずに行けなかったような気がします。それは金銭面が主な理由だったように思います。仕方がないと言えばそうなのですが、もう少し金銭面での余裕がでるようにしたいところです。
Google技術を勉強すると言って始まった2010年でAndroidばかりになって
しまったというのは良くないなと思いました。
来年はGoogle App EngineやHTML5なんかに力を入れていきたいです。
Go言語も途中で止まってしまったので、もう少し力を入れたいと思っています。
この点は、書籍「Go言語プログラミング入門 on Google App Engine」を書かせていただきましたし、中国GTUGの活動でも幅広いテーマで発表をしました。この目標は達成できたと捉えていいと思います。
来年もこの調子で幅広く押さえていきたいと思いますが、HTML5の勉強が足りなかった気がするので多少HTML5+CSS3+JavaScriptに力をかけていきたいと思っています。

次に、仕事に関して。
今年は以下の仕事をしました。

  • 専門学校の非常勤講師(週4日)
  • Androidの講師(センサー、OS)
  • 職業訓練校の立会い
  • 派遣会社の単発案件(PCの導入作業)
  • 執筆

専門学校の非常勤講師として週4回も授業をさせていただいたので、開発の案件に手を出すことができませんでしたが、来年は専門学校の授業が減ると言われているので、また新しい仕事を探さないといけなくなりそうです。今の生活は好きだったのですが、どうやら、1年限定だったようです。もう少し教育分野で活動してみたい気もするので、手を広げる方法を見つけないといけないなと思っています。

職業訓練校の立会では、学校やコミュニティとは違った感じの雰囲気を感じました。
私が立ち会ったのは半分の3ヶ月間だけでしたが、アプリケーションを作成する力を
どんどん身につけて行って、作品が完成していきました。アイデアも私の周りで
思いつくようなものではなかったのも、生活スタイルや文化の違いがあるのかもしれないと思いました。
ただ、彼らが無事将来を切り開いたのかどうか気になります。

そして、派遣会社の単発案件もさせていただきました。これも新しい経験でしたが、当時は「GTUGのマネージャを派遣できる会社なんてないだろ。貴重だぞ」なんて思っていましたが、本当にただの派遣社員として扱われました。派遣会社の社員で通さないといけないので、自営業と兼務するのは向かないかもしれません。名刺交換もできないし、営業活動的な事はできないので。これも本当に金に困った時にやることにしようと思います。

最後に執筆ですね。3月に「Google Android WebAPIプログラミング入門」、12月に「Go言語プログラミング入門 on Google App Engine」を書きました。年に2冊も
出版できるとは思っていませんでしたが、1冊目はそれなりに、2冊目はまだ結果が出ていないようですが、注目して、購入もしていただいているようなので安心しています。
3冊目に関してもまた書きたいとは思っているのですが、2冊目の時にボツになったネタなので書けなさそうだと思っています。GoやGoogle App Engineが盛り上がってきて、2冊目の内容から1歩進んだり、Go言語自体に注目した内容の本が書けたりすると良いなと思っていたりします。GoもしばらくするとVersion 1がリリースされて互換性の保証もされるようになるようですし。

最後に中国GTUGの活動に関して。
今年はハッカソンを増やすと言って、結局新年と盆の2回の開催をしました。
ポイントとして、中国地方だと2週連続で場所を確保するということが難しく、アイデアソン、チーム決めとハッカソンを分割する事ができませんでした。新年のハッカソンは2日確保して、前日にアイデアソンを、2日目にハッカソンを行いました。
8月は1日しか確保できなかったので、チーム決めも適当にせざるを得ず、「難しい」と
いう意見を頂きました。
個人的には満足していますが、課題をクリアできればと思っています。

新しい講師の発掘もしたいという事で、これまでの経緯を振り返ってみると、全体的に発表回数が少ない方に登壇をしていただけたのではないかと思っています。次の2月の勉強会も初めての発表の方にお願いしてありますし、岡山では選択の幅が広がってきたかなと思っています。広島でも開催の要望があるので、来年は広島での開催も実現したいです。
(広島のスタッフにお願いして場所を確保するしかないわけですが)

年末から、新しい試みとして、東京や大阪ではすでに行われているようですが、ソースコードリーディングを行うことにしました。きっかけは岡山Javaユーザ会で、@sinmetalさんと会話をしていた時に”そういえばSlim3のソースコードを読んでみたいよね”という話題になって、早速開催してみました。初回は5名の募集に6人の応募があるなど(そのうち2人は私と@sinmetalさん)注目度は高かったようで、楽しく(?)Controllerの辺りを読みました。

と、色々振り返ってみると、活動としては充実してたのかなと思っています。
これも中国GTUGのメンバー、地元の技術者の積極的な参加が非常に大きいと思います。
来年もどこかでハッカソン、発表挑戦者の発掘。ハンズオン、ソースコードリーディングなど、色々挑戦していきたいと思います。

が、やっぱりまず仕事の確保だな!

2011年12月25日日曜日

Slim3ソースコード読み会(2)の前に。

次回のSlim3 Source Code Reading #2が12/27(火)に開催されるのですが、
次回はmodel周りを読んでいく予定になっています。

ただ、model周りはデータストアへの読み込み、書き込みがあるため、
奥が深いので、事前に少し読んでおこうと思って読んでみました。

ひとまずメモを残しておきます。

  • Slim3はAsyncDatastoreServiceを使ってデータストアに書き込みを行っている。
非同期での書き込みなので、何もしなければ更新がすぐに反映されない(表示されない)時がある。

  • ModelクラスからModelMetaクラスを生成してデータストアに書き込みを行う。
    • ModelMetaクラスはVersionを持っている(データストアに書き込まれる)
      • Versionはputのたびにカウントアップされる。これはなぜ?
    • 同じく、SchemaVersionも持っている(データストアに書き込まれる)
      • 生成された直後は固定で"1"を書きこむ
      • SchemaVersionはプログラムの更新により、エンティティの内容が混在する時に新旧のバージョンのエンティティを判定するのに使う?
      • Modelのプロパティが追加される時にSchemaVersionも変更すべき?
  • Model→Modelの生成手順
例:slim3.model.Tweet
1. クラス名(フルパス)から".model."を探す。
2. 見つかった場合(lastIndexOf()の戻り値が0以上)
".model."より前、(今回の場合、"slim3") + ".meta." + "Tweet" + "Meta"にする
3. 見つからない場合は、そのまま+"Meta"にする
4. 2、3で生成したクラス名でインスタンスを生成する。
5. 1度生成されたMetaクラスは変換前のクラス名をキーにしてConcurrentHashMapに保存される。(2度目以降はHashMapにあるインスタンスを読みだして再利用する)


2011年12月21日水曜日

Slim3ソースコード読み会(1)

今日は中国GTUGのSlim3ソースコード読み会(1)を開催しました。

今日は最初だったので、様子を見ながらFrontControllerから読み進める事にしました。

今日読んだファイルは

  • FrontController.java
  • Controller.java
  • ControllerConstants.java
を主に読みました。

自分で実装したコントローラが呼び出されるまでの大まかな流れが知りたかったので
以下のソースコードは、呼び出しがあるのですが、読みませんでした。

  • RouterFactory.java
  • ApplicationMessage.java
  • CipherFactory.java
  • RequestUtil.java
  • RouterImpl.java
でも、帰ってからじっくり読んでみると、FrontController.javaの231行目の静的ファイルの判定の部分のためにはRequestUtil.javaとRouterImpl.javaは読んだ方が良かったのかもしれません。(という事で、再度読んでいます)

FrontController.javaの235行目のdoForward()が呼び出される条件がよくわからない等、
今回は不明な点を残しつつ進めて行きました。
(なんとなく、235行目は自分でRouterを実装した場合に変化がありそう)

FrontController.javaの261行目のdoFilter()では、リクエストとレスポンスを退避して、元に戻している処理がありますが、これの意味も今日の段階ではよくわからないポイントだったと思います。

分かった点は、

  • slim3-blankのweb.xmlにある、context-paramで、slim3.rootPackageは省略できない。
  • 同じく、javax.servlet.jsp.…localizationContextは設定が無くても"application"となる。(デフォルトが"application")
  • 同じく、javax.servlet.jsp.…request.charsetも設定がなくても"UTF-8"となる(デフォルトが"UTF-8"。ただし、リクエスト時にcharset指定がある場合はリクエストが優先される)
  • IndexController(というか、Controllerを継承したコントローラ)はsetUp()、run()、tearDown()の順番で呼び出される。それぞれ、事前処理、主処理、後処理となる。tearDown()で例外が発生すると、WARNレベルのログが出力される。

今日、一番の議論は、リクエストURLからコントローラのクラス名(フルパス)に変換するルールでした。

例えば、
http://localhost:8888/sample/
だと、
slim3.controller.sample.IndexControllerというパスに変換されて呼び出されます。

変換ルールは、
rootPackage + "." + コントローラパッケージ名 + "/"を"."に変えたgetServletPath() + "Controller"となります。

これにより、例えば、
http://localhost:8888/sample/hoge
であれば、
slim3.controller.sample.HogeControllerが呼び出されるようになります。

しかし、
http://localhost:8888/sample
だと、
slim3.controller.sampleControllerというパスに変換されるはずですが、
URLがhttp://localhost:8888/sample/に書き換わって実行されていました。
(想定と違った動き)

単純なURL書き換えが発生しているのか、Framework側で書き換えているのかは
よくわかりませんでした。

といった所で、本日はタイムアップしました。

次週は12/27(火)の19:00〜21:00の予定で、
Modelのあたりを読む予定です。

2011年12月20日火曜日

Slim3ソースコード読書会の前に

12/21(水)にSlim3ソースコード読書会(1)を開催する予定なのですが、
思ったより参加者が多いので、それなりに前提知識を整理したいと思います。

第1回はFrontControllerから各Controllerへの処理の振り分け部分について
読んでいく予定ですが、まずjavax.servlet.Filterインターフェイスの認識がないと
だめだと思ったのでその辺りの挙動をまとめておきます。

まず、Slim3でも(Blankプロジェクトのweb.xmlに定義)3つのFilterが定義されています。

    <filter-mapping>
        <filter-name>HotReloadingFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>  
    <filter-mapping>
        <filter-name>DatastoreFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>
    <filter-mapping>
        <filter-name>FrontController</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
        <dispatcher>ERROR</dispatcher>
    </filter-mapping>
第1回は名前の通りのFrontControllerから読み進めてどのようにControllerの振り分けを
行っているかを確認していこうと考えています。
処理の順番としては、<filter-mapping>タグが付いている順番にFilterインターフェイスが呼び出されます。今回のケースだと、
  1. HotReloadingFilter
  2. DatastoreFilter
  3. FrontController
が呼び出し順になります。したがって、<filter-mapping>の順番を入れ替えると呼び出し順も逆転します。

その挙動を確認するプログラムは、どこかにおく…必要もないと思うので、抜粋します。
3つぐらいFilterを作って設定すれば動作可能だと思います。

public class FirstFilter implements Filter {

 @Override
 public void destroy() {
  // TODO Auto-generated method stub

 }

 @Override
 public void doFilter(ServletRequest req, ServletResponse res,
   FilterChain chain) throws IOException, ServletException {
  System.out.println("FirstFilter#doFilter");
  chain.doFilter(req, res);
 }

 @Override
 public void init(FilterConfig arg0) throws ServletException {
  // TODO Auto-generated method stub

 }

}

Filterインターフェイスは3つのメソッドを実装し、以下のタイミングで呼び出されます。
  • init():フィルタの初期化時(1度だけ呼び出される)
  • doFilter():web.xmlの<filter-mapping>タグで設定したリクエスト時
  • destroy():コンテナが破棄される時などフィルタが破棄されるタイミング
Slim3では、doFilter()を駆使してコントローラの振り分けを行っているようです。

また、doFilterの引数であるFilterChain#doFilter(req, res)を呼び出さないと、
以降のFilterが実行されなくなるので、サーブレット/JSPを実行する場合も
注意が必要です。(動作を確認する場合は、chain.doFilter()をコメントアウトして下さい。)

以下、参考にしたサイト

Javaの道(Servlet-10.フィルタ)
http://www.javaroad.jp/servletjsp/sj_servlet10.htm

tomcatのドキュメント(Filterインターフェイス)
http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/Filter.html

Tomcatでフィルタを使う
http://www.nina.jp/server/slackware/webapp/tomcat_filter.html

new関数とmake関数について


私が書いたGo言語プログラミング入門 on Google App Engineにある記述で間違いがあったのですが、正誤表に書くには長いので、この記事に残しておこうと思います。

P.125のnew関数とmake関数の使い分けの所で、
次のように間違った例を掲載しています。

intArray := new([]int)
fmt.Fprintf(w, "%d¥n", intArray[0])

これは、そもそも書き方が間違っているという指摘を受けまして、
確認をしてみました。結論は間違ってます。

new([]int)が返す型は「*[]int」型です。int型配列に対するポインタが返されます。
しかも、配列の長さを指定していませんので、配列の長さが0です。
中身がありません。

したがって、intArray[0]と書くのは間違いで、(*intArray)[0]と書くのが
正しい表記となりますが、配列の中身がないので、実行時にエラーになります。

しかし、次のように、配列の長さを指定した形で使えば実行時エラーにはならなくなります。

intArray := new([5]int)
fmt.Fprintf(w, "%d¥n", (*intArray)[0])
検証したプログラムも掲載しておきます。
検証したバージョンはVer.1.6.1ですが、未検証ですが1.5.5でも問題ないと思います。

package newsample

import (
 "fmt"
 "http"
)

func init() {
 http.HandleFunc("/", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
// 書籍の例は間違い!
// intArray := new([]int)
//
// fmt.Fprintf(w, "%d\n", intArray[0])

 intArray := new([5]int)

 fmt.Fprintf(w, "%d\n", (*intArray)[0])

 intArray2 := make([]int, 5)

 fmt.Fprintf(w, "%d\n", intArray2[0]) 
}


new関数の使い方について認識不足でした。
今回も柴田芳樹さんにご指摘いただきました。本当にありがとうございました。

GoのTypeAssertion(型変換?)


私が書いたGo言語プログラミング入門 on Google App Engineにある記述で間違いがあったのですが、正誤表に書くには長いので、この記事に残しておこうと思います。

P.108で「インターフェイスの型の変数に値を代入した後、本来の型に戻す事はできません。」と記述しているのですが、実際は、戻すことが可能です。
具体的な方法は、"変数名.(型)"と記述することで復元します。
Go言語の言語仕様にも、Primary expressionsに記載がありました。

実際の検証用のソースコードです。
動作確認はSDK1.6.1で行いましたので、書籍のベースバージョン1.5.5では未検証ですが、
古いバージョンのSDKで開発される事は減るかと思いますので、検証していません。

以下のソースコードが検証用です。(ほぼツッコミ時に紹介されたソースのままですが…)

package interfacesample3

import (
 "fmt"
 "http"
)

type Introduction interface {
 intro(w http.ResponseWriter)
}

type Coffee struct {
 Sugar bool
}

func (coffee Coffee) intro(w http.ResponseWriter) {
 if coffee.Sugar {
  fmt.Fprintf(w, "This is a coffee with sugar\n")
 } else {
  fmt.Fprintf(w, "This is a black coffee\n")
 }
}

func init() {
 http.HandleFunc("/", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
        // Introduction型の配列を作成し、Coffee型のインスタンスを代入する。
 array := make([]Introduction, 1)
 array[0] = new(Coffee)
 array[0].intro(w)

        // そもそもnew関数で返される型はCoffeeではなく、*Coffee!
 var coffee *Coffee
 coffee = array[0].(*Coffee)
 coffee.Sugar = true
 coffee.intro(w)
}

出力結果は
This is a black coffee
This is a coffee with sugar

となり、復元できている事がわかります。

書籍の型の復元については、完全に不勉強でした。
今回は柴田芳樹さんにご指摘いただきました。本当にありがとうございました。

2011年12月18日日曜日

Goでの日付変換

私が書いたGo言語プログラミング入門 on Google App Engineにも記述していないので、ここに載せておきたいと思います。

書籍内だとデータストアに日付を登録する時に、以下のような記述をしています。

datastore.SecondsToTime(time.Seconds())

これは、現在日時が取得されて日付がdatastore.Time型(中身は整数)に変換されます。
確かに現在日時であれば、これで良いのですが、指定した日時を格納したい場合に
この方法では日時のデータに変換することができません。
したがって、他の言語と同様に、文字列から日時データに変換します。
以下のような記述にします。

strdate := "2011-12-18 23:00:00"
inputtime := time.Parse("2006-01-02 15:04:05", startdatestr)
datastore.SecondsToTime(inputtime.Seconds())

これは、年:4桁、月:2桁、日:2桁、24時間表記の時間、2桁の分、2桁の秒となります。

time.Parse関数の第1引数がフォーマットを指定するのですが、標準で用意されている
フォーマットもあります。以下、timeパッケージのformat.goからの抜粋です。

const (
ANSIC    = "Mon Jan _2 15:04:05 2006"
  UnixDate = "Mon Jan _2 15:04:05 MST 2006"
RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
RFC822   = "02 Jan 06 1504 MST"
// RFC822 with Zulu time.
RFC822Z = "02 Jan 06 1504 -0700"
RFC850  = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
RFC3339 = "2006-01-02T15:04:05Z07:00"
Kitchen = "3:04PM"
// Handy time stamps.
Stamp      = "Jan _2 15:04:05"
StampMilli = "Jan _2 15:04:05.000"
StampMicro = "Jan _2 15:04:05.000000"
StampNano  = "Jan _2 15:04:05.000000000"
)

RFC準拠のフォーマットであれば、"RFC3339"などと指定することで書式に合わせて文字列を解析し、変換してくれます。

JavaやC#などと違って"yyyy/MM/dd HH:mm:ss"というフォーマットが指定できないのが大変ですが、慣れると意外と良いかもしれません。

2011年12月16日金曜日

Go言語プログラミング入門(正誤表)

そろそろ(12/16時点)私の2冊目の書籍、「Go言語プログラミング入門 on Google App Engine」が発売されて、手元に届いた頃だと思うので、読者の方からの指摘、自分自身で発見した誤りをメモしておきたいと思います。
正式な発表は出版社のサイトを御覧ください。
※2011/12/20追記:秀和システムさんにも連絡して公式の正誤表となりました。

  • P.43 中段3行目:「メソッドf()」→「メソッドf」
余計な()が含まれていました。()は不要です。
柴田芳樹さんありがとうございました。

  • P.69 8行目:「2バイトずつ読み取っている」→「3バイトずつ読み取っている」
これに関しては、内部の文字コードがUTF-8なので、全角文字は基本的に3バイトとなります。JIS X0213のBMPセットからはみ出す文字は4バイトとなります。
私の文字コードの知識不足でした。
@titoi2さんありがとうございました。
  • P.108 4行目:「インターフェイスの型の変数に値を代入した後、本来の型に戻すことはできません。」→「できます」
詳細は、別の記事に残しましたのでご確認下さい。
柴田芳樹さんありがとうございました。

  • P.125 new関数の間違った使い方の例が間違っている。
詳細は、別の記事に残しましたのでご確認下さい。
柴田芳樹さんありがとうございました。

  • P.216 「今回のプログラムは、ローカルサーバで実行しようとしても、図4-19のようにエラーになってしまうので」→「図4-26」
指定している図の番号が間違っていました。正しくは図4-26です。
また、ローカルサーバでもCross Group Transactionの実行は可能です。
ただし、ローカルサーバの起動オプションの--high_replicationを指定する必要があります。
現時点では、--high_replicationはデフォルトfalseなので、Master-Slave型で動作します。

  • P.228 ユーザ認証のポイント2点目「OpenIDについては現時点ではAPIのみ提供していて動作しない」→「OpenIDはクラウド環境でFederated Loginの設定にすれば、動作する」
これは、直前で設定の手順だけ記述しましたが、(今、思えば、キャプチャ画像ぐらいは貼れば良かった)本番環境にデプロイして実行すれば動作します。
結果は、デプロイして出力結果を確認してみてください。
  • P.271 ソースコード1行目「var body = make([]byte, res.ContentLength)」→「var body make([]byte, 0, res.ContentLength)」
SDK 1.5.5ではこのままでも大丈夫だと思うのですが、1.6.1で利用する場合は先頭に余計なデータが詰まってしまうので長さ0の容量がデータ長のバッファを確保する必要があります。
別の記事にもまとめてあるのでご確認下さい。
http://takashi-yokoyama.blogspot.com/2012/01/bytesnewbuffer.html
  • P.349 「必ずデータを登録した状態で実行してください」
  • P.352 「また、最初に注意しましたが…プログラムが応答を返さなくなってしまう」→「Load()でdatastore.LoadStruct()、Save()でdatastore.SaveStruct()を呼び出すか、close(c)を呼び出してChannelをクローズしないとプログラムが応答を返さなくなってしまう」
文章自体は正しいのですが、PropertyLoadSaverのSaveメソッド(P.350(4))で、SaveStruct()かclose(c)を実行しないと登録処理を行うときにロック(応答を返さなくなる)してしまいます。
逆にP.350のLoad()メソッド(2)内でLoadStructを呼び出すかclose(c)を呼び出さないと読み出し時もロックします。
  • P.359 2段目、3行目最後「本書の内容も動作するような」→「本書の内容が動作しなくなるような」
正反対の記述になっていました。バージョンが上がると、書籍のソースコードがコンパイルエラーになってしまう可能性があります。



2011年12月8日木曜日

Googleの周辺技術(メモ)

shin1ogawaさんが発表された時の資料で、中国GTUGでの発表のネタになるかと
思ったので、ブックマークしようかと思ったのですが、
ブログに残しておこうかなと思います。

ひと通りのGoogleのAPIやサービスを知るには良い資料だと思いました。

2011年12月7日水曜日

第1回岡山PHP勉強会に参加しました。

第1回岡山PHP勉強会に参加してきたので、そのメモを残しておきます。

システム構築事例の話(…?)

  • 突発的なアクセスの増加
  • Yahooアタック
    • Yahooのトピックスにリンクが付くと…
    • 動画への直接リンクはやばい
  • PHPを選んだ理由
    • 簡単
    • みんな使っている
    • 自由度が高い
    • サーバ設定が簡単
    • 速い(?)
  • しかし
    • コードの統一性がない
    • セキュリティが最悪
  • フレームワークを活用することにした。
    • 開発時間の大幅短縮
    • ルールに従うと、コードが統一
    • DBとの連携が簡単
    • 表示が速い(ページキャッシュ機能)
  • PHP勉強法
    • 参考までに。
      • 目標を作る(アプリを1週間で作る。必ず日程を決めておく事。)
      • 入門書とリファレンスブックを購入
        • 作りたいものに近いサンプルがある本が良い
      • 説明を見ながらとにかく作る
      • リファレンスブックを見ながらソースコードを読む
      • 自作アプリケーションを作成する。
    • オープンソースを解読(バグ情報は便利)
    • 参加する
    • オープンソースを作る
    • 勉強会に参加する
  • TIPS
    • コードのガイドラインを決める
    • コードの最適化
    • セキュリティに気を使え!
      • サニタイズ処理だらけの関数等を通して無効化する。
    • 英語ができたほうが良い
    • 最新情報を得る(セキュリティ等)
    • 初級者こそフレームワークを使うべき
  • 3カ月以前の自分のソースコードを恥ずかしく思える様になること。
    • 常に精進しつづけましょう!
  • アイデアをお待ちしております!
  • 苦労した点
    • ロードバランサ
PHPフレームワーク入門
  • 無害化する方法(フレームワークを使わない場合)
    • htmlspecialchars()
    • mysql_real_escape_string()
  • いつも同じようなコードを書いている?
  • 以下のようなコードは…
    • ロジックとデザインがごちゃまぜになったコード
    • ルールが統一されていない
  • サーバを移したら動かなくなった。(PHPの場合)
    • バージョンの違い
    • 設定値の違い
    • ライブラリの不足
  • セキュリティが不安
    • いろいろな攻撃

  • フレームワーク(Framework)
    • 骨組み
    • 土台となるもの
    • 主な役割
      • 標準的な機能の提供
        • ライブラリ
        • ヘルパー関数
          • CakePHPのpr()
            • print_r()の結果を<pre></pre>で囲って出力する
      • MVCモデルの実現
        • Model
        • View
        • Controller
      • MVCモデルのメリット
        • 独立性の確保
          • 機能毎の役割が明確になる
        • 依存性の抑制
        • 保守性の向上
      • ORマッピング
      • ルールの制定
        • 命名規則
          • 変数名、テーブル名
          • ディレクトリ構成
          • コーディングスタイル
    • フレームワークのデメリット
      • 学習コスト
      • どれが良いかわからない
        • 色々なフレームワーク
          • 場合に応じて使い分ける
        • 選定基準
          • 実用性
            • 安定性
            • 機能、対応バージョン
          • 開発の継続性
          • ライセンス
          • 情報の入手しやすさ
    • CodeIgniter
      • 高速
      • 軽量
        • ソースの容量は(展開後で)1.2M
      • 低い学習コスト
      • 日本語のユーザガイドが完備
    • CodeIgniterのURL
      • index.phpがフロントコントローラ
        • URLは、index.php/fuga/piyo/paramなど。
          • class fuga extends CI_Controller {
            • function piyo($param) 
    • 便利な機能
      • active_record
      • form_validation
    • View
      • 共通部分はinclude

セキュリティについて考えてみよう
  • バグ、脆弱性
    • バグとは何か?
      • なるべきものが、そうならない。
    • 脆弱性とは何か?
      • バグと言えばバグ。
      • そのうち、セキュリティに関係するもの
        • 例)脆弱なOSで動作しているサーバがあっても、ファイアウォールで完全に隔離されていれば問題はない。
          • 外部から接続できないので。
      • セキュリティホール、脆弱性はバグの一部。
    • アプリケーションが正常に動作するように作ること。
      • 「一定の定義」に従って正常に動作するのであれば問題ない。
    • リスクを知り、対応する
      • 以下のような問題に対して
        • SQL Injectionでデータを取られた
        • SQL Injectionでページを書き換えられた
      • Webアプリケーションは「最もリスクがあるもの」
        • 全世界に向けて公開する前提だと。
        • 自分のサーバは人気がないから問題ないだろう。
          • クラックする人は、踏み台にするためにサイトの大小に関わらず攻撃してくる!
          • 従って、これは間違い。
    • リスクとは何か?
      • CVEというデータベースがある。
    • 入力、処理、出力
      • エコーバック問題?
      • 9割方、入力と出力の部分で対処がない。
      • 基本的に自分のアプリ以外は全て信用できない前提で考える。
        • 信頼境界線
      • 入力は「全てバリデーション」
        • 「サニタイズ」とは違う
          • ブラックリスト的考え方。(悪いものを弾く)
          • validationはホワイトリスト的考え方。(良いもののみを受け入れる)
      • 処理は「ベストプラクティスに従う」
        • 話をすると長くなるので省略
        • めんどくさい
      • 出力
        • エスケープを理解し、エスケープする
        • ヘルパーを理解し、ヘルパーを使う
          • 属性名をエスケープしないヘルパーがあるので、下手すると、そこがXSSの原因になる可能性も。
        • エスケープもヘルパーも使えないものはバリデーション
        • どうしようもないもの、絶対に安全だとわかっているもの
          • そのまま出力
    • アプリケーションが正しく動作することを担保する
      • 特にセキュリティに特化する場合
        • CIAを保証する
          • Confidential(機密性)
          • Integrity(統合性)
          • Availability(可用性)
      • セキュリティ対策に役立たないセキュリティ対策はない
    • セキュリティ対策とはリスクマネジメント
      • リスクを許容できれば、どんな対策でも構わない。
        • リスクを理解した上で、どこまでリスクを許容できるのか。
        • ただし、他人に迷惑はかけない
      • 例えば、文字エンコーディングのバリデーション
        • 入力時に文字エンコーディングをバリデーションする。
      • 適切な設計も必要
      • どれが優れたセキュリティ対策か?よりも、必要なセキュリティ対策か?が重要



2011年12月3日土曜日

第11回中国GTUG勉強会

第11回勉強会を開催しました。内容のメモを残しておきます。

DevQuizへの参加

  • Googleの開発者向けイベント
    • できるだけ能力の高い人に参加してもらうため
    • より多くの開発者に参加してもらう
    • 公平な選抜方式
    • イベントの前に開発者に楽しんでもらう
  • ウォームアップ問題
    • Google技術のトリビア
  • 分野別問題
    • Web Game
      • JavaScriptを使った神経衰弱
    • Go
      • PNG画像を与えられて、何色の画像があるかを調べる
    • Android
      • AIDLを使ってデータを抜き出す。
    • Google Apps Script
    • 一人ゲーム
  • スライドパズル

  • 参加者:3000人
  • 通過者:1000人
  • ボーダー:100.56点/150点
  • スライドパズルは、結果を探索するコードをバグ無くかければ。。
  • スコア分布
    • 100〜110点のところに大半の方が分布
  • 問題作成チームのコメント
    • みんな頑張りすぎ。
    • 30人も満点を取るとは思っていなかった。

  • スライドパズル
    • 解決するための定石
    • 幅優先探索
      • 1手後、2手後の状態を保持して、ゴールの状態になるかを調べる
    • 双方向探索
      • スタートとゴールから幅優先探索
    • でも、最短経路を見つけるのは無理!という結論
      • 20Byteぐらい保持して、2億通りなので、4GBぐらいになる。PCではこれが限界。
      • ゴールに近づいたかどうかを評価する関数を準備。
        • 当然、壁の有無も考慮しなければならない。
        • この時点で844問/5000問
    • 評価関数に一工夫をする。
      • 先に盤面の真ん中を揃えると、左上を揃えに行く時に乱される。
        • 無駄が多くなる。
      • 人間だと左上から揃えるようにする。
        • 人間が解決する方法を考えると解決策が思いつく場合がある。
    • メモリの省力化
      • 経路を1byte保持→2bit保持へ。
      • intをint8_tへ。
      • 4000問ぐらいまでは結構行ける。
    • 難しいケースの対策
      • 通路のようになっているケース
      • 4966問/5000問
    • もっと難しいケース
      • 結局、手動で解いた。
      • 5000問/5000問
    • 手数は12426手余った。
    • 最長手数は303手
    • 思考・コーディングは40時間
    • 計算時間は40時間
    • 最後の手動の問題を解くのに10時間位
  • 言語はC++で。
    • 処理速度が重要
    • 寝るときに計算し始めて…
      • 起きた時に終わる or 丸一日
    • C++11は便利
      • 拡張for
      • 型推論のauto
      • ラムダ式
      • サイズを指定できる整数型
    • 実装上のほそぼそとしたこと。
      • 盤面サイズをテンプレートパラメータ化
        • 1.5倍ぐらいの速度向上
        • ただし、コンパイル時間は16倍…
  • Samurai Coding
  • TopCoder
  • Code VS
  • AI Challenge Ants(スポンサーがGoogle)

  • 近似解を求めるプログラムの重要性
    • 「アルゴリズムイントロダクション」の練習問題より。

  • NASA TopCoder Challenge
    • NASAがスポンサー
  • 身につく能力
    • ボトルネック以外を最適化する無意味さ
      • 面白いぐらい無意味なんだそうです。手を付けやすい所からやってしまうという人間の性も。
    • 実装の難しさと効果を天秤に掛ける感覚
    • コードを綺麗に保つことの大事さ
      • 後で改造が難しくなる
    • 作業管理
      • バージョン管理は大事!

  • EXP-Hackathon
    • WebIntents、GITKitを使って簡易画像ピッカー
    • 自動飲み会幹事システム
    • Hangoutsを自分のガジェットに埋め込む
    • etc

Google Code Jam Japanに参加した
  • TopCoderは言語の縛りがあるが、Google Code Jamについては、縛りはない。
    • TopCoderはAppletか何かで動作しなければNGとなるかも?
  • Google Code Jam Japan
    • 問題は3〜6問
      • SmallとLarge
        • Smallは制限時間4分(再挑戦可能、即答される)
        • Largeは制限時間8分(時間内に限り、再挑戦可能)
    • テストケースの入ったファイルをダウンロードし、実行結果をソースコードと一緒に提出
    • 各問題の得点と回答した時間で順位が付く
  • 競技の流れ
    • 参加登録(2月中旬登録開始)予選終了前なら登録可能
    • 練習問題
    • 予選(10/1 13:00〜19:00)
      • 6時間で3問の問題
        • 予選で1問以上の問題でSmall、Largeの両方を解いた人のみ
        • 600人程度
    • 決勝(10/8 13:00〜16:00)
      • 3時間で5問の問題
  • 戦略
    • 言語:Java(Eclipse)
    • 予めプロジェクトを作成しておく
      • ファイルを読み込み、出力するというテンプレート的なコード等
    • 先に問題を全部読んで、解けそうなものから解く
    • サンプルの入力・結果で確認
      • 問題にサンプルの入力、結果がある。
  • 予選
    • B問題はコーヒーの幸福度、賞味期限を扱う
    • C問題はビット数を数える
  • 決勝
    • 手も足も出ず
    • 長さを持つアンテナのエレメントを並べて、感度が良くなるパターンを算出。みたいな問題など
Google Developer Day 2011のフィードバック
  • 技術的な情報を紹介するイベント
  • OAuth1.0→OAuth2.0へ!
  • OAuth2.0とOpenID Connectによる認証
    • Google Identity Toolkit
    • Account Chooser
  • Google APIs Consoleで登録
  • OAuth2.0のaccess_tokenを取得
    • Scope https://www.googleapis.com/auth/userinfo.mailなどを指定。
  • Account Chooser
    • https://account-chooser.appspot.com
    • 認証で使うウィジェット
  • 認証はGoogleなどのクラウド側に任せてしまって、アプリケーションの開発に力を注いだほうがいいのでは?
  • Chromeのデベロッパーツールについて
    • HTML/CSSの編集・更新、差分履歴、バージョン管理
    • スタイルシートの変更をリアルタイムに反映
    • 定義を追加も可能
    • 補完機能
    • 差分履歴、バージョン管理
      • 変更履歴が残る
      • 指定するバージョンに戻すことも可能
    • Firebug CommandLine APIとの互換もある。
    • リモートデバッグ

  • HTML5のオフライン機能
    • バイナリデータの保存
      • File System API
と、言う感じで、タイムアップ
資料は、公開されたら中国GTUGのサイトで公開します。

2011年11月29日火曜日

GoogleのOAuthAPIを使う。(Chrome-Extension編)

今日は、新しいChrome-Extensionの開発をしていました。

今回のアプリケーションはGoogleのサービスを利用したかったので、
GDataAPIのドキュメントを見てみると、JavaScript版はすでに非推奨になっており、
最新のv3ではJavaScriptのAPIが存在しないようなので、v2で実装してやろうと
思ったのですが、Chrome-Extensionからだとうまくいかず。

どううまくいかないかというと、
var token = google.accounts.user.login(scope);
を実行すると、ログインした状態でもtokenがnullを返してくる。
(ローカル実行だからなのかもしれない。サイト上におけば結果が変わると思います)

という事で、仕方が無いので別の方法を探そうと思ったらいいライブラリがありました。
http://code.google.com/chrome/extensions/tut_oauth.html

これを利用するとChrome-ExtensionでもOAuth認証を行うことができると
言うことだったのですが、これを利用して、今日1日終わってしまいました。

BackgroundPageからoauth.authorize(onAuthorized);を呼び出すと、
新しいtabが表示されて、Googleのアプリケーション認証画面が表示されます。
が、今度はライブラリ側で実行されている、ChromeExOAuth.initCallbackPage();
(※chrome_ex_oauth.htmlファイル内で呼び出されている)
を実行すると、XMLHttpRequestのstatusが0になり、エラー扱いに
なってしまうようです。

ちなみに、上記のライブラリを利用するためには、ConsumerKeyとConsumerSecretが
必要なのですが、https://accounts.google.com/ManageDomainsのサイトで、
ドメインでの認証キーを取得すれば、利用することができるようになります。
(Chrome-Extensionでドメインの認証キーを利用するのがいいかどうかは不明です)
ちなみに、Google App Engineの[appID].appspot.comでも認証キーを取得する
事が可能なようなので、静的な認証用のファイルをアップロードしておいて、
Google App Engineではそれを利用すると良いと思います。


2011年11月7日月曜日

CodeIgniterを使ったアプリケーションのUnitTest

今年から、専門学校の授業でPHPを教えているのですが、
その授業のネタとしてCodeIgniterを利用しています。

基本的な機能について、大体触ったので、これから実践的な
内容にしようと思って、教科書にしている「CodeIgniter徹底入門」を
見ていると、フレームワークでユニットテストのライブラリが用意されているようなので
試してみました。使い方は、以下のように
ライブラリを読み込み、テストを実行、レポートを出力する。
最後に確認という感じです。

// ライブラリの読み込み
$this->load->library('unit_test');
// テストの実行
$this->unit->run(実行するメソッド、評価対象, 期待する実行結果, テストの名前);
// テスト結果(レポート)の表示
echo $this->unit->report();

ちなみに、以下の本です。


ただ、これだとブラウザでリクエストしないとテストが実行できないので、
テストコードも本番環境にデプロイしないといけなさそうです。

が、授業の一環なので、ひとまずはこれで良いかな。

で、データベースのテストに関して調べていたら、本番用とテスト用で
データベースを切り替えるか、テスト用のテーブルを用意するしかなさそうな感じ。


2011年10月12日水曜日

Google App Engine Go SDK1.5.5の変更点

Google App Engine Go SDK 1.5.5がリリースされました。

1.5.4からの変更点を確認した所、たくさんの変更がありました。
したがって、1.5.4で動作していたプログラムが1.5.5ではコンパイルエラーになる可能性が高いです。(データストアを使っていたら、ほぼNGでしょう)

わかり次第、変更点を追記していく予定です。

変更点は以下のポイントです。

  1. app.yamlに指定するapi_versionは"3"を指定する。(ローカルサーバが動きません)
  2. Cross Multiple Group Transactionの追加により、datastore.RunInTransaction()の引数にTransactionOptions構造体の引数が必要。メンバ変数XGにfalseを設定するとSingle Transactionとなる。
  3. datastore.NewKeyにappengine.Contextの引数が追加された。
  4. datastore.NewIncompleteKeyも同じくappengine.Contextの引数が追加された。
  5. datastore.NewIncompleteKeyにも親キーを指定するKey引数が追加された。
  6. http.ResponseWriterのHeaderが初期値が"text/plain"になっているので、w.Header().set("Content-Type", "text/html")を入れる必要がある。※ただし、w.Fprintf()で文字列を出力した時の挙動
  7. templateパッケージが変更されている。(詳細は、http://golang.org/pkg/template/#Template.Parse参照)
  8. gofmt、gofix、godocコマンドが同梱されるようになった。(1.5.4以前は無かった)※gofixコマンドはtemplateパッケージの変更には対応していない(?)
2011.10.13:
  • 8を追記
2011.10.15:
  • gofixコマンドのtemplateパッケージの変化に対応していない事を追記
2011.10.18:

  • datastore.RunInTransactionのTransactionOptions構造体の説明を修正




レイアウトのXMLに配置したButtonのOnClickはDialogでも使えるらしい

以前、移転前のブログにて、
「レイアウトのXMLに配置したButtonのOnClickがDialogだと使えない?」
http://hobby.txt-nifty.com/t1000/2011/06/xmlbuttononclic.html

という記事を書きました。

しかし、後日、コメントが付き、以下のサイトのようにするとDialogでもonClickを
利用する事ができるようです。

http://wiki.android-fun.jp/?layout%20xml%E3%81%ABonClick%E3%81%A7%E5%91%BC%E3%81%B0%E3%82%8C%E3%82%8B%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%82%92%E5%AE%9A%E7%BE%A9%E3%81%99%E3%82%8B


レイアウトのボタンに定義したonClickはDialogからは使えない件について、
Activityに定義すれば利用可能。

emacsにcss-modeを導入する

emacsでCSS3を編集しようとした時に、どうも見にくいなと思ったので、
emacsの設定ファイルがないか探していた所、以下のサイトにcss-mode.elが
公開されているという事で、導入しました。

A CSS editing mode for Emacs
http://www.garshol.priv.no/download/software/css-mode/

上記サイトにある、css-mode.elをMacOSXの場合は、~/.emacs.dにコピーし、
.emacsに以下の設定を追記します。


;; CSS mode
(autoload 'css-mode "css-mode")
(setq auto-mode-alist
	  (cons '("\\.css\\'" . css-mode) auto-mode-alist))

あとは、emacsでcssファイルを開き、色が変わればOKです。

追記:
上記までだと、入力時のタブ幅が8(?)なので4に変更するのと、
インデントをCのスタイルに変更する設定も一緒に入れておくと良いでしょう。

(setq cssm-indent-level 4)
(setq cssm-indent-function #'cssm-c-style-indenter)

参考サイト:
http://uch-x40.seesaa.net/article/44721501.html

2011年10月11日火曜日

emacsのコマンド集


今日は、Rubyのkazuhisa1976さんの「ミニミニemacs勉強会」に
参加してきたので、emacsのコマンドをメモしておきます。
※私はRubyの話はわからないので、ひとまずスルー気味でいました。
(分かるようにはならんとなと思っていますが)

便利な(?)emacsコマンド集
※Ctrlを押しながらの操作は「C-*」、ESCを押してからのキー操作を「M-*」と表記しています。

M-X grep-find[Enter]
   カーソルの場所にキーワードを入力するとfindコマンドが実行される。
   (実行結果は新しいバッファ)

C-a
   行の先頭にカーソルを移動する。
C-e
   行の最後にカーソルを移動する。
C-x 1
   分割した選択していないバッファを閉じる
C-x 2
   バッファを上下に分割
C-x 3
   バッファを左右に分割

@kazuhisa1976さんのブログも参考に。
http://d.hatena.ne.jp/tech-kazuhisa/20111010

そういえば、C-sで検索しても、前に検索することができないなーと
言っていたけど、手元にある書籍を見返すとC-rで前検索をするようです。

2011年10月10日月曜日

Dartの導入 on MacOS X

Web構造化プログラミング言語"Dart"が発表されたみたいですね。

参考:
http://www.dartlang.org/(公式、英語)

ということで、早速動かしてやろうと思って、作業をした手順を控えておこうと思います。

最初にDepot_Toolsをダウンロードする必要があります。
Dartのソースコード、ツール一式がgclientを利用しないとダウンロードできないためです。

Depot_Toolsのダウンロード(いろんな物が落ちてきます)
$ svn co http://src.chromium.org/svn/trunk/tools/depot_tools

Depot_Toolsをダウンロードしたら、その中にある、gclientというコマンドを利用します。
恐らく、パスを通しておく方が良いでしょう。
export PATH=$PATH:[Depot_Tools

Dartのソースコード、ツール一式のダウンロード(本当にいろんな物が落ちてきます)
$ gclient config http://dart.googlecode.com/svn/branches/bleeding_edge/deps/all.deps

$ gclient sync

ダウンロード後、Dartをビルドします。
$ cd [Dartのダウンロードディレクトリ]/dart
$ ./tools/build.py --arch=ia32

ビルド後、以下のHTMLのコードを作成します。これは、Dartのコードを含んでいます。
ファイル名はdartsample.htmlで保存しました。
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>Dart Sample</title>
</head>
<body>
  <script type='application/dart'>
	void main() {
	   HTMLElement element = document.getElementById('result');
	   element.innerHTML = 'Hello World!';
	}
  </script>
  <div id="result"></div>
</body>
</html>

このHTMLファイルをDartのコンパイラ(?)dartcでコンパイルします。ただし、pythonのスクリプトが用意されているので、以下のコマンドを使ってコンパイルします。

$ python [Dartのダウンロードディレクトリ]/dart/client/tools/htmlconverter.py dartsample.html -o out/

正常に終了したら、outディレクトリを調べると、dartsample-js.htmlというファイルが
生成されていました。これをChromeで表示すると、Hello World!という文字列が
表示されました。

今回はブラウザで実行させるようにしましたが、DartはVM上でも動作させる事が
できるようなので、後で、同じく動かしてみようと思います。

2011/10/11追記
dartsample.htmlのソースコードに変なspanタグが挿入されているのに
気がついたので、削除しました。本来は不要でした。

2011年9月21日水曜日

職業訓練校のバイトが終わって…

5月のGW明けから今日まで、職業訓練校のバイトをしていました。
大体、平均して週2日(1日の時と3日の時もありました)
Androidの技術的なサポートという事で、立会いをしつつ、質問に答えるようにしていたのですが、
最初は質問があるものの、1ヶ月もすれば質問がほとんどでなくなりました。

質問が無い事自体は、良いことなのかどうかは別として、
そんなに聞くことが無いのかな?とは思いました。
ということだったので、状況を確認して、立会いを終わらせようと
思っていたのですが、運営側としては、私がいた方が良いようで
ずっと呼んで頂いていたのですが、
実際、お力になれたのかな…と、考えさせられます。

しかし、生徒達の技術は成長していますし、アプリケーションの質も
良くなったと思います。マーケットに出しても、恐らく問題ないと思います。
(これは、”人気が出る”、”売れる”という意味ではないです。)
アプリケーション開発の仕事をしたとしても、開発経験のある人の
フォローがあれば、問題なく遂行するでしょう。

実際、心残りがあるとしたら、最初に作成したアプリケーションの
ソースコードを見た時に、プログラムの構造がぐちゃぐちゃだったのを
矯正する事ができなかったことでしょうか。
(これは、私も偉そうに言うことはできないと思います)

後は、プログラムを組めても、ヒューマンスキルがない人もいたし
それも、指摘ぐらいはしたかったですね。

ただ、今後も開発を続けていくという声を聞きましたし
Android開発者の人口が増えていくと思うと、今後が楽しみです。

後は、私は専門学校の講師、中国GTUGのマネージャ、そして、立会いのバイト、
それぞれの空気を感じてみて、それぞれで独特の空気があるなと言うことが
分かったのも大きかったです。

中国GTUGのイベントだと、参加者の皆さんが「好きで」参加するという
前向きなメンバーで進めるわけですが、
専門学校の講師、職業訓練校のバイトなどでは、必ずしもそうではない可能性を
否定できない気がしました。
当然、興味を引き出すのが講師の仕事と言われると、言い返す言葉は無いですが、
相手が前向きな姿勢でないと聞いてはもらえない気もしますし…
(これについては、もう少し勉強しないといけない事もありますね)



2011年8月15日月曜日

第8回中国GTUG勉強会@岡山を開催しました。

一昨日の事ですが、第8回中国GTUG勉強会@岡山を開催しました。

詳細は中国GTUGのサイトを見て頂ければ、写真と合わせて見ることが
できるようになっています。

第8回中国GTUG勉強会@岡山
http://sites.google.com/site/chugokugtug/event/8

ここでは、私のチームの事について掘り下げておこうと思います。
私のチームでは、「作業用BGMを再生するアプリケーション」を作ろうと
考えました。私が欲しい物だったのですが、作業用BGMを再生するために
毎回YouTubeやニコニコ動画にログインしたりするのは、ちょっと面倒だと
思っていました。そこで、YouTube Data APIとカスタムプレーヤーを使えば
いちいちYouTubeのサイトに行かなくても何とかなるかな?と考えたわけです。

第8回は初心者向けということで、ノープランの人の為に、チームに誘って
私ともう一人の方の2人のプロジェクトになりました。

カスタムプレーヤーの件については以前のエントリーに書いてある通りで
httpを経由してデータを受け取らないとコールバック関数が呼ばれない
現象があるようなので当日はGAE/Gの開発サーバを使ってhttpでの経由をさせました。

カスタムプレーヤーが置いてあるだけでは面白味がなかったので、
テレビの絵を描いて頂いて、テレビのように見せることにしました。

結局、HTML5的要素としては、DOCTYPEとscriptタグにtypeを付けないだけに
なってしまいましたが、早くYouTubeのカスタムプレーヤーがvideoタグで
実現できるようになってくれれば良いなあと思っています。

ソースコードも公開していますので、興味がありましたら
以下のURLから取得して下さい。

作成したテレビアプリケーションのソースコード(github)
https://github.com/tyokoyama/chugokugtug_tv

(2011/08/31追記)
忘れていましたが、秋葉さんにCSS3の本にサインをして頂きました。
良い本だと思いますのでよろしければ。





2011年8月11日木曜日

YouTubeのカスタムプレーヤーAPIのコールバック関数の件が解決しました

以前、以下の件で苦戦していた事について、一応の解決をしたのでメモ。
http://takashi-yokoyama.blogspot.com/2011/07/youtubeapionyoutubeplayerready.html

どうやら、YouTubeのカスタムプレーヤーのコールバック関数はファイルを直接開くと
(file://というURLで開く場合)
onYouTubePlayerReady()が呼び出されないようです。
仕様の記述を見つける事ができていないのですが、
Webサーバに配置してhttpアクセスをした場合は関数が呼び出される事が確認できました。
Webサーバはapacheでも良いし、GAE/Gの開発サーバを使っても良いです。

ということで、利用する場合はWebサーバに配置した状態でアクセスする必要があります。

これはブラウザの仕様なのか、httpの仕様なのか、まだまだ勉強が必要なようです。

2011年8月2日火曜日

Google App Engine Goでは"_"(アンダースコア)に気をつけろ

Google App Engine for Go SDK1.5.2のローカル環境で発生しているのですが、
アプリケーションの初回ビルド時にGo言語のソースファイルに"_"が含まれていると、
ビルドは正常に通るのですが、レスポンスが404になってしまいます。
※MacOSX(32bit版SDK)とUbuntu11.04(64bit版SDK)で現象を確認しました。

例えば、以下のような構成で、
app.yaml
compiletest(ディレクトリ)
  compile_test.go

app.yaml
application: helloworld
version: 1
runtime: go
api_version: 2

handlers:
- url: /.*
  script: _go_app

compile_test.go
package compiletest

import (
 "fmt"
 "http"
)

func init() {
 http.HandleFunc("/", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
 fmt.Fprintf(w, "Hello World!")
}

中身はただのHelloWorldですが、この構成で初回ビルドを行うと、404が返ってきます。これが、ファイル名から"_"を削除した状態にして
アクセス(コンパイル、実行)した後、再度、"_"を付けた状態にしても正常に動作するようになります。

ということで、バグなのか、仕様なのか(多分バグだと思います)わかりませんが、ファイル名に"_"を付けた命名は
今の所、気をつけた方が良いと思います。

ちなみに、本番環境では試していないのでわかりません。

2011年8月1日月曜日

vi、emacsにGoのソースコード設定を追加する。

Go言語のソースコードを読んだり、書いたりするためには、
今の所、私が知る限りでは、vi、emacs、その他テキストエディタで開いて中身を見るしか
方法がありません。
ということで、Go言語のソースコードをダウンロードすると、一緒にvi用、emacs用の設定ファイルが
ついてきます。それを導入したので、メモを残しておきます。

●viの設定(on Ubuntu11.04 64bit版)
設定ファイルの場所:$GOROOT/misc/vim

1. sudo apt-get install vim
初期状態のvimだと2の設定が有効にならない(エラーになる)ので最新の状態にしておく。

2. ~/.vimrcに以下の記述を追加する。
filetype plugin on
filetype indent on

2.5. Mac OSXだと、.vimrcに以下の記述も追記する必要がある。(2011/08/31追記)
syntax on

3. ~/.vim/に$GOROOT/misc/vimの設定ファイルをすべてコピーする
例)
$ cd $GOROOT/misc/vim
$ cp -rp * ~/.vim

4. Goのソースコードをviで開いて、以下のように色が変わっていれば成功



●emacsの設定(on Mac OSX)
設定ファイルの場所:$GOROOT/misc/emacs

1. $GOROOT/misc/emacsにある設定ファイル(*.el)を~/emacs.dにコピーする
例)
$ cd $GOROOT/misc/emacs
$ cp -p *.el ~/emacs.d

2. .emacsに以下の設定を追記する。
;;これはお好みに合わせて。。(初期値は8)
(setq-default tab-width 4)

(add-to-list 'load-path "~/emacs.d")

(require 'go-mode-load)

3. emacsでGoのソースファイルを開き、以下のように色が変わればOK

2011年7月29日金曜日

Google Android WebAPIプログラミング入門(正誤表)

私が執筆したGoogle Android WebAPIプログラミング入門の正誤表を載せておきたいと思います。(ちなみに以下の本です)
このページは非公式のものとします。(2011/12/20:秀和システムさんに連絡して公式の正誤表となりました。)
また、発見、報告があり次第、追記したいと思います。



正誤表
P.272−9行目:
(誤)また、後述しますが最新版Twitter4j 2.2.1が…
(正)また、最新版Twitter4jが…

9章の9-4に関して書籍のサンプルが動作しなかったという報告をいただきました。
ありがとうございます。現象を確認したいのですが、すぐに時間が取れないので、
取り急ぎ、サイトへのリンクを掲載しておきます。
http://sarl-tokyo.com/wiki/index.php?Google%20Android%20WebAPI%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%85%A5%E9%96%80%E3%82%92%E8%AA%AD%E3%82%93%E3%81%A7%E3%81%84%E3%81%A6

2011年7月25日月曜日

Google App Engine Go SDK 1.5.2での注意点

Google App Engine SDKのバージョンが1.5.2になりました。

リリース内容は以下のサイトを御覧ください。
http://googleappengine.blogspot.com/2011/07/app-engine-152-sdk-released.html


私もGoのSDKを更新してプログラムが動くかどうか確認していたのですが、
ローカルサーバで実行するとdev_appserver.pyのエラーが出て実行できなくなりました。

いろいろ調べているとapp.yamlのapi_versionを2にしないといけないことがわかりました。

ということで、ドキュメントサイトを確認してみたら、サンプルコードは2になっていましたが、説明には1と記述されていたので注意が必要です。

一応、Hello Worldのコードを掲載しておきます。

application: helloworld
version: 1
runtime: go
api_version: 2

handlers:
- url: /.*
  script: _go_app


package hello

import (
       "fmt"
       "http"
)

func init() {
     http.HandleFunc("/", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
     fmt.Fprint(w, "Hello World!")
}

大したコードではないですが、api_versionには注意してください。
これに気がつくのにかなりの時間を取られました。

ただ、クラウド上にデプロイして実行する分にはapi_versionが1でも動作します。
(※HelloWorldレベルで確認しただけです)
デプロイのコマンドは以下のコマンドです。
appcfg.py update [ソースコードがあるディレクトリ]

2011年7月9日土曜日

第10回OITEC勉強会に参加しました。

今日は岡山でMicrosoft関連の技術を主に扱っているOITEC勉強会に参加しました。

会場が県立図書館のデジタル情報シアターだったので、飲食禁止。
しかも、いい感じで無線LANスポットも使えず、色々と残念な状態でした。
(結局、Android端末でテザリングをしました。電源が使えたので良かった。)

午前の部はTDDBCのサテライトということで、Ust放送をしていました。
テスト駆動開発がテーマでしたが、良い点、悪い点はあるような気がしました。
Twitter上でのやりとりは以下にまとめられています。
http://togetter.com/li/159430

午後の部
Kinect開発、はじめの一歩
・結構スペックを要求される。

開発方法
・OpenNIを利用する
Macでは開発が不可能かと思ったら、詳細は以下のブログにまとめられていました。
http://switch.dip.jp/toro/blog/?p=266

・Microsoftが提供しているSDKを利用する。

価格に対して、いろいろ遊べるので良いそうです。
導入、開発も簡単。(Visual Studio 2010とKinect SDKがあれば良いのかな?)

教育、医療分野では導入実績もあるそうです。
服を買う時に、服を着た映像を表示するなどマーケティングにも利用される。

手話を声に変換するという使い方もできるようになるかもしれない。
一番の期待はアクセシビリティ

しかし、環境がWindows7限定になっているのが残念。

ASP.NET MVC 3
・Microsoft .NET Framework 4のみのサポート

・データを参照する(Model)
・ルーティングに従って、クラスが実行される(Controller)
・Razorビュー・エンジン
View内でもブレークポイントがおける。

Razorでは、@変数名でView内に値を表示させる事ができる。
@("<strong>")なんてことをすると、HTMLがエスケープされる。
@Html.Row()を使うと、HTMLがそのまま出力される。
@{ }で囲むと、View内でコードを書くことができる。
コードブロック内でもHTMLのタグはタグとして認識してくれる。
<text>タグで囲むと、プログラムと認識されずに、そのまま出力してくれる。

ASP.NET MVC 3 EF4.1 Code FirstとNuGet
・Ruby on RailsのようにModelからデータベースを生成してくれる。
・バリデーションも自動的に。

・SQL Server Compact Edition 4.0をWebサーバにデプロイすることができるようになった。
SQLiteのような利用が可能になる。
・ただし、利用可能なホスティング業者が少ないので、実運用するためには…?

NuGet
・Ruby Gemのようにプロジェクトに必要なライブラリを取り込むアプリケーション
GUI、CUIどちらでも利用可能。

0から始めるExpression Blend + Phone 7
・疲労困憊により、デモを眺めているだけになりました。
(やっぱり最近、目の疲労からくる疲れ(?)に悩まされます。)

2011/07/10 追記
プレゼント大会で、以下の書籍を頂きました。以前からSilverlightはやりたかったので
しっかり読んでみようと思います。

2011年7月8日金曜日

YouTubeAPIのコールバックonYouTubePlayerReady関数がコールされない

今日はYouTube APIを使ってみようと思い、サンプルコードを作ってみたのですが、
YouTubeの動画が表示されて、マニュアルだと再生されるようにもなりました。

しかし、JavaScriptのコールバック関数が呼ばれない状態に陥っています。
原因はなんだろう。

これをHEADタグの所に仕込んで、
 
  google.load("swfobject", "2.1");

  function onYouTubePlayerReady(playerId) {
    alert(playerId);
    console.log('onYouTubePlayerReady' + playerId);
  }

以下の処理をBODYの所に仕込んでみました。

var player;
  var swfUrl = 'http://www.youtube.com/v/u1zgFlCw8Aw?enablejsapi=1&playerapiid=ytplayer';

  var params = { allowScript: "always", bgcolor: "#cccccc" };

  var atts = {id: "myytplayer" };
  swfobject.embedSWF(swfUrl, "ytapiplayer", "640", "360", "9", null, null, params, atts);

仕様では、onYouTubePlayerReadyが呼び出されるはずなんだけど。。。
HTML5だと動かないとかかな…?
(HTML4.01の例ならあったし、表示したら動いていた)

2011年6月26日日曜日

第19回オープンラボ岡山

第19回オープンラボ岡山に参加したので、メモを残しておきます。
色々と抜けてたり、間違いもあると思いますが、参考程度に。
  • 昨日までは Tomcat 今日からは GlassFish
GlashFishがすごいらしい。
http://d.hatena.ne.jp/t_yano/20101227

Tomcatだと、色々なフレームワークが必要で、単体では使っていない。
→実は事足りてないんじゃないのか?
→GlashFishだといろんなフレームワーク等も含まれている。

Tomcatだと運用が大変じゃないか?
→1台ずつマシンにログインして設定が必要。
→GlashFishだと、1台のマシン(管理サーバ)にアクセスすれば全て管理可能。

TomcatユーザにおくるGlashFishのすすめ
1. 軽量
2. インストールが簡単(Zipを展開すればOK)
3. IDEとの連携が簡単
Eclipseプラグイン、NetBeansバンドル

GlashFish v3.1 vs Tomcat 7
・2011/01 Tomcat 7 安定版リリース、サポートなし
・2011/02 v3.1 本番向け、サポート有り
・2011/07 v3.1クラウド向け、Java SE 7

オープンソース版を使っても、製品版にアップグレードが可能。

再配備時にセッションを持続させる事ができる。
・オプション-keepSessions=trueに設定

GlashFishにおけるOSGiとHK2の役割
OSGiランタイム
・デフォルトApache Felixを使用(他のランタイムも動作する)

OSGiの採用によるメリット
・動的なモジュールの追加、削除
・拡張可能なアプリケーションサーバ
・任意のOSGiバンドルを利用可能

Grizzly
・ネットワークサーバアプリケーションのOSSプロジェクト
・Java NIOを採用
・サーバエンジンの実装
・Non Blockingの通信に対応(少ないスレッドで多くのリクエストを処理できる)

GlashFishの新機能について
・アプリケーションバージョンニング
→同一アプリケーションの複数配備
→asadminでバージョンの切り替え、有効なバージョンの確認も可能
・自己増殖クラスタ
→対象ノードへのインストールはSSH経由(SSHのデーモンとJDKがあれば可能)
自分自身をZipで固めてインストール
・WebSocketへの対応
→今までのやり方よりも、パフォーマンスが良い。

Java EE 6のベストセラー本もある。

まとめ:
・まずはお試し下さい。

質問:
・製品版GlashFishのサポート料は?
→パートナー経由での販売をしているので、パートナーに問い合せて下さい。
→WebLogicは大規模環境、GlashFishは先進性を求める時に。

JBoss AS7について
・起動が早い。(1.6秒)
・超軽量
・起動に必要なメモリ=12M
・Tomcat7は=8M。(ただし、サーブレットコンテナしか入っていない)

・管理容易性の向上
・設定ファイル(単一)
・API、GUI、CUIを容易

・作り直した理由
・クラウド前提
・Amazon EC2などを使ってみても、遅い。
・スタンドアロン
・ドメイン

・デモ
・2.7秒で起動(alpha3、少し汚れている)
・1.8秒で起動(beta4、スナップショット)
・管理画面はGWTベース

・arquillian(JBoss7から提供されるテストフレームワーク)
・JUnitのテストで簡単に記述が可能になる。

・JBoss Modules
・モジュール=JARを指す

・階層型クラスローダの問題
・上から実行するか、下から実行するか、両方動かすと簡単にデッドロック?

・スレッドコンテキストクラスローダ

・JBoss MSC
・JBoss Moduler Service Container
・AS7の新しいカーネル

質問:
・Amazon EC2での稼働実績などは?
→JBoss AS7のリリースがまだなので、実績はないが、10秒ぐらいでいけるのでは?

Java EE 6の詳細
・今後は本番環境へ
・今までは、お試しレベルだった。
・メインテーマ:開発生産性の向上

・仕様の削減
・古く使われなくなったAPIの整理
・コンポーネントのオプション化
・Java EE7で削除される可能性
・JAX-RPC→JAX-WS
・EJB Entity Beans→JPA
・JAXR
・JSR-88

・統合開発環境…

・Managed Bean 1.0
・@javax.annotation.ManagedBeanを指定
・コンテナによって管理
・他のJava EE コンポーネントのベース
・呼び出し元と同じスレッドで事項
・代表的なアノテーション
・@Resource
・@PostConstruct
・@PreDestroy
・JSR-250を参照

・Interceptors 1.1の使用
・自身のインターセプタクラスの作成

・Servlet 3.0
・web.xmlのオプション化
・アノテーションを使う。

・@WebServlet{name="hello"…}

・拡張性
・設定ファイルによる拡張
・web-fragments.xml
・サードパーティフレームワークの追加が容易
・プログラムによる拡張

・マルチパート対応
・@MultipartConfig

・非同期処理のサポート
・非同期リクエスト処理用のプログラムモデル
・長時間処理が必要なリクエストに有効
・Async用アノテーションを追加
・@WebServlet(asyncSupported=true)
・AsyncContext aCtx = req.startAsync(req, res);

・セキュリティの拡張
・認証/ログイン/ログアウト機能

・JavaServer Faces 2.0
・テンプレート機能
・Ajax対応
・JSFの仕様でJavaScript APIが定義
・<f:ajax execute="productname"…
・1行で対応可能
・ブックマーク可能なURL

・EJB 3.1
・JSR-318
・warファイルにEJBを含める事ができるようになった。
→まとめ方を考える必要がなくなる(EARなのか、WARなのか)

・Lite

・Full
・Lite + …

・標準化された Global JNDI名
・アプリケーションサーバによって、名前が違っていた。
・Java EE 6から
・JNDI名が標準化される。

・組み込み可能なEJBコンテナ
・javax.ejb.jar

・その他
・タイマーサービス

・Singleton Session Bean
・JVMをまたがらない、個々のJVMでのSingletonを保証

・JPA 2.0
・EJBの仕様から独立
・モデリングの強化
・@ElementCollection
・@CollectionTable(name="NICNAMES")
・組み込み可能型コレクション
・MapのCollection
・Criteria API
・クエリの制御をJavaオブジェクトで制御
・CriteriaBuilder
・EntityManager#getCriteriaBuilder()
・Metamodel API
・型チェックが強力
・コンパイル時に属性の有無、型チェックを実施

・JAX-RS 1.1

・Bean Validation 1.0
・アプリケーション中で宣言的なバリデーションが可能

・DI 1.0/CDI 1.0
・beans.xmlを必ず配置する。(デフォルト無効)

・Java EE 7に含まれる技術
・JPA 2.1
・JAX-RS2.0
・JMS 2.0
・JavaServer Faces 2.2
・WebTier
・HTML5
・WebSocket
・JSON API

質問:
・プロファイルの提供で、Webプロファイル以外に何かあるか?
→現時点ではWebプロファイルかFullしかない。
・アノテーションが増えたのは良いが、判別するためには、全クラスを
読み込んでおく必要があるので、遅いのでは?
→アノテーションスキャンは遅いです。
ただし、index化したりして早くする仕組みはあるだろう。

CDIを乗りこなせ
・JSR-299
・参照実装=Weld

・Portable Extension
・implements Extension
・Extensionは中身が空のインターフェイス

・Seam Catch
・例外ハンドリングを提供
・例外が発生したら、メソッドを実行されるようにする。

・Seam Faces
・JSFのフェーズコールバック

・Seam Solder
・はんだづけ
・Expression Languageを提供

・Seam Forge
・シェル環境を提供
・鍛冶場

と、ここで、MacBookProのバッテリーが残り少なくなったので
ここまででメモは終わり。

Desireでテザリングをしながらバッテリー駆動だと4、5時間程度で
残りがやばくなるようです。(だいぶ余裕を持って電源を切ったかもしれない(?))

2011年6月23日木曜日

設定アプリケーションから、アプリケーションの強制停止ボタンを押したら。

今日は、設定→アプリケーション→アプリケーションの管理→アプリケーションの詳細画面で
強制停止ボタンを押した時の挙動についてメモしておきたいと思います。

今回はAndroid2.2のソースコードを見た結果です。

ボタンを押すと、ActivityManager#forceStopPackage(String packageName)が
呼び出されます。

以下が、onClickメソッドの呼び出し元です。

} else if (v == mForceStopButton) {
            forceStopPackage(mAppInfo.packageName);

メソッド化されているのでその中身を見ると、確かにActivityManager#forceStopPackageが呼び出されているようです。

private void forceStopPackage(String pkgName) {
        ActivityManager am = (ActivityManager)getSystemService(
                Context.ACTIVITY_SERVICE);
        am.forceStopPackage(pkgName);
        checkForceStop();
    }
}

その後も、forceStopPackage()の中身も追いかけてみました。
ActivityManagerNative#getDefault()を呼び出しているようです。

public void forceStopPackage(String packageName) {
        try {
            ActivityManagerNative.getDefault().forceStopPackage(packageName);
        } catch (RemoteException e) {
        }
    }

getDefault()の中身は、よくわからないサービスが呼び出されていました。

static public IActivityManager getDefault()
    {
        if (gDefault != null) {
            //if (Config.LOGV) Log.v(
            //    "ActivityManager", "returning cur default = " + gDefault);
            return gDefault;
        }
        IBinder b = ServiceManager.getService("activity");
        if (Config.LOGV) Log.v(
            "ActivityManager", "default service binder = " + b);
        gDefault = asInterface(b);
        if (Config.LOGV) Log.v(
            "ActivityManager", "default service = " + gDefault);
        return gDefault;
    }

この後は結局見るのをやめたのですが、何かのサービスがいて、そのサービスが
プロセスをkillしているのかどうかは不明ですが、アプリケーションを終了させている
ようです。

サービスの中身は、以下のサイトに書いてあるような事がされているのでしょうか。
androidアプリをクリーンに終了させる方法
http://jp-shibax.air-nifty.com/blog/2010/05/android-e2dd.html

もう少し、ソースコードを追いかけてみる必要がありますが、
今日はこの辺でやめておきたいと思います。

2011年6月20日月曜日

Blogger上でソースコードに色をつけるための情報

Bloggerに移転するときに、「この機能が欲しい」と思っていたのが、
ソースコードを添付した時の色付け機能です。
ただ、Bloggerには標準で用意されているわけではないので、
自分でテンプレートを編集したりして、機能を追加する必要があります。
私は、Syntax Highlighterとgoogle-code-prettifyを導入しました。
ただ、Blogの背景が今のところ黒なので、Syntax Highlighterを利用することに
なりそうです。

ということで、導入までに参考にしたサイトが、以下のサイトです。
もし、同じ悩みがあれば、参考にしていただけたら幸いです。

あなたのソースコードを彩る、Syntax Highlighterまとめ
http://blog.37to.net/2007/06/syntax_highlighter/

BloggerにおけるSyntaxHighlighterの使い方
http://moririn-web.blogspot.com/2010/03/bloggersyntax-hilighter.html

Blogger でソースコードに色付けをする - google-code-prettify
http://jutememo.blogspot.com/2008/01/blogger.html

2011年6月19日日曜日

レイアウトのXMLに配置したButtonのOnClickがDialogだと使えない?

最近、ButtonのOnClickListenerを実装するのが面倒なので、レイアウトXMLのonClickを利用しているのですが、Dialogでも同じように使おうとしたところ、
以下のメッセージと共に、java.lang.IllegalStateException例外が発生しました。

「Could not find a method buttonClick(View) in the activity」

その時はOnClickListenerを実装した方が早かったので、深く調べなかったのですが、
たまたま思い出したので調べてみました。
※今回はAndroid2.2のソースコードを追いかけました。1.6でも同様の現象に
ぶち当たるのではないかと思います。

実際、レイアウトXMLのOnClickが設定される場所は、Viewクラスにあります。

case R.styleable.View_onClick:
                    if (context.isRestricted()) {
                        throw new IllegalStateException("The android:onClick attribute cannot " 
                                + "be used within a restricted context");
                    }

                    final String handlerName = a.getString(attr);
                    if (handlerName != null) {
                        setOnClickListener(new OnClickListener() {
                            private Method mHandler;

                            public void onClick(View v) {
                                if (mHandler == null) {
                                    try {
                                        mHandler = getContext().getClass().getMethod(handlerName,
                                                View.class);
                                    } catch (NoSuchMethodException e) {
                                        int id = getId();
                                        String idText = id == NO_ID ? "" : " with id '"
                                                + getContext().getResources().getResourceEntryName(
                                                    id) + "'";
                                        throw new IllegalStateException("Could not find a method " +
                                                handlerName + "(View) in the activity "
                                                + getContext().getClass() + " for onClick handler"
                                                + " on view " + View.this.getClass() + idText, e);
                                    }
                                }

                                try {
                                    mHandler.invoke(getContext(), View.this);
                                } catch (IllegalAccessException e) {
                                    throw new IllegalStateException("Could not execute non "
                                            + "public method of the activity", e);
                                } catch (InvocationTargetException e) {
                                    throw new IllegalStateException("Could not execute "
                                            + "method of the activity", e);
                                }
                            }
                        });
                    }
                    break;

handlerName変数には呼び出されるはずのメソッド名が設定されています。

ポイントは、以下のコードになります。

mHandler = getContext().getClass().getMethod(handlerName,
                                                View.class);

この部分で、クラス内にOnClickで設定したメソッドがあるかどうかを確認しています。
さて、今回の現象はActivityだとメソッドが発見できて、Dialogだと発見出来ないわけですから、getContext().getClass()で返されるクラスのインスタンスが違ってそうな気がします。
ということで、Dialog#onCreate(setContentView()を呼び出した直後)で

Log.d("TEST", "ClassName = " + getContext().getClass().getName());

なんてことをしてみました。

すると、出力されたログをみると、

ClassName = android.view.ContextThemeWrapper

と出力されました。

Activityだと同じ事ができないのですが、恐らく、getContext()がActivityのインスタンスを返すのだろうと思われます。

Activityのインスタンスであれば、自分で実装してあれば、メソッドが発見できますが、DialogでgetContext()するとContextThemeWrapperが返ってくるため、
OnClickのメソッドが発見出来ないわけです。

ちなみに、Dialog#getContext()が返す、Contextは、以下の通りです。
mContext = new ContextThemeWrapper(
            context, theme == 0 ? com.android.internal.R.style.Theme_Dialog : theme);

    public final Context getContext() {
        return mContext;
    }

ということで、結論は、「DialogではレイアウトXMLのOnClickは使えない」と言うことがわかりました。

DialogではおとなしくOnClickListenerを実装しましょう。