package kr.co.inger.hotwind.request_check.impl;
import java.io.Serializable;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import kr.co.inger.hotwind.guice.Guicer;
import kr.co.inger.hotwind.request_check.CheckRequest;
import kr.co.inger.hotwind.request_check.RequestProvider;
import kr.co.inger.hotwind.request_check.backend.RequestCheckKvStore;
import kr.co.inger.hotwind.request_check.session.AccessTokenedSession;
import kr.co.inger.hotwind.request_check.session.AccessTokenedSessionProvider;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Strings;
public class CheckRequestProc {
private static Logger logger = LoggerFactory
.getLogger(CheckRequestProc.class);
public Object invoke(MethodInvocation invocation, CheckRequest annot)
throws Throwable {
// 일단 저장소를 얻고.
RequestCheckKvStore store = getRequestCheckKvStore();
// 캐쉬에서 해당 메서드에 전달하는 맵이나 값이나 인자의 이름 중에 label와 일치하는 값이 캐쉬에 있는지?
boolean found = false;
BoxRef<String> storeKeyRef = new BoxRef<String>();
//
if (checkHttpHeader(invocation, annot, store, storeKeyRef)) {
found = true;
} else if (checkHttpRequestParam(invocation, annot, store, storeKeyRef)) {
found = true;
} else if (!Strings.isNullOrEmpty(annot.targetField())) {
// path-param와 같이 인자로 그대로 전달되는 경우를 위해서.
for (Object arg : invocation.getArguments()) {
if (checkAsKeyItself(store, arg)) {
found = true;
storeKeyRef.setRef(ObjectUtils.toString(arg));
break;
}
}
}
//
if (found) {
Map<String, Serializable> session = bindSession(invocation, store,
storeKeyRef);
//
Object result = invocation.proceed();
// preserve.
updateStoredSession(store, storeKeyRef, session);
//
return result;
} else {
throw new Exception(annot.errorMessage());
}
}
private void updateStoredSession(RequestCheckKvStore store,
BoxRef<String> storeKeyRef, Map<String, Serializable> session) {
if (session != null && store != null && storeKeyRef != null
&& storeKeyRef.getRef() != null) {
//
final String key = storeKeyRef.getRef();
if (store.isExists(key)) {
store.update(key, session);
} else {
logger.debug(String.format(
"update-stored-session skip, not found. -- %s", key));
}
}
}
private RequestCheckKvStore requestCheckKvStore = null;
private RequestCheckKvStore getRequestCheckKvStore() throws Exception {
if (requestCheckKvStore == null) {
try {
requestCheckKvStore = Guicer.get().getInstance(
RequestCheckKvStore.class);
} catch (Exception exc) {
logger.error("No binding for RequestCheckKvStore interface!!!");
throw exc;
}
}
//
return requestCheckKvStore;
}
private Map<String, Serializable> bindSession(MethodInvocation invocation,
RequestCheckKvStore store, BoxRef<String> storeKeyRef) {
if (invocation.getThis() instanceof RequestProvider
&& storeKeyRef.getRef() != null) {
//
final String accesstoken = storeKeyRef.getRef();
//
Map<String, Serializable> session = (Map<String, Serializable>) store
.fetch(accesstoken);
//
RequestProvider rp = (RequestProvider) invocation.getThis();
HttpServletRequest req = rp.getHttpServletRequest();
if (null != req
.getAttribute(AccessTokenedSessionProvider.SESSION_SAVE_KEY)) {
AccessTokenedSession ats = (AccessTokenedSession) req
.getAttribute(AccessTokenedSessionProvider.SESSION_SAVE_KEY);
ats.setAccesstoken(accesstoken);
ats.setInnerMap(session);
} else {
AccessTokenedSession ats = new AccessTokenedSession();
ats.setAccesstoken(accesstoken);
ats.setInnerMap(session);
req.setAttribute(AccessTokenedSessionProvider.SESSION_SAVE_KEY,
ats);
}
return session;
} else {
logger.warn("SKIP set AccessTokenedSession, your JAX-RS resource class isn't a RequestProvider or session-key not-found.");
return null;
}
}
private boolean checkAsKeyItself(RequestCheckKvStore store, Object arg) {
if (store.isExists(ObjectUtils.toString(arg))) {
logger.debug(String.format(
"arg itself is in request-check-kv-store. (%s)", arg));
return true;
} else
return false;
}
private boolean checkHttpHeader(MethodInvocation invocation,
final CheckRequest annot, RequestCheckKvStore store,
BoxRef<String> storeKeyRef) {
try {
Object obj = invocation.getThis();
if (obj instanceof RequestProvider
&& !Strings.isNullOrEmpty(annot.httpHeaderName())) {
RequestProvider rp = (RequestProvider) obj;
HttpServletRequest r = rp.getHttpServletRequest();
final String k = annot.httpHeaderName();
final String val = (String) r.getHeader(k);
if (checkAsKeyItself(store, val)) {
logger.debug(String.format(
"http-header has %s = %s, and request-checked ok.",
annot.httpHeaderName(), val));
storeKeyRef.setRef(val);
return true;
}
}
} catch (Exception exc) {
logger.warn(
"http-header lookup FAIL! please implement RequestProvider in your JAX-RS resource class.",
exc);
}
return false;
}
private boolean checkHttpRequestParam(MethodInvocation invocation,
final CheckRequest annot, RequestCheckKvStore store,
BoxRef<String> storeKeyRef) {
try {
Object obj = invocation.getThis();
if (!Strings.isNullOrEmpty(annot.targetField())
&& obj instanceof RequestProvider) {
RequestProvider rp = (RequestProvider) obj;
HttpServletRequest r = rp.getHttpServletRequest();
final String v = r.getParameter(annot.targetField());
if (checkAsKeyItself(store, v)) {
logger.debug(String
.format("http-request has %s = %s, and request-checked ok.",
annot.targetField(), v));
storeKeyRef.setRef(v);
return true;
}
}
} catch (Exception exc) {
logger.warn(
"http-parameter lookup FAIL! please implement RequestProvider in your JAX-RS resource class.",
exc);
}
//
return false;
}
}