俺俺、俺だよ、俺インタセプタを作るの巻

tomcat に付属している realm だと他のアプリケーションサーバに持っていったときに動かないので、俺インタセプタを作ってユーザ認証を行おうと思って以下のようなコードを書いた。


package sabbs.interceptor;

import java.util.Enumeration;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.aopalliance.intercept.MethodInvocation;
import org.seasar.framework.aop.interceptors.AbstractInterceptor;
import org.seasar.framework.container.SingletonS2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;
import org.seasar.struts.annotation.Execute;

import sabbs.annotation.Login;
import sabbs.dto.MemberDto;
import sabbs.enums.Role;
import sabbs.form.MemberForm;

public class LoginConfirmInterceptor extends AbstractInterceptor {

/**
*
*/
private static final long serialVersionUID = -8722302398902465135L;

/**
* ログインチェックを行う
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object ret = (!isLoginMethod(invocation) || isLoggedIn(invocation)) ?
invocation.proceed() : "/member/login?redirect=true";
System.out.println("redirect=" + ret);
return ret;
}

/**
* ログインアノテーションがついているか?
*
* @param invocation
* @return
*/
private boolean isLoginMethod(MethodInvocation invocation) {
return invocation.getMethod().isAnnotationPresent(Login.class);
}

/**
* ログインしているか
*
* @return
*/
private boolean isLoggedIn(MethodInvocation invocation) {
Map session =
SingletonS2ContainerFactory
.getContainer().getExternalContext().getSession();
MemberForm form = (MemberForm) session.get("memberForm");

Role role = invocation.getMethod().getAnnotation(Login.class).role();

if (form != null && form.userId != null) {
return true;
}
else {
if (form != null && !form.roleEquals(role)) {
form.redirect = "/index/loginError"; // 許可されていないメッセージ
sessionScope.put("memberForm", form);
return false;
}
HttpServletRequest request = (HttpServletRequest)SingletonS2ContainerFactory
.getContainer().getExternalContext().getRequest();
String str = request.getParameter("SAStruts.method");
Pattern pattern = Pattern.compile("\\.do$");
Matcher matcher = pattern.matcher(request.getServletPath());

form = new MemberForm();
form.redirect = matcher.replaceAll("") + "/" + str;

String param = null;
String genreId = request.getParameter("genreId");
if(genreId != null) {
param = form.redirect + "/" + genreId;
}

String boardId = request.getParameter("boardId");
if(boardId != null) {
param = form.redirect + "/" + boardId;
}

String msgId = request.getParameter("msgId");
if(msgId != null) {
param = form.redirect + "/" + msgId;
}

if (param != null) {
form.redirect += param;
}

sessionScope.put("memberForm", form);
return false;
}
}
}

ところがこれだと HOT Deploy の時は動かない。
COOL Deploy だと大丈夫なのになんでだーと思って、2日ほど調べたが答え的なサイトは見つらなかった。
それっぽいのはあるのだけど・・・
仕方なく(MLで質問するのは、すごーく久しぶりだけど)SeasarのMLで聞いてみたら、ひがさんから回答を頂いた。

Interceptorで、直接セッションを触っているためだと思います。
Map sessionScope =
SingletonS2Container.getComponent("sessionScope");
のようにSeasar2で管理しているオブジェクト経由で
セッションには触るようにしてください。
なるほど、HOT Deploy ではセッションはSeasar2経由で触らないと駄目なんだ。
すごくあっさりと解決してしまったので、拍子抜けの感じがあるけど無事解決。