シンプルにS2を使う

とりあえず最小限の構成で触ってみた。
servlet-api.jarは必須かぁ…

ディレクトリ/ファイル構成


メイン


public class Main {

public static final void main(String[] args) {
S2Container container = new S2ContainerImpl();
container.register(FooImpl.class);
container.register(BarImpl.class);
container.register(ZooImpl.class);
container.register(BazImpl.class);
Baz baz = (Baz) container.getComponent(Baz.class);
baz.perform();
}

}

コンポーネント(インターフェース)


public interface Bar {

public void perform();

}



public interface Baz {

public void perform();

}



public interface Foo {

public void perform();

}



public interface Zoo {

public void perform();

}

コンポーネント(実装)


public class BarImpl implements Bar {

public void perform() {
System.out.println(this);
}

}



public class BazImpl implements Baz {

private Foo foo = null;

public void setFoo(Foo foo) {
this.foo = foo;
}

private Bar bar = null;

public void setBar(Bar bar) {
this.bar = bar;
}

/////////////////////////////////////////////////////////////////
public void perform() {
System.out.println(this);
foo.perform();
bar.perform();
}

}



public class FooImpl implements Foo {

private Zoo zoo = null;

public void setZoo(Zoo zoo) {
this.zoo = zoo;
}

public void perform() {
System.out.println(this);
zoo.perform();
}
}



public class ZooImpl implements Zoo {

public void perform() {
System.out.println(this);
}
}

はてなアンテナからOPMLを生成する

at2opml.rb


#!/usr/bin/env ruby
require "open-uri"
require "csv"
require "kconv"
require "rexml/document"
$stdout.sync = true

########################################

class Page
def initialize(url)
@url = url
end

def feed
hrss = hatena(@url)
return hrss if hrss
open(@url) {|f|
f.read.scan(/<link\b[^>]+>/i) {|m|
if attr(m, "rel") == "alternate" || attr(m, "type") == "application/rss+xml"
return attr(m, "href")
end
}
}
return nil
end

private
def hatena(url)
return (url =~ %r|^(http://d.hatena.ne.jp/[^/]+)/?$|) ? $1 + "/rss" : nil
end

def attr(elem, name)
elem.slice(Regexp.new('\b' + name + '="?([^"\s]+)"?\b'), 1)
end
end

########################################

class OPML
def initialize(title)
@doc = REXML::Document.new
@doc << REXML::XMLDecl.new("1.0", "UTF-8")
root = @doc.add_element("opml", "version"=>"1.0")
root.add_element("head").add_element("title").text = title
@body = root.add_element("body")
end

def add(title, url)
page = Page.new(url)
feed = page.feed
if feed
puts title + " => " + feed
attrs = {"title"=>title, "htmlUrl"=>url, "xmlUrl"=>feed, "type"=>"rss"}
@body.add_element("outline", attrs)
else
puts "warning: #{title}のフィードが見つかりませんでした"
end
end

def write(output, indent=-1, transitive=false)
@doc.write(output, indent, transitive)
end

def to_s
return @doc.to_s
end
end

########################################

def get_lirs(id)
lirs = nil
begin
puts "#{id}のアンテナを開きます..."
f = open("http://a.hatena.ne.jp/#{id}/source?mode=lirs")
lirs = CSV.parse(f.read.tosjis)
ensure
f.close if f
end
return lirs
end

########################################

unless ARGV.length == 1
puts "at2opml.rb はてなID"
exit
end

id = ARGV[0]
filename = "antenna.xml"
lirs = get_lirs(id)
opml = OPML.new("はてなアンテナ - #{id}のアンテナ")
lirs.each {|row| opml.add(row[6], row[5])}
puts "#{filename}を書き出します..."
File.open(filename, "w") {|f|
opml.write(f, 0)
}

実行結果


~$ ./at2opml.rb winebarrel
winebarrelのアンテナを開きます...
a-sanの日記 => http://d.hatena.ne.jp/a-san/rss
chibafの日記 => http://d.hatena.ne.jp/chibaf/rss
...
antenna.xmlを書き出します...
~$