Download - お題でGroovyプログラミング: Part A
summer special g* workshop / 2009.08.22slide #1
お題でGroovyプログラミング
summer special g* workshop / 2009.08.22slide #2
このセッションのねらい! 具体的かつ実践的な、短い「お題」を使ってGroovyの特徴や便利さを伝えたい
! 一方的な解説ではなく、みんなで一緒に考えることで理解を深めたい
プレゼントもあるよ!
summer special g* workshop / 2009.08.22slide #3
進め方! 「お題」とヒント・注意点の説明
http://groups.google.com/group/jggug-summer-2009
! プログラミング・タイム! できた人はコードを次のアドレスにポスト[email protected]
subjectにお題番号と回答者の名前/ハンドルを書いてください! 回答者からの発表
! 解答例とポイントの解説 質問はいつでもお気軽に
summer special g* workshop / 2009.08.22slide #4
アジェンダ! Part A ‒ 関谷
! ファイル処理、フィードリーダー、簡易サーバ! Part B ‒ 上原
! 正規表現、JDKへのメソッド追加、Twitter! Part C ‒ 須江
! Swing、XML編集
summer special g* workshop / 2009.08.22slide #5
準備! Java 5以降およびGroovy 1.6.xがインストールされていること
! 環境変数JAVA_HOMEおよびGROOVY_HOMEが設定されていること
! $GROOVY_HOME/binにパスが通っていること
! 確認方法% groovy -vGroovy Version: 1.6.4 JVM: 1.5.0_19
summer special g* workshop / 2009.08.22slide #6
Groovyとは(1分で)! Java VM上で動作する動的スクリプト言語
! JSR-241で標準化。実装はオープンソース! 特徴
! 簡潔さ– RubyなどのLLと同水準の強力な表現力
! 柔軟性– 動的、メタプログラミング、DSL向き
! Javaとの親和性– 構文、相互呼び出し、実行環境、知識/ノウハウ
summer special g* workshop / 2009.08.22slide #7
Part Aコーディネータ:関谷
summer special g* workshop / 2009.08.22slide #8
お題 A-1: ファイルコピー! 指定したファイルを指定した名前にコピーするスクリプトを書いてください! Input/OutputStream や Reader/Writer を使わずにやってみましょう
% groovy filecopy <srcfile> <destfile>
summer special g* workshop / 2009.08.22slide #9
お題 A-1: ヒントと注意点! コマンドライン引数は args[0], args[1]! いろいろな方法があります
! GDKでFileクラスに追加されたメソッドを活用! 外部コマンドを起動! Antタスクを利用! ベストな方法は?
groovy.util.AntBuilder
File#getText(), readBytes(), append(), leftShift()...
String#execute()
summer special g* workshop / 2009.08.22slide #10
解答例 A-1a
src = new File(args[0])dest = new File(args[1])dest << src.text
普通のjava.io.Fileクラス
dest.leftShift(src.getText()) と等価leftShiftはappendを呼び出すいずれもGDKにより追加されたメソッド
バイナリファイルに対しては正しく動作しない!
summer special g* workshop / 2009.08.22slide #11
解答例 A-1b
src = new File(args[0])dest = new File(args[1])dest << src.readBytes()
巨大なファイルではOutOfMemoryErrorが発生!
summer special g* workshop / 2009.08.22slide #12
解答例 A-1c
proc = "cp ${args[0]} ${args[1]}".execute()proc.waitFor()
waitFor() はなくても動くが、cpの完了を待たずにスクリプトが終了してしまう
巨大なファイルでもOKだが、UNIXのcpコマンドに依存
summer special g* workshop / 2009.08.22slide #13
解答例 A-1d
ant = new AntBuilder()ant.copy(file:args[0], tofile:args[1])
ベストな解?テキストでもバイナリでもOK巨大なファイルにも対応し、プラットフォーム非依存
Antのcopyタスク
summer special g* workshop / 2009.08.22slide #14
お題 A-2: フィードリーダー! 指定したURLからフィードを読み込み、ヘッドライン(全item/entryのtitle)を出力するスクリプトを書いてください
! できれば、RSS 1.0/2.0、Atom等、多様なフィードフォーマットに対応できるようにしてみてください% groovy feedreader <URL>
summer special g* workshop / 2009.08.22slide #15
お題 A-2: ヒントと注意点! フィードの取得と解析は XmlParser または xmlSlurper の parse(String url) が便利
! フィード要素へのアクセスはGPath記法で
summer special g* workshop / 2009.08.22slide #16
RSS 0.9/1.0の基本構造<rdf:RDF> <channel> ... </channel> <item> <title>...</title> ... </item> <item> <title>...</title> ... </item></rdf:RDF>
summer special g* workshop / 2009.08.22slide #17
RSS 0.9x/2.0の基本構造<rss> <channel> ... <item> <title>...</title> ... </item> <item> <title>...</title> ... </item> </channel></rss>
summer special g* workshop / 2009.08.22slide #18
Atomの基本構造<feed> ... <entry> <title>...</title> ... </entry> <entry> <title>...</title> ... </entry></feed>
summer special g* workshop / 2009.08.22slide #19
解答例 A-2root = new XmlSlurper().parse(args[0])switch(root.name()) { case 'RDF' : nodes = root.item; break case 'rss' : nodes = root.channel.item; break case 'feed': nodes = root.entry; break}nodes.each { println it.title }
summer special g* workshop / 2009.08.22slide #20
お題 A-3: 簡易webサーバ! ブラウザからのリクエストに対して、常に固定HTMLファイルを返すHTTPサーバを書いてください! groovyコマンドの -l (listen)オプションを使ってください
% groovy -l 8080 httpserver
summer special g* workshop / 2009.08.22slide #21
お題 A-3: ヒントと注意点! -l <port> オプションの働き
! 指定したポートでクライアントからの接続を待ち受ける
! 接続があったら、クライアントから送られて来るデータを行単位で変数lineにセットしつつ、スクリプトをループ実行する
! 一つの接続に対するループを終了するには return 'success' を実行する
summer special g* workshop / 2009.08.22slide #22
解答例 A-3if (!line) { println 'HTTP/1.0 200 OK' println 'Content-Type: text/html\n' println new File('message.html').text return 'success'}
If 文はなくても動くが、動作の理解や将来の拡張のためにはあった方が良いかも
summer special g* workshop / 2009.08.22slide #23
お題 A-3改: 簡易webサーバ! 固定HTMLファイルの中に、<% … %> や <%= … %> などを使って任意のGroovy式を埋め込めるようにサーバを拡張してください
% groovy -l 8080 httpserver
summer special g* workshop / 2009.08.22slide #24
お題 A-3改: ヒントと注意点! groovy.text.SimpleTemplateEngineを利用
! importが必要な上、名前が長いので import as を使って別名をつけると良い
summer special g* workshop / 2009.08.22slide #25
解答例 A-3改import groovy.text.SimpleTemplateEngine as STE
if (!line) { println 'HTTP/1.0 200 OK' println 'Content-Type: text/html\n' text = new File('message.html').text println new STE().createTemplate(text).make() return 'success'}
summer special g* workshop / 2009.08.22slide #26
お題 A-4: オプション解析! コマンドラインオプションを解析するスクリプトを書いてください(どう書く?orgより )! cmdopt -o [-q] -d{0|1|2} 文字列 [文字列 …]! 詳細は http://ja.doukaku.org/205/
% groovy cmdopt <arguments...>
summer special g* workshop / 2009.08.22slide #27
解答例 A-4cli = new CliBuilder(usage:'cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]')cli.with { o longOpt:'output', 'set output', required:true q longOpt:'quote', 'set quote' d longOpt:'debug', 'set debug level', args:1, argName:'level'}
if (!(opt = cli.parse(args))) die 'bad command line'params = opt.arguments()if (params.size() < 1) die 'parameter must be specified'level = opt.d ? opt.d as int : 0if (!(level in 0..2)) die 'debug level must be in 0-2'
<次ページへ続く>
summer special g* workshop / 2009.08.22slide #28
解答例 A-4
println '[オプション情報]'println "o(output): ${opt.o ? 'ON' : 'OFF'}"println "q(quote): ${opt.q ? 'ON' : 'OFF'}"println "d(debug): $level"println '\n[パラメータ情報]'println "指定数: ${params.size()}"params.eachWithIndex { param, i -> println "${i + 1}: $param" }
def die(msg) { cli.writer.println "error: $msg" cli.usage() System.exit 1}
<前ページからの続き>