/**
* Copyright 2005-2010 hdiv.org
*
* Licensed 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 org.hdiv.web.servlet.view;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.hdiv.config.HDIVConfig;
import org.hdiv.util.HDIVRequestUtils;
import org.hdiv.util.HDIVUtil;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.view.RedirectView;
/**
* <p>View that redirects to an absolute, context relative, or current request
* relative URL. By default all primitive model attributes (or collections
* thereof) are exposed as HTTP query parameters, but this behavior can be changed
* by overriding the {@link #isEligibleProperty(String, Object)} method.
*
* <p>A URL for this view is supposed to be a HTTP redirect URL, i.e.
* suitable for HttpServletResponse's <code>sendRedirect</code> method, which
* is what actually does the redirect if the HTTP 1.0 flag is on, or via sending
* back an HTTP 303 code - if the HTTP 1.0 compatibility flag is off.
*
* <p>Note that while the default value for the "contextRelative" flag is off,
* you will probably want to almost always set it to true. With the flag off,
* URLs starting with "/" are considered relative to the web server root, while
* with the flag on, they are considered relative to the web application root.
* Since most web applications will never know or care what their context path
* actually is, they are much better off setting this flag to true, and submitting
* paths which are to be considered relative to the web application root.
*
* <p><b>NOTE when using this redirect view in a Portlet environment:</b> Make sure
* that your controller respects the Portlet <code>sendRedirect</code> constraints.
* When e.g. using {@link org.springframework.web.portlet.mvc.SimpleFormController},
* make sure to set your controller's
* {@link org.springframework.web.portlet.mvc.AbstractFormController#setRedirectAction "redirectAction"}
* property to "true", in order to make the controller base class behave accordingly.
*
* @author Gorka Vicente
* @since HDIV 2.0.6
* @see #setHttp10Compatible
* @see javax.servlet.http.HttpServletResponse#sendRedirect
*/
public class RedirectViewHDIV extends RedirectView {
private HttpStatus statusCode;
/**
* Constructor for use as a bean.
*/
public RedirectViewHDIV() {
super();
}
/**
* Create a new RedirectView with the given URL.
* <p>
* The given URL will be considered as relative to the web server, not as
* relative to the current ServletContext.
*
* @param url the URL to redirect to
* @see #RedirectView(String, boolean)
*/
public RedirectViewHDIV(String url) {
super(url);
}
/**
* Create a new RedirectView with the given URL.
*
* @param url the URL to redirect to
* @param contextRelative whether to interpret the given URL as relative to
* the current ServletContext
*/
public RedirectViewHDIV(String url, boolean contextRelative) {
super(url, contextRelative);
}
/**
* Create a new RedirectView with the given URL.
*
* @param url the URL to redirect to
* @param contextRelative whether to interpret the given URL as relative to
* the current ServletContext
* @param http10Compatible whether to stay compatible with HTTP 1.0 clients
*/
public RedirectViewHDIV(String url, boolean contextRelative, boolean http10Compatible) {
super(url, contextRelative, http10Compatible);
}
/**
* Send a redirect back to the HTTP client and adds HDIV state as a
* parameter if <code>targetUrl</code> references our application.
*
* @param request current HTTP request (allows for reacting to request
* method)
* @param response current HTTP response (for sending response headers)
* @param targetUrl the target URL to redirect to
* @param http10Compatible whether to stay compatible with HTTP 1.0 clients
* @throws IOException if thrown by response methods
*/
@Override
protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String targetUrl,
boolean http10Compatible) throws IOException {
if (request.getSession(false) != null) {
ServletContext servletContext = request.getSession().getServletContext();
HDIVConfig hdivConfig = HDIVUtil.getHDIVConfig(servletContext);
if (HDIVRequestUtils.hasActionOrServletExtension(targetUrl, hdivConfig.getProtectedURLPatterns())) {
targetUrl = HDIVRequestUtils.addHDIVParameterIfNecessary(request, targetUrl, hdivConfig.isValidationInUrlsWithoutParamsActivated());
}
}
if (http10Compatible) {
// Always send status code 302.
response.sendRedirect(response.encodeRedirectURL(targetUrl));
} else {
HttpStatus statusCode = getHttp11StatusCode(request, response, targetUrl);
response.setStatus(statusCode.value());
response.setHeader("Location", response.encodeRedirectURL(targetUrl));
}
}
/**
* Determines the status code to use for HTTP 1.1 compatible requests.
* <p>The default implemenetation returns the {@link #setStatusCode(HttpStatus) statusCode}
* property if set, or the value of the {@link #RESPONSE_STATUS_ATTRIBUTE} attribute. If neither are
* set, it defaults to {@link HttpStatus#SEE_OTHER} (303).
* @param request the request to inspect
* @return the response
*/
/* the "this.statusCode != null" is now in spring, so this is identical and not needed
@Override
protected HttpStatus getHttp11StatusCode(HttpServletRequest request, HttpServletResponse response, String targetUrl) {
//TODO: testear habi�ndole asignado valor a statusCode mediante el applicationContext.xml
if (this.statusCode != null) {
return statusCode;
}
HttpStatus attributeStatusCode = (HttpStatus) request.getAttribute(View.RESPONSE_STATUS_ATTRIBUTE);
if (attributeStatusCode != null) {
return attributeStatusCode;
}
return HttpStatus.SEE_OTHER;
}
*/
/**
* Set the status code for this view.
* <p>Default is to send 302/303, depending on the value of the
* {@link #setHttp10Compatible(boolean) http10Compatible} flag.
*/
public void setStatusCode(HttpStatus statusCode) {
this.statusCode = statusCode;
}
}