polishing

This commit is contained in:
Juergen Hoeller 2009-02-18 23:51:03 +00:00
parent 85bc98ea4b
commit d3d0111439
9 changed files with 154 additions and 205 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -37,7 +37,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* FactoryBean that creates a named EHCache {@link net.sf.ehcache.Cache} instance * {@link FactoryBean} that creates a named EHCache {@link net.sf.ehcache.Cache} instance
* (or a decorator that implements the {@link net.sf.ehcache.Ehcache} interface), * (or a decorator that implements the {@link net.sf.ehcache.Ehcache} interface),
* representing a cache region within an EHCache {@link net.sf.ehcache.CacheManager}. * representing a cache region within an EHCache {@link net.sf.ehcache.CacheManager}.
* *
@ -56,7 +56,7 @@ import org.springframework.util.Assert;
* @see EhCacheManagerFactoryBean * @see EhCacheManagerFactoryBean
* @see net.sf.ehcache.Cache * @see net.sf.ehcache.Cache
*/ */
public class EhCacheFactoryBean implements FactoryBean, BeanNameAware, InitializingBean { public class EhCacheFactoryBean implements FactoryBean<Ehcache>, BeanNameAware, InitializingBean {
protected final Log logger = LogFactory.getLog(getClass()); protected final Log logger = LogFactory.getLog(getClass());
@ -298,11 +298,11 @@ public class EhCacheFactoryBean implements FactoryBean, BeanNameAware, Initializ
} }
public Object getObject() { public Ehcache getObject() {
return this.cache; return this.cache;
} }
public Class getObjectType() { public Class<? extends Ehcache> getObjectType() {
return (this.cache != null ? this.cache.getClass() : Ehcache.class); return (this.cache != null ? this.cache.getClass() : Ehcache.class);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2007 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,8 +29,8 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
/** /**
* FactoryBean that exposes an EHCache {@link net.sf.ehcache.CacheManager} instance * {@link FactoryBean} that exposes an EHCache {@link net.sf.ehcache.CacheManager}
* (independent or shared), configured from a specified config location. * instance (independent or shared), configured from a specified config location.
* *
* <p>If no config location is specified, a CacheManager will be configured from * <p>If no config location is specified, a CacheManager will be configured from
* "ehcache.xml" in the root of the class path (that is, default EHCache initialization * "ehcache.xml" in the root of the class path (that is, default EHCache initialization
@ -52,7 +52,7 @@ import org.springframework.core.io.Resource;
* @see EhCacheFactoryBean * @see EhCacheFactoryBean
* @see net.sf.ehcache.CacheManager * @see net.sf.ehcache.CacheManager
*/ */
public class EhCacheManagerFactoryBean implements FactoryBean, InitializingBean, DisposableBean { public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, InitializingBean, DisposableBean {
protected final Log logger = LogFactory.getLog(getClass()); protected final Log logger = LogFactory.getLog(getClass());
@ -122,11 +122,11 @@ public class EhCacheManagerFactoryBean implements FactoryBean, InitializingBean,
} }
public Object getObject() { public CacheManager getObject() {
return this.cacheManager; return this.cacheManager;
} }
public Class getObjectType() { public Class<? extends CacheManager> getObjectType() {
return (this.cacheManager != null ? this.cacheManager.getClass() : CacheManager.class); return (this.cacheManager != null ? this.cacheManager.getClass() : CacheManager.class);
} }

View File

@ -1078,8 +1078,8 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
* @param lifecycleBeans Map with bean name as key and Lifecycle instance as value * @param lifecycleBeans Map with bean name as key and Lifecycle instance as value
* @param beanName the name of the bean to start * @param beanName the name of the bean to start
*/ */
private void doStart(Map lifecycleBeans, String beanName) { private void doStart(Map<String, Lifecycle> lifecycleBeans, String beanName) {
Lifecycle bean = (Lifecycle) lifecycleBeans.get(beanName); Lifecycle bean = lifecycleBeans.get(beanName);
if (bean != null) { if (bean != null) {
String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName); String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName);
for (String dependency : dependenciesForBean) { for (String dependency : dependenciesForBean) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,7 +29,6 @@ import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -122,8 +121,8 @@ public abstract class StatementCreatorUtils {
* @throws SQLException if thrown by PreparedStatement methods * @throws SQLException if thrown by PreparedStatement methods
*/ */
public static void setParameterValue( public static void setParameterValue(
PreparedStatement ps, int paramIndex, SqlParameter param, Object inValue) PreparedStatement ps, int paramIndex, SqlParameter param, Object inValue)
throws SQLException { throws SQLException {
setParameterValueInternal(ps, paramIndex, param.getSqlType(), param.getTypeName(), param.getScale(), inValue); setParameterValueInternal(ps, paramIndex, param.getSqlType(), param.getTypeName(), param.getScale(), inValue);
} }
@ -139,8 +138,8 @@ public abstract class StatementCreatorUtils {
* @see SqlTypeValue * @see SqlTypeValue
*/ */
public static void setParameterValue( public static void setParameterValue(
PreparedStatement ps, int paramIndex, int sqlType, Object inValue) PreparedStatement ps, int paramIndex, int sqlType, Object inValue)
throws SQLException { throws SQLException {
setParameterValueInternal(ps, paramIndex, sqlType, null, null, inValue); setParameterValueInternal(ps, paramIndex, sqlType, null, null, inValue);
} }
@ -158,8 +157,8 @@ public abstract class StatementCreatorUtils {
* @see SqlTypeValue * @see SqlTypeValue
*/ */
public static void setParameterValue( public static void setParameterValue(
PreparedStatement ps, int paramIndex, int sqlType, String typeName, Object inValue) PreparedStatement ps, int paramIndex, int sqlType, String typeName, Object inValue)
throws SQLException { throws SQLException {
setParameterValueInternal(ps, paramIndex, sqlType, typeName, null, inValue); setParameterValueInternal(ps, paramIndex, sqlType, typeName, null, inValue);
} }
@ -179,8 +178,8 @@ public abstract class StatementCreatorUtils {
* @see SqlTypeValue * @see SqlTypeValue
*/ */
private static void setParameterValueInternal( private static void setParameterValueInternal(
PreparedStatement ps, int paramIndex, int sqlType, String typeName, Integer scale, Object inValue) PreparedStatement ps, int paramIndex, int sqlType, String typeName, Integer scale, Object inValue)
throws SQLException { throws SQLException {
String typeNameToUse = typeName; String typeNameToUse = typeName;
int sqlTypeToUse = sqlType; int sqlTypeToUse = sqlType;
@ -218,7 +217,13 @@ public abstract class StatementCreatorUtils {
} }
} }
private static void setNull(PreparedStatement ps, int paramIndex, int sqlType, String typeName) throws SQLException { /**
* Set the specified PreparedStatement parameter to null,
* respecting database-specific peculiarities.
*/
private static void setNull(PreparedStatement ps, int paramIndex, int sqlType, String typeName)
throws SQLException {
if (sqlType == SqlTypeValue.TYPE_UNKNOWN) { if (sqlType == SqlTypeValue.TYPE_UNKNOWN) {
boolean useSetObject = false; boolean useSetObject = false;
sqlType = Types.NULL; sqlType = Types.NULL;
@ -356,7 +361,7 @@ public abstract class StatementCreatorUtils {
* Check whether the given value can be treated as a String value. * Check whether the given value can be treated as a String value.
*/ */
private static boolean isStringValue(Class inValueType) { private static boolean isStringValue(Class inValueType) {
// Consider any CharSequence (including JDK 1.5's StringBuilder) as String. // Consider any CharSequence (including StringBuffer and StringBuilder) as a String.
return (CharSequence.class.isAssignableFrom(inValueType) || return (CharSequence.class.isAssignableFrom(inValueType) ||
StringWriter.class.isAssignableFrom(inValueType)); StringWriter.class.isAssignableFrom(inValueType));
} }

View File

@ -67,7 +67,10 @@ import org.springframework.util.Assert;
* @author Sam Brannen * @author Sam Brannen
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 2.0 * @since 2.0
* @deprecated as of Spring 3.0, in favor of using the listener-based test context framework
* ({@link org.springframework.test.context.junit38.AbstractJUnit38SpringContextTests})
*/ */
@Deprecated
public abstract class AbstractAnnotationAwareTransactionalTests extends public abstract class AbstractAnnotationAwareTransactionalTests extends
AbstractTransactionalDataSourceSpringContextTests { AbstractTransactionalDataSourceSpringContextTests {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2007 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -23,27 +23,14 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
* <p>
* Test annotation to indicate that a test method <em>dirties</em> the context * Test annotation to indicate that a test method <em>dirties</em> the context
* for the current test. * for the current test.
* </p>
* <p>
* Using this annotation in conjunction with
* {@link AbstractAnnotationAwareTransactionalTests} is less error-prone than
* calling
* {@link org.springframework.test.AbstractSingleSpringContextTests#setDirty() setDirty()}
* explicitly because the call to <code>setDirty()</code> is guaranteed to
* occur, even if the test failed. If only a particular code path in the test
* dirties the context, prefer calling <code>setDirty()</code> explicitly --
* and take care!
* </p>
* *
* @author Rod Johnson * @author Rod Johnson
* @author Sam Brannen * @author Sam Brannen
* @since 2.0 * @since 2.0
* @see org.springframework.test.AbstractSingleSpringContextTests
*/ */
@Target( { ElementType.METHOD }) @Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface DirtiesContext { public @interface DirtiesContext {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2007 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -31,16 +31,14 @@ import java.lang.annotation.Target;
* @author Sam Brannen * @author Sam Brannen
* @since 2.5 * @since 2.5
*/ */
@Target( { ElementType.METHOD }) @Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface Rollback { public @interface Rollback {
/** /**
* <p>
* Whether or not the transaction for the annotated method should be rolled * Whether or not the transaction for the annotated method should be rolled
* back after the method has completed. * back after the method has completed.
* </p>
*/ */
boolean value() default true; boolean value() default true;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,7 +17,7 @@
package org.springframework.web.servlet.tags; package org.springframework.web.servlet.tags;
/** /**
* Allows implementing tag to utilize nested spring:param tags. * Allows implementing tag to utilize nested <code>spring:param</code> tags.
* *
* @author Scott Andrews * @author Scott Andrews
* @since 3.0 * @since 3.0
@ -26,11 +26,10 @@ package org.springframework.web.servlet.tags;
public interface ParamAware { public interface ParamAware {
/** /**
* Callback hook for nested spring:param tags to pass their value to the * Callback hook for nested spring:param tags to pass their value
* parent tag. * to the parent tag.
* * @param param the result of the nested <code>spring:param</code> tag
* @param param the result of the nested spring:param tag
*/ */
public void addParam(Param param); void addParam(Param param);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2008 the original author or authors. * Copyright 2002-2009 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -23,7 +23,6 @@ import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspException;
@ -76,12 +75,9 @@ public class UrlTag extends TagSupport implements ParamAware {
private static final String URL_TYPE_ABSOLUTE = "://"; private static final String URL_TYPE_ABSOLUTE = "://";
private enum UrlType {
CONTEXT_RELATIVE, RELATIVE, ABSOLUTE
};
private static final char[] XML_CHARS = { '&', '<', '>', '"', '\'' }; private static final char[] XML_CHARS = { '&', '<', '>', '"', '\'' };
private List<Param> params; private List<Param> params;
private Set<String> templateParams; private Set<String> templateParams;
@ -98,21 +94,79 @@ public class UrlTag extends TagSupport implements ParamAware {
private boolean escapeXml = false; private boolean escapeXml = false;
// tag lifecycle
/**
* 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);
}
/**
* Instructs the tag to XML entity encode the resulting URL.
* <p>Defaults to false to maintain compatibility with the JSTL c:url tag.
* <p><b>NOTE:</b> Strongly recommended to set as 'true' when rendering
* directly to the JspWriter in an XML or HTML based file.
*/
public void setEscapeXml(String escapeXml) {
this.escapeXml = Boolean.valueOf(escapeXml);
}
public void addParam(Param param) {
this.params.add(param);
}
@Override @Override
public int doStartTag() throws JspException { public int doStartTag() throws JspException {
params = new LinkedList<Param>(); this.params = new LinkedList<Param>();
templateParams = new HashSet<String>(); this.templateParams = new HashSet<String>();
return EVAL_BODY_INCLUDE; return EVAL_BODY_INCLUDE;
} }
@Override @Override
public int doEndTag() throws JspException { public int doEndTag() throws JspException {
String url = createUrl(); String url = createUrl();
if (this.var == null) {
if (var == null) {
// print the url to the writer // print the url to the writer
try { try {
pageContext.getOut().print(url); pageContext.getOut().print(url);
@ -125,74 +179,50 @@ public class UrlTag extends TagSupport implements ParamAware {
// store the url as a variable // store the url as a variable
pageContext.setAttribute(var, url, scope); pageContext.setAttribute(var, url, scope);
} }
return EVAL_PAGE; return EVAL_PAGE;
} }
// from ParamAware
public void addParam(Param param) {
params.add(param);
}
// support methods
/** /**
* Build the URL for the tag from the tag attributes and parameters. * Build the URL for the tag from the tag attributes and parameters.
*
* @return the URL value as a String * @return the URL value as a String
* @throws JspException * @throws JspException
*/ */
private String createUrl() throws JspException { private String createUrl() throws JspException {
HttpServletRequest request = (HttpServletRequest) pageContext HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
.getRequest(); HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
HttpServletResponse response = (HttpServletResponse) pageContext
.getResponse();
StringBuilder url = new StringBuilder(); StringBuilder url = new StringBuilder();
if (this.type == UrlType.CONTEXT_RELATIVE) {
if (type == UrlType.CONTEXT_RELATIVE) {
// add application context to url // add application context to url
if (context == null) { if (this.context == null) {
url.append(request.getContextPath()); url.append(request.getContextPath());
} }
else { else {
url.append(context); url.append(this.context);
} }
} }
if (this.type != UrlType.RELATIVE && this.type != UrlType.ABSOLUTE && !this.value.startsWith("/")) {
if (type != UrlType.RELATIVE && type != UrlType.ABSOLUTE
&& !value.startsWith("/")) {
url.append("/"); url.append("/");
} }
url.append(replaceUriTemplateParams(this.value, this.params, this.templateParams));
url.append(createQueryString(this.params, this.templateParams, (url.indexOf("?") == -1)));
url.append(replaceUriTemplateParams(value, params, templateParams)); String urlStr = url.toString();
url.append(createQueryString(params, templateParams, if (this.type != UrlType.ABSOLUTE) {
(url.indexOf("?") == -1))); // Add the session identifier if needed
// (Do not embed the session identifier in a remote link!)
String urlStr; urlStr = response.encodeURL(urlStr);
if (type != UrlType.ABSOLUTE) {
// add the session identifier if needed
urlStr = response.encodeURL(url.toString());
} }
else { if (this.escapeXml) {
// do not embed the session identifier in a remote link
urlStr = url.toString();
}
if (escapeXml) {
urlStr = escapeXml(urlStr); urlStr = escapeXml(urlStr);
} }
return urlStr; return urlStr;
} }
/** /**
* Builds the query string from available parameters that have not already * Build the query string from available parameters that have not already
* been applied as template params. * been applied as template params.
* * <p>The names and values of parameters are URL encoded.
* <p>
* The names and values of parameters are URL encoded.
*
* @param params the parameters to build the query string from * @param params the parameters to build the query string from
* @param usedParams set of parameter names that have been applied as * @param usedParams set of parameter names that have been applied as
* template params * template params
@ -201,13 +231,13 @@ public class UrlTag extends TagSupport implements ParamAware {
* @return the query string * @return the query string
* @throws JspException * @throws JspException
*/ */
protected String createQueryString(List<Param> params, protected String createQueryString(
Set<String> usedParams, boolean includeQueryStringDelimiter) List<Param> params, Set<String> usedParams, boolean includeQueryStringDelimiter)
throws JspException { throws JspException {
StringBuilder qs = new StringBuilder(); StringBuilder qs = new StringBuilder();
for (Param param : params) { for (Param param : params) {
if (!usedParams.contains(param.getName()) if (!usedParams.contains(param.getName()) && param.getName() != null && !"".equals(param.getName())) {
&& param.getName() != null && !"".equals(param.getName())) {
if (includeQueryStringDelimiter && qs.length() == 0) { if (includeQueryStringDelimiter && qs.length() == 0) {
qs.append("?"); qs.append("?");
} }
@ -221,28 +251,24 @@ public class UrlTag extends TagSupport implements ParamAware {
} }
} }
} }
return qs.toString(); return qs.toString();
} }
/** /**
* Replaces template markers in the URL matching available parameters. The * Replace template markers in the URL matching available parameters. The
* name of matched parameters are added to the used parameters set. * name of matched parameters are added to the used parameters set.
* * <p>Parameter values are URL encoded.
* <p>
* Parameter values are URL encoded.
*
* @param uri the URL with template parameters to replace * @param uri the URL with template parameters to replace
* @param params parameters used to replace template markers * @param params parameters used to replace template markers
* @param usedParams set of template parameter names that have been replaced * @param usedParams set of template parameter names that have been replaced
* @return the URL with template parameters replaced * @return the URL with template parameters replaced
* @throws JspException * @throws JspException
*/ */
protected String replaceUriTemplateParams(String uri, List<Param> params, protected String replaceUriTemplateParams(String uri, List<Param> params, Set<String> usedParams)
Set<String> usedParams) throws JspException { throws JspException {
for (Param param : params) { for (Param param : params) {
String template = URL_TEMPLATE_DELIMITER_PREFIX + param.getName() String template = URL_TEMPLATE_DELIMITER_PREFIX + param.getName() + URL_TEMPLATE_DELIMITER_SUFFIX;
+ URL_TEMPLATE_DELIMITER_SUFFIX;
if (uri.contains(template)) { if (uri.contains(template)) {
usedParams.add(param.getName()); usedParams.add(param.getName());
uri = uri.replace(template, urlEncode(param.getValue())); uri = uri.replace(template, urlEncode(param.getValue()));
@ -252,9 +278,7 @@ public class UrlTag extends TagSupport implements ParamAware {
} }
/** /**
* URL encode the provided string using the character encoding for the * URL-encode the providedSstring using the character encoding for the response.
* response.
*
* @param value the value to encode * @param value the value to encode
* @return the URL encoded value * @return the URL encoded value
* @throws JspException if the character encoding is invalid * @throws JspException if the character encoding is invalid
@ -263,20 +287,17 @@ public class UrlTag extends TagSupport implements ParamAware {
if (value == null) { if (value == null) {
return null; return null;
} }
try { try {
return URLEncoder.encode(value, pageContext.getResponse() return URLEncoder.encode(value, pageContext.getResponse().getCharacterEncoding());
.getCharacterEncoding());
} }
catch (UnsupportedEncodingException e) { catch (UnsupportedEncodingException ex) {
throw new JspException(e); throw new JspException(ex);
} }
} }
/** /**
* XML entity encode the provided string. &#38;, &#60;, &#62;, &#39; and * XML entity encode the provided string. &#38;, &#60;, &#62;, &#39; and
* &#34; are encoded to their entity values. * &#34; are encoded to their entity values.
*
* @param xml the value to escape * @param xml the value to escape
* @return the escaped value * @return the escaped value
*/ */
@ -284,95 +305,31 @@ public class UrlTag extends TagSupport implements ParamAware {
if (xml == null) { if (xml == null) {
return null; return null;
} }
String escapedXml = xml; String escapedXml = xml;
for (char xmlChar : XML_CHARS) { for (char xmlChar : XML_CHARS) {
escapedXml = StringUtils.replace(escapedXml, String escapedXml = StringUtils.replace(escapedXml, String.valueOf(xmlChar), entityValue(xmlChar));
.valueOf(xmlChar), entityValue(xmlChar));
} }
return escapedXml; return escapedXml;
} }
/** /**
* Convert a character value to a XML entity value. The decimal value of the * Convert a character value to a XML entity value.
* character is used. * The decimal value of the character is used.
* * <p>For example, 'A' is converted to "&amp;#65;".
* <p>
* For example, 'A' is converted to "&amp;#65;".
*
* @param xmlChar the character to encode * @param xmlChar the character to encode
* @return the entity value * @return the entity value
*/ */
protected String entityValue(char xmlChar) { protected String entityValue(char xmlChar) {
return new StringBuilder().append("&#").append( return new StringBuilder().append("&#").append(Integer.toString(xmlChar)).append(";").toString();
Integer.toString(xmlChar)).append(";").toString();
} }
// tag attribute accessors
/** /**
* Sets the value of the URL * Internal enum that classifies URLs by type.
*/ */
public void setValue(String value) { private enum UrlType {
if (value.contains(URL_TYPE_ABSOLUTE)) {
type = UrlType.ABSOLUTE;
this.value = value;
}
else if (value.startsWith("/")) {
type = UrlType.CONTEXT_RELATIVE;
this.value = value;
}
else {
type = UrlType.RELATIVE;
this.value = value;
}
}
/** CONTEXT_RELATIVE, RELATIVE, ABSOLUTE
* Sets 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;
}
}
/**
* Sets 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;
}
/**
* Sets the scope to export the URL variable to. This attribute has no
* meaning unless var is also defined.
*
* @param scope the string name of the scope
* @see TagUtils#getScope(String)
*/
public void setScope(String scope) {
this.scope = TagUtils.getScope(scope);
}
/**
* Instructs the tag to XML entity encode the resulting URL.
* <p>
* Defaults to false to maintain compatibility with the JSTL c:url tag.
* <p>
* <b>NOTE:</b> Strongly recommended to set as 'true' when rendering
* directly to the JspWriter in an XML or HTML based file.
*
* @param escapeXml string representation of a boolean
* @see Boolean#valueOf(String)
*/
public void setEscapeXml(String escapeXml) {
this.escapeXml = Boolean.valueOf(escapeXml);
} }
} }