package com.aggrepoint.winlet.spring;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspApplicationContext;
import javax.servlet.jsp.JspFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import com.aggrepoint.dao.UserContext;
import com.aggrepoint.winlet.AccessRuleEngine;
import com.aggrepoint.winlet.AuthorizationEngine;
import com.aggrepoint.winlet.ConfigProvider;
import com.aggrepoint.winlet.Context;
import com.aggrepoint.winlet.ContextUtils;
import com.aggrepoint.winlet.ListProvider;
import com.aggrepoint.winlet.LogInfoImpl;
import com.aggrepoint.winlet.PsnRuleEngine;
import com.aggrepoint.winlet.ReqConst;
import com.aggrepoint.winlet.ReqInfo;
import com.aggrepoint.winlet.RequestLogger;
import com.aggrepoint.winlet.UserEngine;
import com.aggrepoint.winlet.form.FormImpl;
import com.aggrepoint.winlet.jsp.Resolver;
import com.aggrepoint.winlet.plugin.AccessRuleAuthorizationEngine;
import com.aggrepoint.winlet.plugin.DefaultAccessRuleEngine;
import com.aggrepoint.winlet.plugin.DefaultConfigProvider;
import com.aggrepoint.winlet.plugin.DefaultListProvider;
import com.aggrepoint.winlet.plugin.DefaultPsnRuleEngine;
import com.aggrepoint.winlet.plugin.DefaultRequestLogger;
import com.aggrepoint.winlet.plugin.DefaultUserEngine;
import com.aggrepoint.winlet.utils.BufferedResponse;
/**
* @author Jiangming Yang (yangjm@gmail.com)
*/
public class WinletDispatcherServlet extends DispatcherServlet {
private static final long serialVersionUID = 1L;
Map<String, RequestLogger> loggers;
UserEngine userEngine;
AuthorizationEngine authEngine;
AccessRuleEngine accessRuleEngine;
PsnRuleEngine psnRuleEngine;
ConfigProvider configProvider;
ListProvider listProvider;
public WinletDispatcherServlet() {
this.setContextClass(WinletXmlApplicationContext.class);
}
protected void initStrategies(ApplicationContext context) {
super.initStrategies(context);
Context.set(context);
loggers = context.getBeansOfType(RequestLogger.class);
if (loggers.size() == 0)
loggers.put(DefaultRequestLogger.class.getName(),
new DefaultRequestLogger());
try {
userEngine = context.getBean(UserEngine.class);
} catch (Exception e) {
}
if (userEngine == null)
userEngine = new DefaultUserEngine();
try {
authEngine = context.getBean(AuthorizationEngine.class);
} catch (Exception e) {
}
if (authEngine == null)
authEngine = new AccessRuleAuthorizationEngine();
try {
accessRuleEngine = context.getBean(AccessRuleEngine.class);
} catch (Exception e) {
}
if (accessRuleEngine == null)
accessRuleEngine = new DefaultAccessRuleEngine();
try {
psnRuleEngine = context.getBean(PsnRuleEngine.class);
} catch (Exception e) {
}
if (psnRuleEngine == null)
psnRuleEngine = new DefaultPsnRuleEngine();
try {
configProvider = context.getBean(ConfigProvider.class);
} catch (Exception e) {
}
if (configProvider == null)
configProvider = new DefaultConfigProvider();
try {
listProvider = context.getBean(ListProvider.class);
} catch (Exception e) {
}
if (listProvider == null)
listProvider = new DefaultListProvider();
// { 启用Resolver
ServletContext ctx = this.getServletContext();
JspApplicationContext jspContext = JspFactory.getDefaultFactory()
.getJspApplicationContext(ctx);
jspContext.addELResolver(new Resolver());
// }
// { 把Spring MVC的Binding Errors合并到Form中
RequestMappingHandlerAdapter adapter = context
.getBean(RequestMappingHandlerAdapter.class);
if (adapter != null) {
WebBindingInitializer initializer = adapter
.getWebBindingInitializer();
adapter.setWebBindingInitializer((binder, request) -> {
initializer.initBinder(binder, request);
((FormImpl) ContextUtils.getReqInfo().getForm())
.addBinder(binder);
});
}
// }
}
protected View resolveViewName(String viewName, Map<String, Object> model,
Locale locale, HttpServletRequest request) throws Exception {
View view = super.resolveViewName(viewName, model, locale, request);
LogInfoImpl.getLogInfo(request, null).setView(view);
return view;
}
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
ContextUtils.setDispatcher(req, this);
ContextUtils.setApplicationContext(req, getWebApplicationContext());
ContextUtils.setUserEngine(req, userEngine);
ContextUtils.setAuthorizationEngine(req, authEngine);
ContextUtils.setAccessRuleEngine(req, accessRuleEngine);
ContextUtils.setPsnRuleEngine(req, psnRuleEngine);
ContextUtils.setConfigProvider(req, configProvider);
ContextUtils.setListProvider(req, listProvider);
UserContext.setUser(userEngine.getUser(req).getLoginId());
LogInfoImpl li = LogInfoImpl.getLogInfo(req, resp);
try {
super.service(req, resp);
} catch (Exception e) {
e.printStackTrace();
} finally {
li.complete();
for (RequestLogger rl : loggers.values())
rl.log(li);
}
}
public Map<String, Object> runHandler(HttpServletRequest req,
HttpServletResponse resp, String pageUrl, String url)
throws Exception {
Map<String, String> params = new HashMap<String, String>();
if (pageUrl != null)
params.put(ReqConst.PARAM_PAGE_URL, pageUrl);
WinletRequestWrapper wreq = new WinletRequestWrapper(req, null, params,
null);
wreq.setServletPath(url);
HandlerExecutionChain mappedHandler = getHandler(wreq);
ModelAndView mv = getHandlerAdapter(mappedHandler.getHandler()).handle(
wreq, resp, mappedHandler.getHandler());
return mv.getModel();
}
@Override
protected void render(ModelAndView mv, HttpServletRequest request,
HttpServletResponse response) throws Exception {
boolean addViewName = "true".equalsIgnoreCase(request
.getParameter(ReqConst.PARAM_WINLET_DEBUG));
if (!addViewName) {
super.render(mv, request, response);
return;
}
ReqInfo reqInfo = ContextUtils.getReqInfo();
if (reqInfo.getWinlet() == null) {
super.render(mv, request, response);
return;
}
BufferedResponse resp = new BufferedResponse();
super.render(mv, request, resp);
byte[] bytes = resp.getBuffered();
String str = bytes == null ? "" : new String(bytes, "UTF-8");
response.getWriter()
.write("<div class=\"winlet_debug_view\"><div class=\"winlet_debug_view_title\">");
Method method = reqInfo.getWinletMethod();
if (method != null) {
response.getWriter().write(
"<div>" + method.getDeclaringClass().getSimpleName() + ":"
+ method.getName() + "</div>");
}
response.getWriter().write(mv.getViewName() + "</div>");
response.getWriter().write(str);
response.getWriter().write("<div style=\"clear:both\"></div></div>");
response.getWriter().flush();
}
}