/** * 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 } }