org.beangle.struts2.convention.result.DefaultResultBuilder Maven / Gradle / Ivy
/*
* Beangle, Agile Java/Scala Development Scaffold and Toolkit
*
* Copyright (c) 2005-2013, Beangle Software.
*
* Beangle is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Beangle is distributed in the hope that it will be useful.
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Beangle. If not, see .
*/
package org.beangle.struts2.convention.result;
import static org.beangle.commons.lang.Strings.contains;
import static org.beangle.commons.lang.Strings.isBlank;
import static org.beangle.commons.lang.Strings.isEmpty;
import static org.beangle.commons.lang.Strings.isNotEmpty;
import static org.beangle.commons.lang.Strings.substringAfter;
import static org.beangle.commons.lang.Strings.substringBefore;
import static org.beangle.commons.web.util.RequestUtils.getServletPath;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.ServletRedirectResult;
import org.apache.struts2.views.freemarker.FreemarkerManager;
import org.beangle.commons.collection.CollectUtils;
import org.beangle.struts2.convention.route.Action;
import org.beangle.struts2.convention.route.ActionBuilder;
import org.beangle.struts2.convention.route.ProfileService;
import org.beangle.struts2.convention.route.ViewMapper;
import org.beangle.struts2.freemarker.TemplateFinder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.XWorkException;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.config.entities.PackageConfig;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
import com.opensymphony.xwork2.inject.Inject;
/**
* 按照各种result的特征进行结果构建
* 1)chain:/xxx?param1=value1¶m2=value2
* 2)redirectAction:/yyy!method.action?param1=value1¶m2=value2
* 2)redirect:/yyy!methodd?param1=value1¶m2=value2
* 3)path/to/page/page.ftl
*
* @author chaostone
*/
public class DefaultResultBuilder implements ResultBuilder {
private static final Logger logger = LoggerFactory.getLogger(DefaultResultBuilder.class);
/** [ftl->freemarker,vm->velocity] */
private final Map resultTypeConfigs = CollectUtils.newHashMap();
private final ObjectFactory objectFactory;
private final ViewMapper viewMapper;
private final ProfileService profileService;
private final ActionBuilder actionBuilder;
private final TemplateFinder templateFinder;
@Inject
public DefaultResultBuilder(Configuration configuration, ObjectFactory objectFactory,
FreemarkerManager freemarkerManager, ProfileService profileService, ActionBuilder actionBuilder,
ViewMapper viewMapper) {
super();
this.objectFactory = objectFactory;
this.profileService = profileService;
this.actionBuilder = actionBuilder;
this.viewMapper = viewMapper;
this.templateFinder = new TemplateFinder(freemarkerManager.getConfig(), viewMapper);
Map typeExtensions = CollectUtils.toMap(new String[][] { { "freemarker", "ftl" },
{ "velocity", "vm" }, { "dispatcher", "jsp" } });
PackageConfig pc = configuration.getPackageConfig("struts-default");
for (String name : pc.getAllResultTypeConfigs().keySet()) {
String extension = typeExtensions.get(name);
ResultTypeConfig rtc = pc.getAllResultTypeConfigs().get(name);
if (null != extension) resultTypeConfigs.put(extension, rtc);
resultTypeConfigs.put(name, rtc);
}
}
public Result build(String resultCode, ActionConfig actionConfig, ActionContext context) {
String path = null;
ResultTypeConfig cfg = null;
logger.debug("result code:{} for actionConfig:{}", resultCode, actionConfig);
// first route by common result
if (!contains(resultCode, ':')) {
Class> actionClass = context.getActionInvocation().getProxy().getAction().getClass();
String className = actionClass.getName();
String methodName = context.getActionInvocation().getProxy().getMethod();
if (isEmpty(resultCode)) resultCode = "index";
String extention = profileService.getProfile(className).getViewExtension();
if (extention.equals("ftl")) {
path = templateFinder.find(actionClass, methodName, resultCode, extention);
if (null == path) {
StringBuilder buf = new StringBuilder();
buf.append(viewMapper.getViewPath(className, methodName, resultCode));
buf.append('.').append(extention);
path = buf.toString();
}
} else {
StringBuilder buf = new StringBuilder();
buf.append(viewMapper.getViewPath(className, methodName, resultCode));
buf.append('.').append(extention);
path = buf.toString();
}
cfg = resultTypeConfigs.get(extention);
return buildResult(resultCode, cfg, context, buildResultParams(path, cfg));
} else {
// by prefix
String prefix = substringBefore(resultCode, ":");
cfg = (ResultTypeConfig) resultTypeConfigs.get(prefix);
if (prefix.startsWith("chain")) {
Action action = buildAction(substringAfter(resultCode, ":"));
Map params = buildResultParams(path, cfg);
addNamespaceAction(action, params);
if (isNotEmpty(action.getMethod())) params.put("method", action.getMethod());
return buildResult(resultCode, cfg, context, params);
} else if (prefix.startsWith("redirect")) {
String targetResource = substringAfter(resultCode, ":");
if (contains(targetResource, ':')) { return new ServletRedirectResult(targetResource); }
Action action = buildAction(targetResource);
// add special param and ajax tag for redirect
HttpServletRequest request = ServletActionContext.getRequest();
String[] redirectParamStrs = request.getParameterValues("params");
if (null != redirectParamStrs) {
for (String redirectParamStr : redirectParamStrs)
action.params(redirectParamStr);
}
// x-requested-with->XMLHttpRequest
if (null != request.getHeader("x-requested-with")) action.param("x-requested-with", "1");
Map params = buildResultParams(path, cfg);
if (null != action.getParams().get("method")) {
params.put("method", (String) action.getParams().get("method"));
action.getParams().remove("method");
}
if (isNotEmpty(action.getMethod())) params.put("method", action.getMethod());
addNamespaceAction(action, params);
ServletRedirectResult result = (ServletRedirectResult) buildResult(resultCode, cfg, context, params);
for (Map.Entry param : action.getParams().entrySet()) {
String property = param.getKey();
result.addParameter(property, param.getValue());
}
return result;
} else {
// 从结果中抽取路径和返回值
path = substringAfter(resultCode, ":");
resultCode = "success";
return buildResult(resultCode, cfg, context, buildResultParams(path, cfg));
}
}
}
/**
* 依据跳转路径进行构建
*
* @param path
* @param param
* @param redirectParamStr
*/
private Action buildAction(String path) {
Action action = (Action) ActionContext.getContext().getContextMap().get("dispatch_action");
if (null == action) {
action = new Action();
String newPath = path;
if (path.startsWith("?")) {
newPath = getServletPath(ServletActionContext.getRequest()) + path;
}
action.path(newPath);
} else {
if (null != action.getClazz()) {
Action newAction = actionBuilder.build(action.getClazz());
action.name(newAction.getName()).namespace(newAction.getNamespace());
}
if (isBlank(action.getName())) {
action.path(getServletPath(ServletActionContext.getRequest()));
}
}
return action;
}
private void addNamespaceAction(Action action, Map params) {
params.put("namespace", action.getNamespace());
params.put("actionName", action.getName());
}
protected Map buildResultParams(String defaultParam, ResultTypeConfig resultTypeConfig) {
Map params = new LinkedHashMap();
if (resultTypeConfig.getParams() != null) {
params.putAll(resultTypeConfig.getParams());
}
params.put(resultTypeConfig.getDefaultResultParam(), defaultParam);
return params;
}
/**
* 构建结果
*
* @param resultCode
* @param resultTypeConfig
* @param context
* @param params
*/
protected Result buildResult(String resultCode, ResultTypeConfig resultTypeConfig, ActionContext context,
Map params) {
ResultConfig resultConfig = new ResultConfig.Builder(resultCode, resultTypeConfig.getClassName())
.addParams(params).build();
try {
return objectFactory.buildResult(resultConfig, context.getContextMap());
} catch (Exception e) {
throw new XWorkException("Unable to build convention result", e, resultConfig);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy