/*
* $Id: PlainTextResult.java 471756 2006-11-06 15:01:43Z husted $
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package cn.org.rapid_framework.struts2.dispatcher;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.PageContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.StrutsResultSupport;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.util.TextParseUtil;
/**
* <pre>
* 直接使用Action执行方法的返回字符串作为Http请求的forward/redirect的转向,
* 以感叹号开头(!)的为redirect转向,反之为forward转向.
* </pre>
*
*/
public class DirectResult extends StrutsResultSupport {
private static final Log _log = LogFactory.getLog(DirectResult.class);
private static final long serialVersionUID = 3633371605905583950L;
private boolean prependServletContext = true;
private static final String FORWARD_PREFIX = "forward:";
private static final String REDIRECT_PREFIX = "redirect:";
public DirectResult() {
super();
}
public DirectResult(String location) {
super(location);
}
/**
* Sets whether or not to prepend the servlet context path to the redirected URL.
*
* @param prependServletContext <tt>true</tt> to prepend the location with the servlet context path,
* <tt>false</tt> otherwise.
*/
public void setPrependServletContext(boolean prependServletContext) {
this.prependServletContext = prependServletContext;
}
/* (non-Javadoc)
* @see org.apache.struts2.dispatcher.StrutsResultSupport#doExecute(java.lang.String, com.opensymphony.xwork2.ActionInvocation)
*/
@Override
protected void doExecute(String finalLocation,ActionInvocation invocation) throws Exception {
HttpServletResponse response = (HttpServletResponse) invocation.getInvocationContext().get(HTTP_RESPONSE);
HttpServletRequest request = (HttpServletRequest) invocation.getInvocationContext().get(HTTP_REQUEST);
String resultCodeAsLocation = invocation.getResultCode();
if(resultCodeAsLocation == null) {
return;
}
//proecss with ONGL expression
resultCodeAsLocation = TextParseUtil.translateVariables(resultCodeAsLocation,invocation.getStack());
if(resultCodeAsLocation.startsWith("!")) {
doRedirect(invocation,request, response, resultCodeAsLocation.substring(1));
return;
}
if(resultCodeAsLocation.startsWith(REDIRECT_PREFIX)) {
doRedirect(invocation,request, response, resultCodeAsLocation.substring(REDIRECT_PREFIX.length()));
return;
}
if(resultCodeAsLocation.startsWith(FORWARD_PREFIX)) {
doDispatcher(response, request, resultCodeAsLocation.substring(FORWARD_PREFIX.length()));
return;
}
doDispatcher(response, request, resultCodeAsLocation);
}
private void doDispatcher(HttpServletResponse response, HttpServletRequest request, String resultCodeAsLocation) throws IOException, ServletException {
if (_log.isInfoEnabled()) {
_log.info("Forwarding to location:" + resultCodeAsLocation);
}
PageContext pageContext = ServletActionContext.getPageContext();
if (pageContext != null) {
pageContext.include(resultCodeAsLocation);
return;
}
RequestDispatcher dispatcher = request.getRequestDispatcher(resultCodeAsLocation);
if (dispatcher == null) {
response.sendError(404, "result '" + resultCodeAsLocation + "' not found");
return;
}
if (!response.isCommitted() && (request.getAttribute("javax.servlet.include.servlet_path") == null)) {
request.setAttribute("struts.view_uri", resultCodeAsLocation);
request.setAttribute("struts.request_uri", request.getRequestURI());
dispatcher.forward(request, response);
} else {
dispatcher.include(request, response);
}
}
private void doRedirect(ActionInvocation invocation,HttpServletRequest request, HttpServletResponse response, String redirectLocation) throws IOException {
if(isPathUrl(redirectLocation)) {
if(!redirectLocation.startsWith("/")) {
String namespace = invocation.getProxy().getNamespace();
if ((namespace != null) && (namespace.length() > 0) && (!"/".equals(namespace))) {
redirectLocation = namespace + "/" + redirectLocation;
} else {
redirectLocation = "/" + redirectLocation;
}
}
if (prependServletContext && (request.getContextPath() != null) && (request.getContextPath().length() > 0)) {
redirectLocation = request.getContextPath() + redirectLocation;
}
}
if(_log.isInfoEnabled())
_log.info("Redirect to location:"+redirectLocation);
response.sendRedirect(response.encodeRedirectURL(redirectLocation));
}
private static boolean isPathUrl(String url) {
// filter out "http:", "https:", "mailto:", "file:", "ftp:"
// since the only valid places for : in URL's is before the path specification
// either before the port, or after the protocol
return (url.indexOf(':') == -1);
}
}