Cubby+Guiceでアクションの自動登録

これやってたから
http://d.hatena.ne.jp/shin/20090720/p1
に気がついたともいえる。

全部ソース乗せる。パッケージが適当すぎるとか言わない。

package hoge;

import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.servlet.ServletModule;
import java.io.File;
import java.io.FilenameFilter;
import java.lang.reflect.Modifier;
import javax.servlet.ServletContext;
import org.seasar.cubby.action.Action;
import org.seasar.cubby.action.ActionClass;

public class ActionAutoBindModule extends AbstractModule {

    File root;
    FilenameFilter nFilter;

    public ActionAutoBindModule(ServletContext sc) {

        root = new File(sc.getRealPath("WEB-INF/classes"));
        nFilter = new FilenameFilter() {

            public boolean accept(File dir, String name) {
                if (new File(dir, name).isDirectory()) {
                    return true;
                }
                if (name.endsWith(".class")) {
                    return true;
                }
                return false;
            }
        };
    }

    @Override
    protected void configure() {
        install(new ServletModule());
        search(root, binder());
    }

    private void search(File parent, Binder binder) {
        for (File file : parent.listFiles(nFilter)) {
            if (file.isDirectory()) {
                search(file, binder);
            } else {
                bindClass(file, binder);
            }
        }
    }

    private void bindClass(File file, Binder binder) {
        String fileName = file.getAbsolutePath();
        String name = fileName.substring(
                root.getAbsolutePath().length() + 1,
                fileName.length() - ".class".length());
        name = name.replace(File.separatorChar, '.');
        try {
            Class c = Class.forName(name);
            //アノテーションがついてるか?
            if (c.isAnnotationPresent(ActionClass.class) == false) {

                try {
                    //Actionのサブクラスか?
                    c.asSubclass(Action.class);
                } catch (Exception ex) {
                    return;
                }
            }

            //publicなコンクリートクラス以外ははねる
            if(c.isInterface()){
                return;
            }
            if(Modifier.isAbstract(c.getModifiers())){
                return;
            }
            if(Modifier.isPublic(c.getModifiers()) == false){
                return;
            }

            //ここで登録する
            System.out.println(name);
            binder.bind(c);
        } catch (ClassNotFoundException ex) {
        }
    }
}


ちなみにCubby以外でも自動登録が出来てハッピー!かとおもいきや、実はこのクラス名のみのbindはCubby以外では役に立たない。

理由はCubby以外のWebフレームワークは全て自分でアクションクラスの管理をしているから。T2FrameworkでもStrutsでもJSFでもなんでもそう。これはあくまでもCubby+Guiceでも他のWebフレームワークと同等の使い勝手にするための設定。