//$Id:ResultBuilderImpl.java 2009-1-21 上午12:43:34 chaostone Exp $ /* * Copyright c 2005-2009. * * Licensed under the GPL License, Version 2.0 (the "License") * http://www.gnu.org/licenses/gpl-2.0.html * */ package org.beanfuse.struts2.plugin.result; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.struts2.ServletActionContext; import org.beanfuse.struts2.route.Action; import org.beanfuse.struts2.route.ActionNameBuilder; import org.beanfuse.struts2.route.ProfileService; import org.beanfuse.struts2.route.ViewMapper; 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的特征进行结果构建<br> * 1)chain:/xxx?param1=value1¶m2=value2<br> * 2)redirect:/yyy??param1=value1¶m2=value2<br> * 3)path/to/page/page.ftl<br> * * @author chaostone * */ public class DefaultResultBuilder implements ResultBuilder { private Logger log = LoggerFactory.getLogger(DefaultResultBuilder.class); protected Map resultTypeConfigs; @Inject protected ObjectFactory objectFactory; @Inject protected Configuration configuration; @Inject protected ViewMapper viewMapper; @Inject protected ProfileService profileService; @Inject protected ActionNameBuilder actionNameBuilder; public Result build(String resultCode, ActionConfig actionConfig, ActionContext context) { String path = null; ResultTypeConfig resultTypeConfig = null; Map params = new HashMap(); log.debug("result code:{} for actionConfig:{}", resultCode, actionConfig); if (null == resultTypeConfigs) { PackageConfig pc = configuration.getPackageConfig(actionConfig.getPackageName()); this.resultTypeConfigs = pc.getAllResultTypeConfigs(); } // prefix // TODO jsp,vm,ftl if (!StringUtils.contains(resultCode, ':')) { String className = context.getActionInvocation().getProxy().getAction().getClass() .getName(); String methodName = context.getActionInvocation().getProxy().getMethod(); if (StringUtils.isEmpty(resultCode)) { resultCode = "index"; } StringBuilder buf = new StringBuilder(); buf.append(viewMapper.getViewPath(className, methodName, resultCode)); buf.append('.'); buf.append(profileService.getProfile(className).getViewExtension()); path = buf.toString(); resultTypeConfig = (ResultTypeConfig) resultTypeConfigs.get("freemarker"); } else { String prefix = StringUtils.substringBefore(resultCode, ":"); resultTypeConfig = (ResultTypeConfig) resultTypeConfigs.get(prefix); String redirectParamStr = null; if (prefix.startsWith("redirect")) { redirectParamStr = ServletActionContext.getRequest().getParameter("params"); } Action action = (Action) ActionContext.getContext().getContextMap().get( "dispatch_action"); if (null != action) { if (null != action.getClazz()) { action.setName(actionNameBuilder.build(action.getClazz().getName())); } if (StringUtils.isBlank(action.getName())) { String t_path = ServletActionContext.getRequest().getServletPath(); if (StringUtils.isBlank(t_path)) { // 在websphere中,t_path会是空串,这是一个workaround t_path = ServletActionContext.getRequest().getRequestURI(); t_path = t_path.substring(t_path.indexOf('/', 1)); action.setName(t_path); } else action.setName(t_path); } path = buildAction(action, params, redirectParamStr); } else { path = buildAction(StringUtils.substringAfter(resultCode, ":"), params, redirectParamStr); } } return buildResult(path, resultCode, resultTypeConfig, context, params); } /** * 依据beanfuse-action构建 * * @param action * @param params * @param redirectParams * @return */ private String buildAction(Action action, Map params, String redirectParams) { if (StringUtils.isNotEmpty(redirectParams)) { action.addParams(redirectParams); } params.put("method", action.getMethod()); if (null != action.getParams() && !action.getParams().isEmpty()) { params.put("requestParameters", action.getParams()); } return addNamespaceAction(action.getName(), params); } private String addNamespaceAction(String path, Map<String, Object> param) { param.put("namespace", "/"); int startIndex = 0; if (path.charAt(0) == '/') { startIndex = 1; } String actionName = null; int endIndex = path.indexOf('!'); if (-1 == endIndex) { endIndex = path.indexOf('.'); } if (-1 == endIndex) { endIndex = path.length(); } actionName = path.substring(startIndex, endIndex); param.put("actionName", actionName); return actionName; } /** * 依据跳转路径进行构建 * * @param path * @param param * @param redirectParamStr * @return */ private String buildAction(String path, Map<String, Object> param, String redirectParamStr) { String newPath = path; if (path.startsWith("?")) { newPath = ServletActionContext.getRequest().getServletPath() + path; } // 添加额外的重定向参数 if (null != redirectParamStr) { if (newPath.indexOf('?') == -1) { newPath += ('?' + redirectParamStr.substring(1)); } else { newPath += redirectParamStr; } } String paramString = StringUtils.substringAfter(newPath, "?"); if (null != paramString) { Map requestParams = new HashMap(); paramString = StringUtils.replace(paramString, "?", ""); String[] paramPairs = StringUtils.split(paramString, "&"); for (int i = 0; i < paramPairs.length; i++) { String name = StringUtils.substringBefore(paramPairs[i], "="); String value = StringUtils.substringAfter(paramPairs[i], "="); if (name == "method") { param.put("method", value); } requestParams.put(name, value); } if (!requestParams.isEmpty()) { param.put("requestParameters", requestParams); } } return addNamespaceAction(newPath, param); } /** * 构建结果 * * @param defaultResultParam * @param resultCode * @param resultTypeConfig * @param context * @param extraParams * @return */ protected Result buildResult(String defaultResultParam, String resultCode, ResultTypeConfig resultTypeConfig, ActionContext context, Map extraParams) { Map params = new LinkedHashMap(); if (resultTypeConfig.getParams() != null) { params.putAll(resultTypeConfig.getParams()); } params.put(resultTypeConfig.getDefaultResultParam(), defaultResultParam); params.putAll(extraParams); ResultConfig resultConfig = new ResultConfig.Builder(resultCode, resultTypeConfig .getClassName()).addParams(params).build(); if (log.isDebugEnabled()) { log.debug("result code:{} for resultConfig:{}", resultCode, resultConfig); log.debug("location:{}", resultConfig.getLocation()); log.debug("name:{}", resultConfig.getName()); log.debug("className:{}", resultConfig.getClassName()); for (Iterator iterator = params.keySet().iterator(); iterator.hasNext();) { String key = (String) iterator.next(); log.debug("key:{} ==>{}", key, params.get(key)); } } try { return objectFactory.buildResult(resultConfig, context.getContextMap()); } catch (Exception e) { throw new XWorkException("Unable to build convention result", e, resultConfig); } } public ObjectFactory getObjectFactory() { return objectFactory; } public void setObjectFactory(ObjectFactory objectFactory) { this.objectFactory = objectFactory; } public Configuration getConfiguration() { return configuration; } public void setConfiguration(Configuration configuration) { this.configuration = configuration; } public void setViewMapper(ViewMapper viewMapper) { this.viewMapper = viewMapper; } public void setProfileService(ProfileService profileService) { this.profileService = profileService; } public void setActionNameBuilder(ActionNameBuilder actionNameBuilder) { this.actionNameBuilder = actionNameBuilder; } }