/**
* 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.tags;
import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hdiv.config.HDIVConfig;
import org.hdiv.util.HDIVRequestUtils;
import org.hdiv.util.HDIVUtil;
import org.springframework.web.servlet.tags.Param;
import org.springframework.web.servlet.tags.UrlTag;
import org.springframework.web.util.ExpressionEvaluationUtils;
import org.springframework.web.util.HtmlUtils;
import org.springframework.web.util.JavaScriptUtils;
import org.springframework.web.util.TagUtils;
public class UrlTagHDIV extends UrlTag {
/**
* Commons Logging instance.
*/
private static Log log = LogFactory.getLog(UrlTagHDIV.class);
private static final String URL_TEMPLATE_DELIMITER_PREFIX = "{";
private static final String URL_TEMPLATE_DELIMITER_SUFFIX = "}";
private static final String URL_TYPE_ABSOLUTE = "://";
private List<Param> params;
private Set<String> templateParams;
private UrlType type;
private String value;
private String context;
private String var;
private int scope = PageContext.PAGE_SCOPE;
private boolean javaScriptEscape = false;
/**
* Sets the value of the URL
*/
public void setValue(String value) {
if (value.contains(URL_TYPE_ABSOLUTE)) {
this.type = UrlType.ABSOLUTE;
this.value = value;
}
else if (value.startsWith("/")) {
this.type = UrlType.CONTEXT_RELATIVE;
this.value = value;
}
else {
this.type = UrlType.RELATIVE;
this.value = value;
}
}
/**
* Set the context path for the URL. Defaults to the current context
*/
public void setContext(String context) {
if (context.startsWith("/")) {
this.context = context;
}
else {
this.context = "/" + context;
}
}
/**
* Set the variable name to expose the URL under. Defaults to rendering the
* URL to the current JspWriter
*/
public void setVar(String var) {
this.var = var;
}
/**
* Set the scope to export the URL variable to. This attribute has no
* meaning unless var is also defined.
*/
public void setScope(String scope) {
this.scope = TagUtils.getScope(scope);
}
/**
* Set JavaScript escaping for this tag, as boolean value.
* Default is "false".
*/
public void setJavaScriptEscape(String javaScriptEscape) throws JspException {
this.javaScriptEscape =
ExpressionEvaluationUtils.evaluateBoolean("javaScriptEscape", javaScriptEscape, pageContext);
}
public void addParam(Param param) {
this.params.add(param);
}
@Override
public int doStartTagInternal() throws JspException {
this.params = new LinkedList<Param>();
this.templateParams = new HashSet<String>();
return EVAL_BODY_INCLUDE;
}
@Override
public int doEndTag() throws JspException {
String url = createUrl();
if (this.var == null) {
// print the url to the writer
try {
pageContext.getOut().print(url);
}
catch (IOException e) {
throw new JspException(e);
}
}
else {
// store the url as a variable
pageContext.setAttribute(var, url, scope);
}
return EVAL_PAGE;
}
/**
* Build the URL for the tag from the tag attributes and parameters.
* @return the URL value as a String
* @throws JspException
*/
private String createUrl() throws JspException {
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
StringBuilder url = new StringBuilder();
if (this.type == UrlType.CONTEXT_RELATIVE) {
// add application context to url
if (this.context == null) {
url.append(request.getContextPath());
}
else {
url.append(this.context);
}
}
if (this.type != UrlType.RELATIVE && this.type != UrlType.ABSOLUTE && !this.value.startsWith("/")) {
url.append("/");
}
url.append(replaceUriTemplateParams(this.value, this.params, this.templateParams));
url.append(createQueryString(this.params, this.templateParams, (url.indexOf("?") == -1)));
String urlStr = url.toString();
urlStr = HDIVRequestUtils.composeLinkUrl(urlStr, request);
// HDIVConfig hdivConfig = (HDIVConfig) HDIVUtil.getHDIVConfig(pageContext.getServletContext());
//
// if (!HDIVRequestUtils.hasExtensionToExclude(urlStr, hdivConfig.getExcludedURLExtensions()))
// {
// if (HDIVRequestUtils.hasActionOrServletExtension(urlStr, hdivConfig.getProtectedURLPatterns())) {
// urlStr = HDIVRequestUtils.addHDIVParameterIfNecessary((HttpServletRequest) pageContext.getRequest(),
// urlStr, hdivConfig.isValidationInUrlsWithoutParamsActivated());
// }
// }
if (this.type != UrlType.ABSOLUTE) {
// Add the session identifier if needed
// (Do not embed the session identifier in a remote link!)
urlStr = response.encodeURL(urlStr);
}
// HTML and/or JavaScript escape, if demanded.
urlStr = isHtmlEscape() ? HtmlUtils.htmlEscape(urlStr) : urlStr;
urlStr = this.javaScriptEscape ? JavaScriptUtils.javaScriptEscape(urlStr) : urlStr;
return urlStr;
}
/**
* Build the query string from available parameters that have not already
* been applied as template params.
* <p>The names and values of parameters are URL encoded.
* @param params the parameters to build the query string from
* @param usedParams set of parameter names that have been applied as
* template params
* @param includeQueryStringDelimiter true if the query string should start
* with a '?' instead of '&'
* @return the query string
*/
protected String createQueryString(List<Param> params, Set<String> usedParams, boolean includeQueryStringDelimiter)
throws JspException {
return super.createQueryString(params, usedParams, includeQueryStringDelimiter);
}
/**
* Replace template markers in the URL matching available parameters. The
* name of matched parameters are added to the used parameters set.
* <p>Parameter values are URL encoded.
* @param uri the URL with template parameters to replace
* @param params parameters used to replace template markers
* @param usedParams set of template parameter names that have been replaced
* @return the URL with template parameters replaced
*/
protected String replaceUriTemplateParams(String uri, List<Param> params, Set<String> usedParams)
throws JspException {
return super.replaceUriTemplateParams(uri, params, usedParams);
}
/**
* Internal enum that classifies URLs by type.
*/
private enum UrlType {
CONTEXT_RELATIVE, RELATIVE, ABSOLUTE
}
}