プログラミング&セキュリティキャンプ・キャラバン2009(東京)

参加してきました。勉強会初参加。いや〜、刺激になりました〜。

業務でWebアプリの開発してるけど、閉じられたネットワークで動いてるシステムなんで、セキュリティ詳しくありません。一番考えさせられたのが、クラウドとか Web API を使ったサービスを提供する場合、自分の与り知らぬ所のモノを使うことになるんだよ、ってトコ。


Google App Engine のデータストアで障害起きたとき、それ使ってサービス提供してたらと思うと…やっぱ内製というか、自社だけでサービスを提供できるのが理想なのかなぁ、なんて。でも基盤から持ってる企業なんて少数だよね。でもクラウドを使わずにコスト面以外で闘うって言ってもねぇ。まとまりないけど、いろいろ考える事があります。


流行だし、1クリックデプロイの手軽さから Google App Engine For Java で遊んでるけど、これを実務で使うってなったら、いろいろ知らなきゃならないことがいっぱいある。でもきっと、GAEを実務で使う事がなかったとしても、Key-Valueデータストアや分散処理を意識した構造はきっと役には立つはず。


@ITの自分戦略研究所のコラムを読んでると、この仕事の将来がものすごい不安になるけど、とりあえずは技術を磨き続けることを考えていきます。来年春の情報セキュリティスペシャリストの試験を受けようかな。

Objectに定義されているメソッドの実装を強制する

Object#hashCode(), Object#equals() などのメソッドは抽象クラスの抽象メソッドとして定義できる。


public abstract class MyAbstractClass {
public abstract int hashCode();
public abstract boolean equals(Object obj);
}
上記のクラスを継承したら、hashCode(), equals() を実装しないとコンパイルエラーになる。

インターフェースだと意味無し。


public interface MyInterface {
public int hashCode();
public boolean equals(Object obj);
}
上記のインターフェースを implements してもコンパイルエラーにはならない。

RSS2.0 の pubDate フォーマットの日付時刻を SimpleDateFormat で解析する。

RSS2.0 の pubDate はこんな感じ。
<pubDate>Tue, 22 Sep 2009 19:24:08 +0900</pubDate>
曜日と月は US ロケールの文字列。
"+0900" は RFC820フォーマットのタイムゾーン解析文字 Z で解析する。


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

public class DateFormatSample {
public static void main(String[] args) {
try {
String s = "Thu, 06 Aug 2009 08:21:24 +0900";
DateFormat input = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
Date d = input.parse(s);

DateFormat output = new SimpleDateFormat("yyyy/MM/dd (E) HH:mm:ss z");
System.out.println(output.format(d));
} catch (ParseException e) {
e.printStackTrace();
}
}
}

実行結果:
2009/08/06 (木) 08:21:24 +0900

csh で "<>" は否定演算子!?

打ち合わせで見た csh のコード


if ( 1 <> $status ) then
それは SQL の not equal でんがな。よくよく聞いてみるとこのコードは動いたらしい。マジっすか!?

mac で動かしてみた。


if ( 1 <> $1 ) then
echo 'true'
else
echo 'false'
endif
動く。シンタックスエラーにならない…。けど、何を入れても true にならない…。いったい何を評価しているのだろうか。

tcshデバッグモードで動かしてみる。


% tcsh -x ./notequal.csh 0
tcsh -x ./notequal.csh 0
if ( 1 < > 0 ) then
echo false
false
endif
やはり <> なんていう演算子はないのだ。< と > が個別に動いているだけ。左の < の引数は ">" なのか、それとも "> 0"なんだろうか。tcsh のソースを見てみるか。
次号に続く…(?)

標準出力を JTextArea に出力する

System.setOut(PrintStream out) で標準出力の出力先を変更できる。
JTextArea に転送するような PrintStream を作れば、JTextArea がコンソール代わりに。
JTextArea に出力する際は、Swing のイベントディスパッチスレッドにのせる必要がある。


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class JTextAreaStream extends OutputStream {

private JTextArea _area;
private ByteArrayOutputStream _buf;

public JTextAreaStream(JTextArea area) {
_area = area;
_buf = new ByteArrayOutputStream();
}

@Override
public void write(int b) throws IOException {
_buf.write(b);
}

@Override
public void flush() throws IOException {

// Swing のイベントスレッドにのせる
SwingUtilities.invokeLater(new Runnable() {
public void run() {
_area.append(_buf.toString());
_buf.reset();
}
});
}

public static void main(String[] args) {
JTextArea area = new JTextArea();
area.setEditable(false); // ReadOnly に
JTextAreaStream stream = new JTextAreaStream(area);
System.setOut(new PrintStream(stream, true)); // true は AutoFlush の設定

JFrame frame = new JFrame();
frame.getContentPane().add(area);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(50,100);
frame.setVisible(true);

System.out.println("あああ");
System.out.println("いいい");
System.out.println("ううう");
}
}

実行結果

親クラスのコンストラクタを呼ぶ前に

super() はコンストラクタの1行目で記述しなければならないが、
親クラスのコンストラクタを呼ぶ際に複雑な処理を行いたい場合は
static のヘルパメソッドを使う。


public class Derived extends Thread {

public Derived() {
super(createString()); // 親のコンストラクタ public Thread(String name) を呼ぶ
}

private static String createString() {
return "複雑な処理で生成された文字列";
}
}

this(), super() の呼び出し中はメンバメソッドは呼び出せない。