polishing

git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@652 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
Juergen Hoeller 2009-02-18 23:51:03 +00:00
parent ebc22a72c1
commit 18e805eac2
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;
@ -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,25 +23,12 @@ 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)

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.
@ -37,10 +37,8 @@ import java.lang.annotation.Target;
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);
} }
} }