Browse Source

Backport further refinements from the nullability efforts

Issue: SPR-15656
pull/1550/head
Juergen Hoeller 9 years ago
parent
commit
cc70fdcbeb
  1. 10
      spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java
  2. 11
      spring-beans/src/main/java/org/springframework/beans/factory/CannotLoadBeanClassException.java
  3. 8
      spring-beans/src/main/java/org/springframework/beans/factory/config/DependencyDescriptor.java
  4. 28
      spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
  5. 4
      spring-beans/src/main/java/org/springframework/beans/factory/xml/AbstractBeanDefinitionParser.java
  6. 3
      spring-beans/src/main/java/org/springframework/beans/factory/xml/BeanDefinitionParserDelegate.java
  7. 22
      spring-context/src/main/java/org/springframework/context/annotation/ConditionContext.java
  8. 16
      spring-context/src/test/java/org/springframework/jmx/IJmxTestBean.java
  9. 4
      spring-core/src/main/java/org/springframework/util/ClassUtils.java
  10. 21
      spring-core/src/main/java/org/springframework/util/ConcurrentReferenceHashMap.java
  11. 37
      spring-core/src/main/java/org/springframework/util/StringUtils.java
  12. 13
      spring-jdbc/src/main/java/org/springframework/jdbc/core/BatchUpdateUtils.java
  13. 9
      spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java
  14. 4
      spring-jdbc/src/main/java/org/springframework/jdbc/core/StatementCreatorUtils.java
  15. 18
      spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java
  16. 7
      spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataProvider.java
  17. 22
      spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/DerbyTableMetaDataProvider.java
  18. 8
      spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/OracleCallMetaDataProvider.java
  19. 10
      spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/PostgresCallMetaDataProvider.java
  20. 5
      spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/SqlParameterSourceUtils.java
  21. 4
      spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceTransactionManager.java
  22. 8
      spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceUtils.java
  23. 11
      spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DataSourceInitializer.java
  24. 6
      spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulatorUtils.java
  25. 28
      spring-jdbc/src/main/java/org/springframework/jdbc/object/RdbmsOperation.java
  26. 20
      spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java
  27. 4
      spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcUtils.java
  28. 6
      spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodesFactory.java
  29. 91
      spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/TemporaryLobCreator.java
  30. 7
      spring-jms/src/main/java/org/springframework/jms/config/AbstractListenerContainerParser.java
  31. 7
      spring-jms/src/main/java/org/springframework/jms/connection/JmsResourceHolder.java
  32. 6
      spring-jms/src/main/java/org/springframework/jms/connection/JmsTransactionManager.java
  33. 10
      spring-jms/src/main/java/org/springframework/jms/listener/AbstractMessageListenerContainer.java
  34. 10
      spring-jms/src/main/java/org/springframework/jms/listener/adapter/AbstractAdaptableMessageListener.java
  35. 4
      spring-jms/src/main/java/org/springframework/jms/listener/endpoint/StandardJmsActivationSpecFactory.java
  36. 16
      spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompClientSupportTests.java
  37. 4
      spring-orm/src/main/java/org/springframework/orm/ObjectOptimisticLockingFailureException.java
  38. 4
      spring-orm/src/main/java/org/springframework/orm/ObjectRetrievalFailureException.java
  39. 4
      spring-oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java
  40. 12
      spring-tx/src/main/java/org/springframework/jca/cci/connection/CciLocalTransactionManager.java
  41. 16
      spring-tx/src/main/java/org/springframework/jca/cci/connection/ConnectionSpecConnectionFactoryAdapter.java
  42. 4
      spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java
  43. 4
      spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAttributeSourcePointcut.java
  44. 6
      spring-tx/src/test/java/org/springframework/transaction/TransactionSupportTests.java
  45. 14
      spring-web/src/main/java/org/springframework/http/HttpHeaders.java
  46. 17
      spring-web/src/main/java/org/springframework/web/util/WebUtils.java
  47. 67
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/BeanTypeNotPresentCondition.java
  48. 2
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/UrlTag.java
  49. 234
      spring-webmvc/src/test/java/org/springframework/web/servlet/tags/UrlTagTests.java
  50. 28
      src/test/java/com/foo/ComponentBeanDefinitionParser.java

10
spring-beans/src/main/java/org/springframework/beans/AbstractNestablePropertyAccessor.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 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.
@ -55,10 +55,10 @@ import org.springframework.util.StringUtils;
* as String arrays are converted in such a format if the array itself is not * as String arrays are converted in such a format if the array itself is not
* assignable. * assignable.
* *
* @author Rod Johnson
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Rob Harrop
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Rod Johnson
* @author Rob Harrop
* @since 4.2 * @since 4.2
* @see #registerCustomEditor * @see #registerCustomEditor
* @see #setPropertyValues * @see #setPropertyValues
@ -96,9 +96,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
Object rootObject; Object rootObject;
/** /** Map with cached nested Accessors: nested path -> Accessor instance */
* Map with cached nested Accessors: nested path -> Accessor instance.
*/
private Map<String, AbstractNestablePropertyAccessor> nestedPropertyAccessors; private Map<String, AbstractNestablePropertyAccessor> nestedPropertyAccessors;

11
spring-beans/src/main/java/org/springframework/beans/factory/CannotLoadBeanClassException.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 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.
@ -46,8 +46,8 @@ public class CannotLoadBeanClassException extends FatalBeanException {
public CannotLoadBeanClassException( public CannotLoadBeanClassException(
String resourceDescription, String beanName, String beanClassName, ClassNotFoundException cause) { String resourceDescription, String beanName, String beanClassName, ClassNotFoundException cause) {
super("Cannot find class [" + beanClassName + "] for bean with name '" + beanName + super("Cannot find class [" + String.valueOf(beanClassName) + "] for bean with name '" + beanName + "'" +
"' defined in " + resourceDescription, cause); (resourceDescription != null ? " defined in " + resourceDescription : ""), cause);
this.resourceDescription = resourceDescription; this.resourceDescription = resourceDescription;
this.beanName = beanName; this.beanName = beanName;
this.beanClassName = beanClassName; this.beanClassName = beanClassName;
@ -64,8 +64,9 @@ public class CannotLoadBeanClassException extends FatalBeanException {
public CannotLoadBeanClassException( public CannotLoadBeanClassException(
String resourceDescription, String beanName, String beanClassName, LinkageError cause) { String resourceDescription, String beanName, String beanClassName, LinkageError cause) {
super("Error loading class [" + beanClassName + "] for bean with name '" + beanName + super("Error loading class [" + String.valueOf(beanClassName) + "] for bean with name '" + beanName + "'" +
"' defined in " + resourceDescription + ": problem with class file or dependent class", cause); (resourceDescription != null ? " defined in " + resourceDescription : "") +
": problem with class file or dependent class", cause);
this.resourceDescription = resourceDescription; this.resourceDescription = resourceDescription;
this.beanName = beanName; this.beanName = beanName;
this.beanClassName = beanClassName; this.beanClassName = beanClassName;

8
spring-beans/src/main/java/org/springframework/beans/factory/config/DependencyDescriptor.java

@ -240,12 +240,14 @@ public class DependencyDescriptor extends InjectionPoint implements Serializable
* @since 4.0 * @since 4.0
*/ */
public ResolvableType getResolvableType() { public ResolvableType getResolvableType() {
if (this.resolvableType == null) { ResolvableType resolvableType = this.resolvableType;
this.resolvableType = (this.field != null ? if (resolvableType == null) {
resolvableType = (this.field != null ?
ResolvableType.forField(this.field, this.nestingLevel, this.containingClass) : ResolvableType.forField(this.field, this.nestingLevel, this.containingClass) :
ResolvableType.forMethodParameter(this.methodParameter)); ResolvableType.forMethodParameter(this.methodParameter));
this.resolvableType = resolvableType;
} }
return this.resolvableType; return resolvableType;
} }
/** /**

28
spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 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.
@ -35,6 +35,7 @@ import org.springframework.beans.factory.SmartFactoryBean;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@ -134,12 +135,21 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T getBean(String name, Class<T> requiredType) throws BeansException { public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
Object bean = getBean(name); Object bean = getBean(name);
if (requiredType != null && !requiredType.isAssignableFrom(bean.getClass())) { if (requiredType != null && !requiredType.isInstance(bean)) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
} }
return (T) bean; return (T) bean;
} }
@Override
public Object getBean(String name, Object... args) throws BeansException {
if (!ObjectUtils.isEmpty(args)) {
throw new UnsupportedOperationException(
"StaticListableBeanFactory does not support explicit bean creation arguments");
}
return getBean(name);
}
@Override @Override
public <T> T getBean(Class<T> requiredType) throws BeansException { public <T> T getBean(Class<T> requiredType) throws BeansException {
String[] beanNames = getBeanNamesForType(requiredType); String[] beanNames = getBeanNamesForType(requiredType);
@ -154,18 +164,9 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
} }
} }
@Override
public Object getBean(String name, Object... args) throws BeansException {
if (args != null) {
throw new UnsupportedOperationException(
"StaticListableBeanFactory does not support explicit bean creation arguments");
}
return getBean(name);
}
@Override @Override
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException { public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
if (args != null) { if (!ObjectUtils.isEmpty(args)) {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"StaticListableBeanFactory does not support explicit bean creation arguments"); "StaticListableBeanFactory does not support explicit bean creation arguments");
} }
@ -352,7 +353,8 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
throws NoSuchBeanDefinitionException{ throws NoSuchBeanDefinitionException{
return AnnotationUtils.findAnnotation(getType(beanName), annotationType); Class<?> beanType = getType(beanName);
return (beanType != null ? AnnotationUtils.findAnnotation(beanType, annotationType) : null);
} }
} }

4
spring-beans/src/main/java/org/springframework/beans/factory/xml/AbstractBeanDefinitionParser.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2017 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.
@ -140,7 +140,7 @@ public abstract class AbstractBeanDefinitionParser implements BeanDefinitionPars
/** /**
* Central template method to actually parse the supplied {@link Element} * Central template method to actually parse the supplied {@link Element}
* into one or more {@link BeanDefinition BeanDefinitions}. * into one or more {@link BeanDefinition BeanDefinitions}.
* @param element the element that is to be parsed into one or more {@link BeanDefinition BeanDefinitions} * @param element the element that is to be parsed into one or more {@link BeanDefinition BeanDefinitions}
* @param parserContext the object encapsulating the current state of the parsing process; * @param parserContext the object encapsulating the current state of the parsing process;
* provides access to a {@link org.springframework.beans.factory.support.BeanDefinitionRegistry} * provides access to a {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}
* @return the primary {@link BeanDefinition} resulting from the parsing of the supplied {@link Element} * @return the primary {@link BeanDefinition} resulting from the parsing of the supplied {@link Element}

3
spring-beans/src/main/java/org/springframework/beans/factory/xml/BeanDefinitionParserDelegate.java

@ -389,8 +389,7 @@ public class BeanDefinitionParserDelegate {
} }
/** /**
* Return the defaults definition object, or {@code null} if the * Return the defaults definition object.
* defaults have been initialized yet.
*/ */
public DocumentDefaultsDefinition getDefaults() { public DocumentDefaultsDefinition getDefaults() {
return this.defaults; return this.defaults;

22
spring-context/src/main/java/org/springframework/context/annotation/ConditionContext.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2017 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.
@ -25,43 +25,39 @@ import org.springframework.core.io.ResourceLoader;
* Context information for use by {@link Condition}s. * Context information for use by {@link Condition}s.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Juergen Hoeller
* @since 4.0 * @since 4.0
*/ */
public interface ConditionContext { public interface ConditionContext {
/** /**
* Return the {@link BeanDefinitionRegistry} that will hold the bean definition * Return the {@link BeanDefinitionRegistry} that will hold the bean definition
* should the condition match or {@code null} if the registry is not available. * should the condition match, or {@code null} if the registry is not available.
* @return the registry or {@code null}
*/ */
BeanDefinitionRegistry getRegistry(); BeanDefinitionRegistry getRegistry();
/** /**
* Return the {@link ConfigurableListableBeanFactory} that will hold the bean * Return the {@link ConfigurableListableBeanFactory} that will hold the bean
* definition should the condition match or {@code null} if the bean factory * definition should the condition match, or {@code null} if the bean factory
* is not available. * is not available.
* @return the bean factory or {@code null}
*/ */
ConfigurableListableBeanFactory getBeanFactory(); ConfigurableListableBeanFactory getBeanFactory();
/** /**
* Return the {@link Environment} for which the current application is running * Return the {@link Environment} for which the current application is running,
* or {@code null} if no environment is available. * or {@code null} if no environment is available.
* @return the environment or {@code null}
*/ */
Environment getEnvironment(); Environment getEnvironment();
/** /**
* Return the {@link ResourceLoader} currently being used or {@code null} * Return the {@link ResourceLoader} currently being used, or {@code null} if
* if the resource loader cannot be obtained. * the resource loader cannot be obtained.
* @return a resource loader or {@code null}
*/ */
ResourceLoader getResourceLoader(); ResourceLoader getResourceLoader();
/** /**
* Return the {@link ClassLoader} that should be used to load additional * Return the {@link ClassLoader} that should be used to load additional classes,
* classes or {@code null} if the default classloader should be used. * or {@code null} if the default classloader should be used.
* @return the class loader or {@code null}
*/ */
ClassLoader getClassLoader(); ClassLoader getClassLoader();

16
spring-context/src/test/java/org/springframework/jmx/IJmxTestBean.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 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.
@ -22,19 +22,19 @@ package org.springframework.jmx;
*/ */
public interface IJmxTestBean { public interface IJmxTestBean {
public int add(int x, int y); int add(int x, int y);
public long myOperation(); long myOperation();
public int getAge(); int getAge();
public void setAge(int age); void setAge(int age);
public void setName(String name) throws Exception; void setName(String name) throws Exception;
public String getName(); String getName();
// used to test invalid methods that exist in the proxy interface // used to test invalid methods that exist in the proxy interface
public void dontExposeMe(); void dontExposeMe();
} }

4
spring-core/src/main/java/org/springframework/util/ClassUtils.java

@ -1030,7 +1030,7 @@ public abstract class ClassUtils {
* in the given array. * in the given array.
* <p>Basically like {@code AbstractCollection.toString()}, but stripping * <p>Basically like {@code AbstractCollection.toString()}, but stripping
* the "class "/"interface " prefix before every class name. * the "class "/"interface " prefix before every class name.
* @param classes a Collection of Class objects (may be {@code null}) * @param classes an array of Class objects
* @return a String of form "[com.foo.Bar, com.foo.Baz]" * @return a String of form "[com.foo.Bar, com.foo.Baz]"
* @see java.util.AbstractCollection#toString() * @see java.util.AbstractCollection#toString()
*/ */
@ -1231,6 +1231,7 @@ public abstract class ClassUtils {
/** /**
* Check whether the given object is a CGLIB proxy. * Check whether the given object is a CGLIB proxy.
* @param object the object to check * @param object the object to check
* @see #isCglibProxyClass(Class)
* @see org.springframework.aop.support.AopUtils#isCglibProxy(Object) * @see org.springframework.aop.support.AopUtils#isCglibProxy(Object)
*/ */
public static boolean isCglibProxy(Object object) { public static boolean isCglibProxy(Object object) {
@ -1240,6 +1241,7 @@ public abstract class ClassUtils {
/** /**
* Check whether the specified class is a CGLIB-generated class. * Check whether the specified class is a CGLIB-generated class.
* @param clazz the class to check * @param clazz the class to check
* @see #isCglibProxyClassName(String)
*/ */
public static boolean isCglibProxyClass(Class<?> clazz) { public static boolean isCglibProxyClass(Class<?> clazz) {
return (clazz != null && isCglibProxyClassName(clazz.getName())); return (clazz != null && isCglibProxyClassName(clazz.getName()));

21
spring-core/src/main/java/org/springframework/util/ConcurrentReferenceHashMap.java

@ -419,9 +419,8 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
private final int initialSize; private final int initialSize;
/** /**
* Array of references indexed using the low order bits from the hash. This * Array of references indexed using the low order bits from the hash.
* property should only be set via {@link #setReferences} to ensure that the * This property should only be set along with {@code resizeThreshold}.
* {@code resizeThreshold} is maintained.
*/ */
private volatile Reference<K, V>[] references; private volatile Reference<K, V>[] references;
@ -617,14 +616,14 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
} }
/** /**
* @return the size of the current references array * Return the size of the current references array.
*/ */
public final int getSize() { public final int getSize() {
return this.references.length; return this.references.length;
} }
/** /**
* @return the total number of references in this segment * Return the total number of references in this segment.
*/ */
public final int getCount() { public final int getCount() {
return this.count; return this.count;
@ -639,21 +638,17 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
protected interface Reference<K, V> { protected interface Reference<K, V> {
/** /**
* Returns the referenced entry or {@code null} if the entry is no longer * Return the referenced entry, or {@code null} if the entry is no longer available.
* available.
* @return the entry or {@code null}
*/ */
Entry<K, V> get(); Entry<K, V> get();
/** /**
* Returns the hash for the reference. * Return the hash for the reference.
* @return the hash
*/ */
int getHash(); int getHash();
/** /**
* Returns the next reference in the chain or {@code null} * Return the next reference in the chain, or {@code null} if none.
* @return the next reference of {@code null}
*/ */
Reference<K, V> getNext(); Reference<K, V> getNext();
@ -930,7 +925,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
* Factory method used to create a new {@link Reference}. * Factory method used to create a new {@link Reference}.
* @param entry the entry contained in the reference * @param entry the entry contained in the reference
* @param hash the hash * @param hash the hash
* @param next the next reference in the chain or {@code null} * @param next the next reference in the chain, or {@code null} if none
* @return a new {@link Reference} * @return a new {@link Reference}
*/ */
public Reference<K, V> createReference(Entry<K, V> entry, int hash, Reference<K, V> next) { public Reference<K, V> createReference(Entry<K, V> entry, int hash, Reference<K, V> next) {

37
spring-core/src/main/java/org/springframework/util/StringUtils.java

@ -114,7 +114,7 @@ public abstract class StringUtils {
* @see #hasText(String) * @see #hasText(String)
*/ */
public static boolean hasLength(String str) { public static boolean hasLength(String str) {
return hasLength((CharSequence) str); return (str != null && !str.isEmpty());
} }
/** /**
@ -159,7 +159,7 @@ public abstract class StringUtils {
* @see #hasText(CharSequence) * @see #hasText(CharSequence)
*/ */
public static boolean hasText(String str) { public static boolean hasText(String str) {
return hasText((CharSequence) str); return (str != null && !str.isEmpty() && hasText((CharSequence) str));
} }
/** /**
@ -376,8 +376,8 @@ public abstract class StringUtils {
/** /**
* Count the occurrences of the substring {@code sub} in string {@code str}. * Count the occurrences of the substring {@code sub} in string {@code str}.
* @param str string to search in. Return 0 if this is {@code null}. * @param str string to search in
* @param sub string to search for. Return 0 if this is {@code null}. * @param sub string to search for
*/ */
public static int countOccurrencesOf(String str, String sub) { public static int countOccurrencesOf(String str, String sub) {
if (!hasLength(str) || !hasLength(sub)) { if (!hasLength(str) || !hasLength(sub)) {
@ -395,8 +395,7 @@ public abstract class StringUtils {
} }
/** /**
* Replace all occurrences of a substring within a string with * Replace all occurrences of a substring within a string with another string.
* another string.
* @param inString {@code String} to examine * @param inString {@code String} to examine
* @param oldPattern {@code String} to replace * @param oldPattern {@code String} to replace
* @param newPattern {@code String} to insert * @param newPattern {@code String} to insert
@ -513,9 +512,8 @@ public abstract class StringUtils {
* Capitalize a {@code String}, changing the first letter to * Capitalize a {@code String}, changing the first letter to
* upper case as per {@link Character#toUpperCase(char)}. * upper case as per {@link Character#toUpperCase(char)}.
* No other letters are changed. * No other letters are changed.
* @param str the {@code String} to capitalize, may be {@code null} * @param str the {@code String} to capitalize
* @return the capitalized {@code String}, or {@code null} if the supplied * @return the capitalized {@code String}
* string is {@code null}
*/ */
public static String capitalize(String str) { public static String capitalize(String str) {
return changeFirstCharacterCase(str, true); return changeFirstCharacterCase(str, true);
@ -525,9 +523,8 @@ public abstract class StringUtils {
* Uncapitalize a {@code String}, changing the first letter to * Uncapitalize a {@code String}, changing the first letter to
* lower case as per {@link Character#toLowerCase(char)}. * lower case as per {@link Character#toLowerCase(char)}.
* No other letters are changed. * No other letters are changed.
* @param str the {@code String} to uncapitalize, may be {@code null} * @param str the {@code String} to uncapitalize
* @return the uncapitalized {@code String}, or {@code null} if the supplied * @return the uncapitalized {@code String}
* string is {@code null}
*/ */
public static String uncapitalize(String str) { public static String uncapitalize(String str) {
return changeFirstCharacterCase(str, false); return changeFirstCharacterCase(str, false);
@ -597,9 +594,8 @@ public abstract class StringUtils {
/** /**
* Strip the filename extension from the given Java resource path, * Strip the filename extension from the given Java resource path,
* e.g. "mypath/myfile.txt" -> "mypath/myfile". * e.g. "mypath/myfile.txt" -> "mypath/myfile".
* @param path the file path (may be {@code null}) * @param path the file path
* @return the path with stripped filename extension, * @return the path with stripped filename extension
* or {@code null} if none
*/ */
public static String stripFilenameExtension(String path) { public static String stripFilenameExtension(String path) {
if (path == null) { if (path == null) {
@ -724,7 +720,7 @@ public abstract class StringUtils {
* @param localeString the locale {@code String}, following {@code Locale's} * @param localeString the locale {@code String}, following {@code Locale's}
* {@code toString()} format ("en", "en_UK", etc); * {@code toString()} format ("en", "en_UK", etc);
* also accepts spaces as separators, as an alternative to underscores * also accepts spaces as separators, as an alternative to underscores
* @return a corresponding {@code Locale} instance * @return a corresponding {@code Locale} instance, or {@code null} if none
* @throws IllegalArgumentException in case of an invalid locale specification * @throws IllegalArgumentException in case of an invalid locale specification
*/ */
public static Locale parseLocaleString(String localeString) { public static Locale parseLocaleString(String localeString) {
@ -877,8 +873,7 @@ public abstract class StringUtils {
* Copy the given {@code Collection} into a {@code String} array. * Copy the given {@code Collection} into a {@code String} array.
* <p>The {@code Collection} must contain {@code String} elements only. * <p>The {@code Collection} must contain {@code String} elements only.
* @param collection the {@code Collection} to copy * @param collection the {@code Collection} to copy
* @return the {@code String} array ({@code null} if the supplied * @return the {@code String} array
* {@code Collection} was {@code null})
*/ */
public static String[] toStringArray(Collection<String> collection) { public static String[] toStringArray(Collection<String> collection) {
if (collection == null) { if (collection == null) {
@ -892,8 +887,7 @@ public abstract class StringUtils {
* Copy the given Enumeration into a {@code String} array. * Copy the given Enumeration into a {@code String} array.
* The Enumeration must contain {@code String} elements only. * The Enumeration must contain {@code String} elements only.
* @param enumeration the Enumeration to copy * @param enumeration the Enumeration to copy
* @return the {@code String} array ({@code null} if the passed-in * @return the {@code String} array
* Enumeration was {@code null})
*/ */
public static String[] toStringArray(Enumeration<String> enumeration) { public static String[] toStringArray(Enumeration<String> enumeration) {
if (enumeration == null) { if (enumeration == null) {
@ -1048,8 +1042,7 @@ public abstract class StringUtils {
* @param ignoreEmptyTokens omit empty tokens from the result array * @param ignoreEmptyTokens omit empty tokens from the result array
* (only applies to tokens that are empty after trimming; StringTokenizer * (only applies to tokens that are empty after trimming; StringTokenizer
* will not consider subsequent delimiters as token in the first place). * will not consider subsequent delimiters as token in the first place).
* @return an array of the tokens ({@code null} if the input {@code String} * @return an array of the tokens
* was {@code null})
* @see java.util.StringTokenizer * @see java.util.StringTokenizer
* @see String#trim() * @see String#trim()
* @see #delimitedListToStringArray * @see #delimitedListToStringArray

13
spring-jdbc/src/main/java/org/springframework/jdbc/core/BatchUpdateUtils.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 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.
@ -25,20 +25,21 @@ import java.util.List;
* within the framework. * within the framework.
* *
* @author Thomas Risberg * @author Thomas Risberg
* @since 3.0
*/ */
public abstract class BatchUpdateUtils { public abstract class BatchUpdateUtils {
public static int[] executeBatchUpdate(String sql, final List<Object[]> batchValues, final int[] columnTypes, JdbcOperations jdbcOperations) { public static int[] executeBatchUpdate(
String sql, final List<Object[]> batchValues, final int[] columnTypes, JdbcOperations jdbcOperations) {
return jdbcOperations.batchUpdate( return jdbcOperations.batchUpdate(
sql, sql,
new BatchPreparedStatementSetter() { new BatchPreparedStatementSetter() {
@Override @Override
public void setValues(PreparedStatement ps, int i) throws SQLException { public void setValues(PreparedStatement ps, int i) throws SQLException {
Object[] values = batchValues.get(i); Object[] values = batchValues.get(i);
setStatementParameters(values, ps, columnTypes); setStatementParameters(values, ps, columnTypes);
} }
@Override @Override
public int getBatchSize() { public int getBatchSize() {
return batchValues.size(); return batchValues.size();
@ -46,7 +47,9 @@ public abstract class BatchUpdateUtils {
}); });
} }
protected static void setStatementParameters(Object[] values, PreparedStatement ps, int[] columnTypes) throws SQLException { protected static void setStatementParameters(Object[] values, PreparedStatement ps, int[] columnTypes)
throws SQLException {
int colIndex = 0; int colIndex = 0;
for (Object value : values) { for (Object value : values) {
colIndex++; colIndex++;

9
spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 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.
@ -1267,11 +1267,14 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
* @param param the corresponding stored procedure parameter * @param param the corresponding stored procedure parameter
* @return Map that contains returned results * @return Map that contains returned results
*/ */
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({"unchecked", "rawtypes"})
protected Map<String, Object> processResultSet(ResultSet rs, ResultSetSupportingSqlParameter param) throws SQLException { protected Map<String, Object> processResultSet(ResultSet rs, ResultSetSupportingSqlParameter param)
throws SQLException {
if (rs == null) { if (rs == null) {
return Collections.emptyMap(); return Collections.emptyMap();
} }
Map<String, Object> returnedResults = new HashMap<String, Object>(); Map<String, Object> returnedResults = new HashMap<String, Object>();
try { try {
ResultSet rsToUse = rs; ResultSet rsToUse = rs;

4
spring-jdbc/src/main/java/org/springframework/jdbc/core/StatementCreatorUtils.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 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.
@ -119,7 +119,7 @@ public abstract class StatementCreatorUtils {
/** /**
* Derive a default SQL type from the given Java type. * Derive a default SQL type from the given Java type.
* @param javaType the Java type to translate * @param javaType the Java type to translate
* @return the corresponding SQL type, or {@code null} if none found * @return the corresponding SQL type, or {@link SqlTypeValue#TYPE_UNKNOWN} if none found
*/ */
public static int javaTypeToSqlParameterType(Class<?> javaType) { public static int javaTypeToSqlParameterType(Class<?> javaType) {
Integer sqlType = javaTypeToSqlTypeMap.get(javaType); Integer sqlType = javaTypeToSqlTypeMap.get(javaType);

18
spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataContext.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2017 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.
@ -234,6 +234,14 @@ public class CallMetaDataContext {
} }
/**
* Initialize this class with metadata from the database.
* @param dataSource the DataSource used to retrieve metadata
*/
public void initializeMetaData(DataSource dataSource) {
this.metaDataProvider = CallMetaDataProviderFactory.createMetaDataProvider(dataSource, this);
}
/** /**
* Create a ReturnResultSetParameter/SqlOutParameter depending on the support provided * Create a ReturnResultSetParameter/SqlOutParameter depending on the support provided
* by the JDBC driver used for the database in use. * by the JDBC driver used for the database in use.
@ -278,14 +286,6 @@ public class CallMetaDataContext {
return this.callParameters; return this.callParameters;
} }
/**
* Initialize this class with metadata from the database.
* @param dataSource the DataSource used to retrieve metadata
*/
public void initializeMetaData(DataSource dataSource) {
this.metaDataProvider = CallMetaDataProviderFactory.createMetaDataProvider(dataSource, this);
}
/** /**
* Process the list of parameters provided, and if procedure column metadata is used, * Process the list of parameters provided, and if procedure column metadata is used,
* the parameters will be matched against the metadata information and any missing * the parameters will be matched against the metadata information and any missing

7
spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/CallMetaDataProvider.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2017 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.
@ -51,9 +51,8 @@ public interface CallMetaDataProvider {
* @throws SQLException in case of initialization failure * @throws SQLException in case of initialization failure
* @see org.springframework.jdbc.core.simple.SimpleJdbcCall#withoutProcedureColumnMetaDataAccess() * @see org.springframework.jdbc.core.simple.SimpleJdbcCall#withoutProcedureColumnMetaDataAccess()
*/ */
void initializeWithProcedureColumnMetaData( void initializeWithProcedureColumnMetaData(DatabaseMetaData databaseMetaData, String catalogName,
DatabaseMetaData databaseMetaData, String catalogName, String schemaName, String procedureName) String schemaName, String procedureName) throws SQLException;
throws SQLException;
/** /**
* Provide any modification of the procedure name passed in to match the meta data currently used. * Provide any modification of the procedure name passed in to match the meta data currently used.

22
spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/DerbyTableMetaDataProvider.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2007 the original author or authors. * Copyright 2002-2017 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.
@ -21,8 +21,8 @@ import java.sql.SQLException;
/** /**
* The Derby specific implementation of the {@link org.springframework.jdbc.core.metadata.TableMetaDataProvider}. * The Derby specific implementation of the {@link org.springframework.jdbc.core.metadata.TableMetaDataProvider}.
* Overrides the Derby metadata info regarding retreiving generated keys. It seems to work OK so not sure why they * Overrides the Derby metadata info regarding retrieving generated keys. It seems to work OK so not sure why
* claim it's not supported. * they claim it's not supported.
* *
* @author Thomas Risberg * @author Thomas Risberg
* @since 3.0 * @since 3.0
@ -31,26 +31,26 @@ public class DerbyTableMetaDataProvider extends GenericTableMetaDataProvider {
private boolean supportsGeneratedKeysOverride = false; private boolean supportsGeneratedKeysOverride = false;
public DerbyTableMetaDataProvider(DatabaseMetaData databaseMetaData) throws SQLException { public DerbyTableMetaDataProvider(DatabaseMetaData databaseMetaData) throws SQLException {
super(databaseMetaData); super(databaseMetaData);
} }
@Override @Override
public void initializeWithMetaData(DatabaseMetaData databaseMetaData) throws SQLException { public void initializeWithMetaData(DatabaseMetaData databaseMetaData) throws SQLException {
super.initializeWithMetaData(databaseMetaData); super.initializeWithMetaData(databaseMetaData);
if (!databaseMetaData.supportsGetGeneratedKeys()) { if (!databaseMetaData.supportsGetGeneratedKeys()) {
logger.warn("Overriding supportsGetGeneratedKeys from DatabaseMetaData to 'true'; it was reported as " + if (logger.isWarnEnabled()) {
"'false' by " + databaseMetaData.getDriverName() + " " + databaseMetaData.getDriverVersion()); logger.warn("Overriding supportsGetGeneratedKeys from DatabaseMetaData to 'true'; it was reported as " +
supportsGeneratedKeysOverride = true; "'false' by " + databaseMetaData.getDriverName() + " " + databaseMetaData.getDriverVersion());
}
this.supportsGeneratedKeysOverride = true;
} }
} }
@Override @Override
public boolean isGetGeneratedKeysSupported() { public boolean isGetGeneratedKeysSupported() {
boolean derbysAnswer = super.isGetGeneratedKeysSupported(); return (super.isGetGeneratedKeysSupported() || this.supportsGeneratedKeysOverride);
if (!derbysAnswer) {
return supportsGeneratedKeysOverride;
}
return derbysAnswer;
} }
} }

8
spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/OracleCallMetaDataProvider.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 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.
@ -25,7 +25,7 @@ import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.core.SqlParameter;
/** /**
* Oracle specific implementation for the {@link CallMetaDataProvider} interface. * Oracle-specific implementation for the {@link CallMetaDataProvider} interface.
* This class is intended for internal use by the Simple JDBC classes. * This class is intended for internal use by the Simple JDBC classes.
* *
* @author Thomas Risberg * @author Thomas Risberg
@ -59,13 +59,13 @@ public class OracleCallMetaDataProvider extends GenericCallMetaDataProvider {
@Override @Override
public String metaDataCatalogNameToUse(String catalogName) { public String metaDataCatalogNameToUse(String catalogName) {
// Oracle uses catalog name for package name or an empty string if no package // Oracle uses catalog name for package name or an empty string if no package
return catalogName == null ? "" : catalogNameToUse(catalogName); return (catalogName == null ? "" : catalogNameToUse(catalogName));
} }
@Override @Override
public String metaDataSchemaNameToUse(String schemaName) { public String metaDataSchemaNameToUse(String schemaName) {
// Use current user schema if no schema specified // Use current user schema if no schema specified
return schemaName == null ? getUserName() : super.metaDataSchemaNameToUse(schemaName); return (schemaName == null ? getUserName() : super.metaDataSchemaNameToUse(schemaName));
} }
@Override @Override

10
spring-jdbc/src/main/java/org/springframework/jdbc/core/metadata/PostgresCallMetaDataProvider.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2011 the original author or authors. * Copyright 2002-2017 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.
@ -25,7 +25,7 @@ import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.core.SqlParameter;
/** /**
* Oracle specific implementation for the {@link org.springframework.jdbc.core.metadata.CallMetaDataProvider} interface. * Postgres-specific implementation for the {@link CallMetaDataProvider} interface.
* This class is intended for internal use by the Simple JDBC classes. * This class is intended for internal use by the Simple JDBC classes.
* *
* @author Thomas Risberg * @author Thomas Risberg
@ -59,7 +59,7 @@ public class PostgresCallMetaDataProvider extends GenericCallMetaDataProvider {
@Override @Override
public String metaDataSchemaNameToUse(String schemaName) { public String metaDataSchemaNameToUse(String schemaName) {
// Use public schema if no schema specified // Use public schema if no schema specified
return schemaName == null ? "public" : super.metaDataSchemaNameToUse(schemaName); return (schemaName == null ? "public" : super.metaDataSchemaNameToUse(schemaName));
} }
@Override @Override
@ -74,7 +74,7 @@ public class PostgresCallMetaDataProvider extends GenericCallMetaDataProvider {
@Override @Override
public boolean byPassReturnParameter(String parameterName) { public boolean byPassReturnParameter(String parameterName) {
return (RETURN_VALUE_NAME.equals(parameterName) || return RETURN_VALUE_NAME.equals(parameterName);
super.byPassReturnParameter(parameterName));
} }
} }

5
spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/SqlParameterSourceUtils.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 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.
@ -90,8 +90,7 @@ public class SqlParameterSourceUtils {
Map<String, String> caseInsensitiveParameterNames = new HashMap<String, String>(); Map<String, String> caseInsensitiveParameterNames = new HashMap<String, String>();
if (parameterSource instanceof BeanPropertySqlParameterSource) { if (parameterSource instanceof BeanPropertySqlParameterSource) {
String[] propertyNames = ((BeanPropertySqlParameterSource)parameterSource).getReadablePropertyNames(); String[] propertyNames = ((BeanPropertySqlParameterSource)parameterSource).getReadablePropertyNames();
for (int i = 0; i < propertyNames.length; i++) { for (String name : propertyNames) {
String name = propertyNames[i];
caseInsensitiveParameterNames.put(name.toLowerCase(), name); caseInsensitiveParameterNames.put(name.toLowerCase(), name);
} }
} }

4
spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceTransactionManager.java

@ -229,7 +229,7 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan
@Override @Override
protected boolean isExistingTransaction(Object transaction) { protected boolean isExistingTransaction(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
return (txObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive()); return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
} }
/** /**
@ -241,7 +241,7 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan
Connection con = null; Connection con = null;
try { try {
if (txObject.getConnectionHolder() == null || if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) { txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
Connection newCon = this.dataSource.getConnection(); Connection newCon = this.dataSource.getConnection();
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {

8
spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceUtils.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2017 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.
@ -268,8 +268,10 @@ public abstract class DataSourceUtils {
*/ */
public static void applyTimeout(Statement stmt, DataSource dataSource, int timeout) throws SQLException { public static void applyTimeout(Statement stmt, DataSource dataSource, int timeout) throws SQLException {
Assert.notNull(stmt, "No Statement specified"); Assert.notNull(stmt, "No Statement specified");
Assert.notNull(dataSource, "No DataSource specified"); ConnectionHolder holder = null;
ConnectionHolder holder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); if (dataSource != null) {
holder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
}
if (holder != null && holder.hasTimeout()) { if (holder != null && holder.hasTimeout()) {
// Remaining transaction timeout overrides specified value. // Remaining transaction timeout overrides specified value.
stmt.setQueryTimeout(holder.getTimeToLiveInSeconds()); stmt.setQueryTimeout(holder.getTimeToLiveInSeconds());

11
spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DataSourceInitializer.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2017 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.
@ -54,10 +54,8 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean {
} }
/** /**
* Set the {@link DatabasePopulator} to execute during the bean initialization * Set the {@link DatabasePopulator} to execute during the bean initialization phase.
* phase. * @param databasePopulator the {@code DatabasePopulator} to use during initialization
* @param databasePopulator the {@code DatabasePopulator} to use during
* initialization
* @see #setDatabaseCleaner * @see #setDatabaseCleaner
*/ */
public void setDatabasePopulator(DatabasePopulator databasePopulator) { public void setDatabasePopulator(DatabasePopulator databasePopulator) {
@ -84,6 +82,7 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean {
this.enabled = enabled; this.enabled = enabled;
} }
/** /**
* Use the {@linkplain #setDatabasePopulator database populator} to set up * Use the {@linkplain #setDatabasePopulator database populator} to set up
* the database. * the database.
@ -103,7 +102,7 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean {
} }
private void execute(DatabasePopulator populator) { private void execute(DatabasePopulator populator) {
Assert.state(dataSource != null, "DataSource must be set"); Assert.state(this.dataSource != null, "DataSource must be set");
if (this.enabled && populator != null) { if (this.enabled && populator != null) {
DatabasePopulatorUtils.execute(populator, this.dataSource); DatabasePopulatorUtils.execute(populator, this.dataSource);
} }

6
spring-jdbc/src/main/java/org/springframework/jdbc/datasource/init/DatabasePopulatorUtils.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 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.
@ -48,9 +48,7 @@ public abstract class DatabasePopulatorUtils {
populator.populate(connection); populator.populate(connection);
} }
finally { finally {
if (connection != null) { DataSourceUtils.releaseConnection(connection, dataSource);
DataSourceUtils.releaseConnection(connection, dataSource);
}
} }
} }
catch (Throwable ex) { catch (Throwable ex) {

28
spring-jdbc/src/main/java/org/springframework/jdbc/object/RdbmsOperation.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2017 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.
@ -32,6 +32,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.core.SqlParameter;
import org.springframework.util.Assert;
/** /**
* An "RDBMS operation" is a multi-threaded, reusable object representing a query, * An "RDBMS operation" is a multi-threaded, reusable object representing a query,
@ -85,27 +86,25 @@ public abstract class RdbmsOperation implements InitializingBean {
/** /**
* An alternative to the more commonly used setDataSource() when you want to * An alternative to the more commonly used {@link #setDataSource} when you want to
* use the same JdbcTemplate in multiple RdbmsOperations. This is appropriate if the * use the same {@link JdbcTemplate} in multiple {@code RdbmsOperations}. This is
* JdbcTemplate has special configuration such as a SQLExceptionTranslator that should * appropriate if the {@code JdbcTemplate} has special configuration such as a
* apply to multiple RdbmsOperation objects. * {@link org.springframework.jdbc.support.SQLExceptionTranslator} to be reused.
*/ */
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
if (jdbcTemplate == null) { Assert.notNull(jdbcTemplate, "JdbcTemplate must not be null");
throw new IllegalArgumentException("jdbcTemplate must not be null");
}
this.jdbcTemplate = jdbcTemplate; this.jdbcTemplate = jdbcTemplate;
} }
/** /**
* Return the JdbcTemplate object used by this object. * Return the {@link JdbcTemplate} used by this operation object.
*/ */
public JdbcTemplate getJdbcTemplate() { public JdbcTemplate getJdbcTemplate() {
return this.jdbcTemplate; return this.jdbcTemplate;
} }
/** /**
* Set the JDBC DataSource to obtain connections from. * Set the JDBC {@link DataSource} to obtain connections from.
* @see org.springframework.jdbc.core.JdbcTemplate#setDataSource * @see org.springframework.jdbc.core.JdbcTemplate#setDataSource
*/ */
public void setDataSource(DataSource dataSource) { public void setDataSource(DataSource dataSource) {
@ -233,9 +232,8 @@ public abstract class RdbmsOperation implements InitializingBean {
} }
/** /**
* Subclasses can override this to supply dynamic SQL if they wish, * Subclasses can override this to supply dynamic SQL if they wish, but SQL is
* but SQL is normally set by calling the setSql() method * normally set by calling the {@link #setSql} method or in a subclass constructor.
* or in a subclass constructor.
*/ */
public String getSql() { public String getSql() {
return this.sql; return this.sql;
@ -287,7 +285,7 @@ public abstract class RdbmsOperation implements InitializingBean {
* @param parameters Array containing the declared {@link SqlParameter} objects * @param parameters Array containing the declared {@link SqlParameter} objects
* @see #declaredParameters * @see #declaredParameters
*/ */
public void setParameters(SqlParameter[] parameters) { public void setParameters(SqlParameter... parameters) {
if (isCompiled()) { if (isCompiled()) {
throw new InvalidDataAccessApiUsageException("Cannot add parameters once the query is compiled"); throw new InvalidDataAccessApiUsageException("Cannot add parameters once the query is compiled");
} }
@ -396,7 +394,7 @@ public abstract class RdbmsOperation implements InitializingBean {
* Validate the named parameters passed to an execute method based on declared parameters. * Validate the named parameters passed to an execute method based on declared parameters.
* Subclasses should invoke this method before every {@code executeQuery()} or * Subclasses should invoke this method before every {@code executeQuery()} or
* {@code update()} method. * {@code update()} method.
* @param parameters parameter Map supplied. May be {@code null}. * @param parameters parameter Map supplied (may be {@code null})
* @throws InvalidDataAccessApiUsageException if the parameters are invalid * @throws InvalidDataAccessApiUsageException if the parameters are invalid
*/ */
protected void validateNamedParameters(Map<String, ?> parameters) throws InvalidDataAccessApiUsageException { protected void validateNamedParameters(Map<String, ?> parameters) throws InvalidDataAccessApiUsageException {

20
spring-jdbc/src/main/java/org/springframework/jdbc/support/AbstractFallbackSQLExceptionTranslator.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 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.
@ -70,16 +70,22 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep
sql = ""; sql = "";
} }
DataAccessException dex = doTranslate(task, sql, ex); DataAccessException dae = doTranslate(task, sql, ex);
if (dex != null) { if (dae != null) {
// Specific exception match found. // Specific exception match found.
return dex; return dae;
} }
// Looking for a fallback... // Looking for a fallback...
SQLExceptionTranslator fallback = getFallbackTranslator(); SQLExceptionTranslator fallback = getFallbackTranslator();
if (fallback != null) { if (fallback != null) {
return fallback.translate(task, sql, ex); dae = fallback.translate(task, sql, ex);
if (dae != null) {
// Fallback exception match found.
return dae;
}
} }
// We couldn't identify it more precisely. // We couldn't identify it more precisely.
return new UncategorizedSQLException(task, sql, ex); return new UncategorizedSQLException(task, sql, ex);
} }
@ -90,7 +96,7 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep
* is allowed to return {@code null} to indicate that no exception match has * is allowed to return {@code null} to indicate that no exception match has
* been found and that fallback translation should kick in. * been found and that fallback translation should kick in.
* @param task readable text describing the task being attempted * @param task readable text describing the task being attempted
* @param sql SQL query or update that caused the problem (may be {@code null}) * @param sql SQL query or update that caused the problem (if known)
* @param ex the offending {@code SQLException} * @param ex the offending {@code SQLException}
* @return the DataAccessException, wrapping the {@code SQLException}; * @return the DataAccessException, wrapping the {@code SQLException};
* or {@code null} if no exception match found * or {@code null} if no exception match found
@ -103,7 +109,7 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep
* <p>To be called by translator subclasses when creating an instance of a generic * <p>To be called by translator subclasses when creating an instance of a generic
* {@link org.springframework.dao.DataAccessException} class. * {@link org.springframework.dao.DataAccessException} class.
* @param task readable text describing the task being attempted * @param task readable text describing the task being attempted
* @param sql the SQL statement that caused the problem (may be {@code null}) * @param sql the SQL statement that caused the problem
* @param ex the offending {@code SQLException} * @param ex the offending {@code SQLException}
* @return the message {@code String} to use * @return the message {@code String} to use
*/ */

4
spring-jdbc/src/main/java/org/springframework/jdbc/support/JdbcUtils.java

@ -472,8 +472,8 @@ public abstract class JdbcUtils {
} }
/** /**
* Convert a column name with underscores to the corresponding property name using "camel case". A name * Convert a column name with underscores to the corresponding property name using "camel case".
* like "customer_number" would match a "customerNumber" property name. * A name like "customer_number" would match a "customerNumber" property name.
* @param name the column name to be converted * @param name the column name to be converted
* @return the name using "camel case" * @return the name using "camel case"
*/ */

6
spring-jdbc/src/main/java/org/springframework/jdbc/support/SQLErrorCodesFactory.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 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.
@ -216,9 +216,9 @@ public class SQLErrorCodesFactory {
} }
catch (MetaDataAccessException ex) { catch (MetaDataAccessException ex) {
logger.warn("Error while extracting database name - falling back to empty error codes", ex); logger.warn("Error while extracting database name - falling back to empty error codes", ex);
// Fallback is to return an empty SQLErrorCodes instance.
return new SQLErrorCodes();
} }
// Fallback is to return an empty SQLErrorCodes instance.
return new SQLErrorCodes();
} }
} }
} }

91
spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/TemporaryLobCreator.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2017 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.
@ -59,11 +59,15 @@ public class TemporaryLobCreator implements LobCreator {
public void setBlobAsBytes(PreparedStatement ps, int paramIndex, byte[] content) public void setBlobAsBytes(PreparedStatement ps, int paramIndex, byte[] content)
throws SQLException { throws SQLException {
Blob blob = ps.getConnection().createBlob(); if (content != null) {
blob.setBytes(1, content); Blob blob = ps.getConnection().createBlob();
blob.setBytes(1, content);
this.temporaryBlobs.add(blob); this.temporaryBlobs.add(blob);
ps.setBlob(paramIndex, blob); ps.setBlob(paramIndex, blob);
}
else {
ps.setBlob(paramIndex, (Blob) null);
}
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(content != null ? "Copied bytes into temporary BLOB with length " + content.length : logger.debug(content != null ? "Copied bytes into temporary BLOB with length " + content.length :
@ -76,17 +80,21 @@ public class TemporaryLobCreator implements LobCreator {
PreparedStatement ps, int paramIndex, InputStream binaryStream, int contentLength) PreparedStatement ps, int paramIndex, InputStream binaryStream, int contentLength)
throws SQLException { throws SQLException {
Blob blob = ps.getConnection().createBlob(); if (binaryStream != null) {
try { Blob blob = ps.getConnection().createBlob();
FileCopyUtils.copy(binaryStream, blob.setBinaryStream(1)); try {
FileCopyUtils.copy(binaryStream, blob.setBinaryStream(1));
}
catch (IOException ex) {
throw new DataAccessResourceFailureException("Could not copy into LOB stream", ex);
}
this.temporaryBlobs.add(blob);
ps.setBlob(paramIndex, blob);
} }
catch (IOException ex) { else {
throw new DataAccessResourceFailureException("Could not copy into LOB stream", ex); ps.setBlob(paramIndex, (Blob) null);
} }
this.temporaryBlobs.add(blob);
ps.setBlob(paramIndex, blob);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(binaryStream != null ? logger.debug(binaryStream != null ?
"Copied binary stream into temporary BLOB with length " + contentLength : "Copied binary stream into temporary BLOB with length " + contentLength :
@ -98,11 +106,15 @@ public class TemporaryLobCreator implements LobCreator {
public void setClobAsString(PreparedStatement ps, int paramIndex, String content) public void setClobAsString(PreparedStatement ps, int paramIndex, String content)
throws SQLException { throws SQLException {
Clob clob = ps.getConnection().createClob(); if (content != null) {
clob.setString(1, content); Clob clob = ps.getConnection().createClob();
clob.setString(1, content);
this.temporaryClobs.add(clob); this.temporaryClobs.add(clob);
ps.setClob(paramIndex, clob); ps.setClob(paramIndex, clob);
}
else {
ps.setClob(paramIndex, (Clob) null);
}
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(content != null ? "Copied string into temporary CLOB with length " + content.length() : logger.debug(content != null ? "Copied string into temporary CLOB with length " + content.length() :
@ -115,17 +127,21 @@ public class TemporaryLobCreator implements LobCreator {
PreparedStatement ps, int paramIndex, InputStream asciiStream, int contentLength) PreparedStatement ps, int paramIndex, InputStream asciiStream, int contentLength)
throws SQLException { throws SQLException {
Clob clob = ps.getConnection().createClob(); if (asciiStream != null) {
try { Clob clob = ps.getConnection().createClob();
FileCopyUtils.copy(asciiStream, clob.setAsciiStream(1)); try {
FileCopyUtils.copy(asciiStream, clob.setAsciiStream(1));
}
catch (IOException ex) {
throw new DataAccessResourceFailureException("Could not copy into LOB stream", ex);
}
this.temporaryClobs.add(clob);
ps.setClob(paramIndex, clob);
} }
catch (IOException ex) { else {
throw new DataAccessResourceFailureException("Could not copy into LOB stream", ex); ps.setClob(paramIndex, (Clob) null);
} }
this.temporaryClobs.add(clob);
ps.setClob(paramIndex, clob);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(asciiStream != null ? logger.debug(asciiStream != null ?
"Copied ASCII stream into temporary CLOB with length " + contentLength : "Copied ASCII stream into temporary CLOB with length " + contentLength :
@ -138,17 +154,21 @@ public class TemporaryLobCreator implements LobCreator {
PreparedStatement ps, int paramIndex, Reader characterStream, int contentLength) PreparedStatement ps, int paramIndex, Reader characterStream, int contentLength)
throws SQLException { throws SQLException {
Clob clob = ps.getConnection().createClob(); if (characterStream != null) {
try { Clob clob = ps.getConnection().createClob();
FileCopyUtils.copy(characterStream, clob.setCharacterStream(1)); try {
FileCopyUtils.copy(characterStream, clob.setCharacterStream(1));
}
catch (IOException ex) {
throw new DataAccessResourceFailureException("Could not copy into LOB stream", ex);
}
this.temporaryClobs.add(clob);
ps.setClob(paramIndex, clob);
} }
catch (IOException ex) { else {
throw new DataAccessResourceFailureException("Could not copy into LOB stream", ex); ps.setClob(paramIndex, (Clob) null);
} }
this.temporaryClobs.add(clob);
ps.setClob(paramIndex, clob);
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(characterStream != null ? logger.debug(characterStream != null ?
"Copied character stream into temporary CLOB with length " + contentLength : "Copied character stream into temporary CLOB with length " + contentLength :
@ -170,4 +190,5 @@ public class TemporaryLobCreator implements LobCreator {
logger.error("Could not free LOB", ex); logger.error("Could not free LOB", ex);
} }
} }
} }

7
spring-jms/src/main/java/org/springframework/jms/config/AbstractListenerContainerParser.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2017 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.
@ -151,15 +151,14 @@ abstract class AbstractListenerContainerParser implements BeanDefinitionParser {
listenerDef.getPropertyValues().add("delegate", new RuntimeBeanReference(ref)); listenerDef.getPropertyValues().add("delegate", new RuntimeBeanReference(ref));
} }
String method = null;
if (listenerEle.hasAttribute(METHOD_ATTRIBUTE)) { if (listenerEle.hasAttribute(METHOD_ATTRIBUTE)) {
method = listenerEle.getAttribute(METHOD_ATTRIBUTE); String method = listenerEle.getAttribute(METHOD_ATTRIBUTE);
if (!StringUtils.hasText(method)) { if (!StringUtils.hasText(method)) {
parserContext.getReaderContext().error( parserContext.getReaderContext().error(
"Listener 'method' attribute contains empty value.", listenerEle); "Listener 'method' attribute contains empty value.", listenerEle);
} }
listenerDef.getPropertyValues().add("defaultListenerMethod", method);
} }
listenerDef.getPropertyValues().add("defaultListenerMethod", method);
PropertyValue messageConverterPv = commonContainerProperties.getPropertyValue("messageConverter"); PropertyValue messageConverterPv = commonContainerProperties.getPropertyValue("messageConverter");
if (messageConverterPv != null) { if (messageConverterPv != null) {

7
spring-jms/src/main/java/org/springframework/jms/connection/JmsResourceHolder.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2017 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.
@ -170,10 +170,7 @@ public class JmsResourceHolder extends ResourceHolderSupport {
} }
public Session getSession(Class<? extends Session> sessionType, Connection connection) { public Session getSession(Class<? extends Session> sessionType, Connection connection) {
List<Session> sessions = this.sessions; List<Session> sessions = (connection != null ? this.sessionsPerConnection.get(connection) : this.sessions);
if (connection != null) {
sessions = this.sessionsPerConnection.get(connection);
}
return CollectionUtils.findValueOfType(sessions, sessionType); return CollectionUtils.findValueOfType(sessions, sessionType);
} }

6
spring-jms/src/main/java/org/springframework/jms/connection/JmsTransactionManager.java

@ -170,7 +170,7 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager
@Override @Override
protected boolean isExistingTransaction(Object transaction) { protected boolean isExistingTransaction(Object transaction) {
JmsTransactionObject txObject = (JmsTransactionObject) transaction; JmsTransactionObject txObject = (JmsTransactionObject) transaction;
return (txObject.getResourceHolder() != null); return txObject.hasResourceHolder();
} }
@Override @Override
@ -316,6 +316,10 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager
return this.resourceHolder; return this.resourceHolder;
} }
public boolean hasResourceHolder() {
return (this.resourceHolder != null);
}
@Override @Override
public boolean isRollbackOnly() { public boolean isRollbackOnly() {
return this.resourceHolder.isRollbackOnly(); return this.resourceHolder.isRollbackOnly();

10
spring-jms/src/main/java/org/springframework/jms/listener/AbstractMessageListenerContainer.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2017 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.
@ -197,7 +197,6 @@ public abstract class AbstractMessageListenerContainer extends AbstractJmsListen
* @see #setDestinationName(String) * @see #setDestinationName(String)
*/ */
public void setDestination(Destination destination) { public void setDestination(Destination destination) {
Assert.notNull(destination, "'destination' must not be null");
this.destination = destination; this.destination = destination;
if (destination instanceof Topic && !(destination instanceof Queue)) { if (destination instanceof Topic && !(destination instanceof Queue)) {
// Clearly a Topic: let's set the "pubSubDomain" flag accordingly. // Clearly a Topic: let's set the "pubSubDomain" flag accordingly.
@ -223,11 +222,9 @@ public abstract class AbstractMessageListenerContainer extends AbstractJmsListen
* container picking up the new destination immediately (works e.g. with * container picking up the new destination immediately (works e.g. with
* DefaultMessageListenerContainer, as long as the cache level is less than * DefaultMessageListenerContainer, as long as the cache level is less than
* CACHE_CONSUMER). However, this is considered advanced usage; use it with care! * CACHE_CONSUMER). However, this is considered advanced usage; use it with care!
* @param destinationName the desired destination (can be {@code null})
* @see #setDestination(javax.jms.Destination) * @see #setDestination(javax.jms.Destination)
*/ */
public void setDestinationName(String destinationName) { public void setDestinationName(String destinationName) {
Assert.notNull(destinationName, "'destinationName' must not be null");
this.destination = destinationName; this.destination = destinationName;
} }
@ -246,7 +243,8 @@ public abstract class AbstractMessageListenerContainer extends AbstractJmsListen
* (never {@code null}). * (never {@code null}).
*/ */
protected String getDestinationDescription() { protected String getDestinationDescription() {
return this.destination.toString(); Object destination = this.destination;
return (destination != null ? destination.toString() : "");
} }
/** /**
@ -432,7 +430,7 @@ public abstract class AbstractMessageListenerContainer extends AbstractJmsListen
*/ */
public void setDurableSubscriptionName(String durableSubscriptionName) { public void setDurableSubscriptionName(String durableSubscriptionName) {
this.subscriptionName = durableSubscriptionName; this.subscriptionName = durableSubscriptionName;
this.subscriptionDurable = true; this.subscriptionDurable = (durableSubscriptionName != null);
} }
/** /**

10
spring-jms/src/main/java/org/springframework/jms/listener/adapter/AbstractAdaptableMessageListener.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 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.
@ -191,6 +191,9 @@ public abstract class AbstractAdaptableMessageListener
} }
} }
@Override
public abstract void onMessage(Message message, Session session) throws JMSException;
/** /**
* Handle the given exception that arose during listener execution. * Handle the given exception that arose during listener execution.
* The default implementation logs the exception at error level. * The default implementation logs the exception at error level.
@ -204,6 +207,7 @@ public abstract class AbstractAdaptableMessageListener
logger.error("Listener execution failed", ex); logger.error("Listener execution failed", ex);
} }
/** /**
* Extract the message body from the given JMS message. * Extract the message body from the given JMS message.
* @param message the JMS {@code Message} * @param message the JMS {@code Message}
@ -453,6 +457,7 @@ public abstract class AbstractAdaptableMessageListener
@Override @Override
protected Message createMessageForPayload(Object payload, Session session, Object conversionHint) protected Message createMessageForPayload(Object payload, Session session, Object conversionHint)
throws JMSException { throws JMSException {
MessageConverter converter = getMessageConverter(); MessageConverter converter = getMessageConverter();
if (converter == null) { if (converter == null) {
throw new IllegalStateException("No message converter, cannot handle '" + payload + "'"); throw new IllegalStateException("No message converter, cannot handle '" + payload + "'");
@ -464,6 +469,7 @@ public abstract class AbstractAdaptableMessageListener
return converter.toMessage(payload, session); return converter.toMessage(payload, session);
} }
protected class LazyResolutionMessage implements org.springframework.messaging.Message<Object> { protected class LazyResolutionMessage implements org.springframework.messaging.Message<Object> {
private final javax.jms.Message message; private final javax.jms.Message message;
@ -487,7 +493,6 @@ public abstract class AbstractAdaptableMessageListener
"Failed to extract payload from [" + this.message + "]", ex); "Failed to extract payload from [" + this.message + "]", ex);
} }
} }
//
return this.payload; return this.payload;
} }
@ -513,7 +518,6 @@ public abstract class AbstractAdaptableMessageListener
return this.headers; return this.headers;
} }
} }
} }

4
spring-jms/src/main/java/org/springframework/jms/listener/endpoint/StandardJmsActivationSpecFactory.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2017 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.
@ -94,7 +94,7 @@ public class StandardJmsActivationSpecFactory implements JmsActivationSpecFactor
* Return the {@link DestinationResolver} to use for resolving destinations names. * Return the {@link DestinationResolver} to use for resolving destinations names.
*/ */
public DestinationResolver getDestinationResolver() { public DestinationResolver getDestinationResolver() {
return destinationResolver; return this.destinationResolver;
} }
@Override @Override

16
spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompClientSupportTests.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2017 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.
@ -13,29 +13,25 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.messaging.simp.stomp; package org.springframework.messaging.simp.stomp;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
* Unit tests for {@@link StompClientSupport}. * Unit tests for {@link StompClientSupport}.
*
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
*/ */
public class StompClientSupportTests { public class StompClientSupportTests {
private StompClientSupport stompClient; private final StompClientSupport stompClient = new StompClientSupport() {};
@Before
public void setUp() throws Exception {
this.stompClient = new StompClientSupport() {};
}
@Test @Test
public void defaultHearbeatValidation() throws Exception { public void defaultHeartbeatValidation() throws Exception {
trySetDefaultHeartbeat(null); trySetDefaultHeartbeat(null);
trySetDefaultHeartbeat(new long[] {-1, 0}); trySetDefaultHeartbeat(new long[] {-1, 0});
trySetDefaultHeartbeat(new long[] {0, -1}); trySetDefaultHeartbeat(new long[] {0, -1});

4
spring-orm/src/main/java/org/springframework/orm/ObjectOptimisticLockingFailureException.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 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.
@ -149,7 +149,7 @@ public class ObjectOptimisticLockingFailureException extends OptimisticLockingFa
* Return the identifier of the object for which the locking failed. * Return the identifier of the object for which the locking failed.
*/ */
public Object getIdentifier() { public Object getIdentifier() {
return identifier; return this.identifier;
} }
} }

4
spring-orm/src/main/java/org/springframework/orm/ObjectRetrievalFailureException.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 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.
@ -123,7 +123,7 @@ public class ObjectRetrievalFailureException extends DataRetrievalFailureExcepti
* Return the identifier of the object that was not found. * Return the identifier of the object that was not found.
*/ */
public Object getIdentifier() { public Object getIdentifier() {
return identifier; return this.identifier;
} }
} }

4
spring-oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 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.
@ -196,7 +196,6 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi
* or {@link #setPackagesToScan "packagesToScan"} is required. * or {@link #setPackagesToScan "packagesToScan"} is required.
*/ */
public void setContextPath(String contextPath) { public void setContextPath(String contextPath) {
Assert.hasText(contextPath, "'contextPath' must not be null");
this.contextPath = contextPath; this.contextPath = contextPath;
} }
@ -213,7 +212,6 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, Generi
* or {@link #setPackagesToScan "packagesToScan"} is required. * or {@link #setPackagesToScan "packagesToScan"} is required.
*/ */
public void setClassesToBeBound(Class<?>... classesToBeBound) { public void setClassesToBeBound(Class<?>... classesToBeBound) {
Assert.notEmpty(classesToBeBound, "'classesToBeBound' must not be empty");
this.classesToBeBound = classesToBeBound; this.classesToBeBound = classesToBeBound;
} }

12
spring-tx/src/main/java/org/springframework/jca/cci/connection/CciLocalTransactionManager.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2017 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.
@ -40,14 +40,14 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
* *
* <p>Application code is required to retrieve the CCI Connection via * <p>Application code is required to retrieve the CCI Connection via
* {@link ConnectionFactoryUtils#getConnection(ConnectionFactory)} instead of a standard * {@link ConnectionFactoryUtils#getConnection(ConnectionFactory)} instead of a standard
* J2EE-style {@link ConnectionFactory#getConnection()} call. Spring classes such as * Java EE-style {@link ConnectionFactory#getConnection()} call. Spring classes such as
* {@link org.springframework.jca.cci.core.CciTemplate} use this strategy implicitly. * {@link org.springframework.jca.cci.core.CciTemplate} use this strategy implicitly.
* If not used in combination with this transaction manager, the * If not used in combination with this transaction manager, the
* {@link ConnectionFactoryUtils} lookup strategy behaves exactly like the native * {@link ConnectionFactoryUtils} lookup strategy behaves exactly like the native
* DataSource lookup; it can thus be used in a portable fashion. * DataSource lookup; it can thus be used in a portable fashion.
* *
* <p>Alternatively, you can allow application code to work with the standard * <p>Alternatively, you can allow application code to work with the standard
* J2EE lookup pattern {@link ConnectionFactory#getConnection()}, for example * Java EE lookup pattern {@link ConnectionFactory#getConnection()}, for example
* for legacy code that is not aware of Spring at all. In that case, define a * for legacy code that is not aware of Spring at all. In that case, define a
* {@link TransactionAwareConnectionFactoryProxy} for your target ConnectionFactory, * {@link TransactionAwareConnectionFactoryProxy} for your target ConnectionFactory,
* which will automatically participate in Spring-managed transactions. * which will automatically participate in Spring-managed transactions.
@ -135,7 +135,7 @@ public class CciLocalTransactionManager extends AbstractPlatformTransactionManag
protected boolean isExistingTransaction(Object transaction) { protected boolean isExistingTransaction(Object transaction) {
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction; CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction;
// Consider a pre-bound connection as transaction. // Consider a pre-bound connection as transaction.
return (txObject.getConnectionHolder() != null); return txObject.hasConnectionHolder();
} }
@Override @Override
@ -269,6 +269,10 @@ public class CciLocalTransactionManager extends AbstractPlatformTransactionManag
public ConnectionHolder getConnectionHolder() { public ConnectionHolder getConnectionHolder() {
return this.connectionHolder; return this.connectionHolder;
} }
public boolean hasConnectionHolder() {
return (this.connectionHolder != null);
}
} }
} }

16
spring-tx/src/main/java/org/springframework/jca/cci/connection/ConnectionSpecConnectionFactoryAdapter.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2017 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.
@ -18,9 +18,11 @@ package org.springframework.jca.cci.connection;
import javax.resource.ResourceException; import javax.resource.ResourceException;
import javax.resource.cci.Connection; import javax.resource.cci.Connection;
import javax.resource.cci.ConnectionFactory;
import javax.resource.cci.ConnectionSpec; import javax.resource.cci.ConnectionSpec;
import org.springframework.core.NamedThreadLocal; import org.springframework.core.NamedThreadLocal;
import org.springframework.util.Assert;
/** /**
* An adapter for a target CCI {@link javax.resource.cci.ConnectionFactory}, * An adapter for a target CCI {@link javax.resource.cci.ConnectionFactory},
@ -129,15 +131,9 @@ public class ConnectionSpecConnectionFactoryAdapter extends DelegatingConnection
* @see javax.resource.cci.ConnectionFactory#getConnection() * @see javax.resource.cci.ConnectionFactory#getConnection()
*/ */
protected Connection doGetConnection(ConnectionSpec spec) throws ResourceException { protected Connection doGetConnection(ConnectionSpec spec) throws ResourceException {
if (getTargetConnectionFactory() == null) { ConnectionFactory connectionFactory = getTargetConnectionFactory();
throw new IllegalStateException("targetConnectionFactory is required"); Assert.state(connectionFactory != null, "No 'targetConnectionFactory' set");
} return (spec != null ? connectionFactory.getConnection(spec) : connectionFactory.getConnection());
if (spec != null) {
return getTargetConnectionFactory().getConnection(spec);
}
else {
return getTargetConnectionFactory().getConnection();
}
} }
} }

4
spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 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.
@ -197,7 +197,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
* @see NameMatchTransactionAttributeSource * @see NameMatchTransactionAttributeSource
* @see org.springframework.transaction.annotation.AnnotationTransactionAttributeSource * @see org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
*/ */
public void setTransactionAttributeSources(TransactionAttributeSource[] transactionAttributeSources) { public void setTransactionAttributeSources(TransactionAttributeSource... transactionAttributeSources) {
this.transactionAttributeSource = new CompositeTransactionAttributeSource(transactionAttributeSources); this.transactionAttributeSource = new CompositeTransactionAttributeSource(transactionAttributeSources);
} }

4
spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAttributeSourcePointcut.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2017 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.
@ -34,7 +34,7 @@ abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPoi
@Override @Override
public boolean matches(Method method, Class<?> targetClass) { public boolean matches(Method method, Class<?> targetClass) {
if (TransactionalProxy.class.isAssignableFrom(targetClass)) { if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false; return false;
} }
TransactionAttributeSource tas = getTransactionAttributeSource(); TransactionAttributeSource tas = getTransactionAttributeSource();

6
spring-tx/src/test/java/org/springframework/transaction/TransactionSupportTests.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2017 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.
@ -38,11 +38,11 @@ public class TransactionSupportTests {
PlatformTransactionManager tm = new TestTransactionManager(false, true); PlatformTransactionManager tm = new TestTransactionManager(false, true);
DefaultTransactionStatus status1 = (DefaultTransactionStatus) DefaultTransactionStatus status1 = (DefaultTransactionStatus)
tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_SUPPORTS)); tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_SUPPORTS));
assertTrue("Must not have transaction", status1.getTransaction() == null); assertFalse("Must not have transaction", status1.hasTransaction());
DefaultTransactionStatus status2 = (DefaultTransactionStatus) DefaultTransactionStatus status2 = (DefaultTransactionStatus)
tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED)); tm.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED));
assertTrue("Must have transaction", status2.getTransaction() != null); assertTrue("Must have transaction", status2.hasTransaction());
assertTrue("Must be new transaction", status2.isNewTransaction()); assertTrue("Must be new transaction", status2.isNewTransaction());
try { try {

14
spring-web/src/main/java/org/springframework/http/HttpHeaders.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 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.
@ -784,13 +784,13 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
/** /**
* Set the (new) entity tag of the body, as specified by the {@code ETag} header. * Set the (new) entity tag of the body, as specified by the {@code ETag} header.
*/ */
public void setETag(String eTag) { public void setETag(String etag) {
if (eTag != null) { if (etag != null) {
Assert.isTrue(eTag.startsWith("\"") || eTag.startsWith("W/"), Assert.isTrue(etag.startsWith("\"") || etag.startsWith("W/"),
"Invalid eTag, does not start with W/ or \""); "Invalid ETag: does not start with W/ or \"");
Assert.isTrue(eTag.endsWith("\""), "Invalid eTag, does not end with \""); Assert.isTrue(etag.endsWith("\""), "Invalid ETag: does not end with \"");
} }
set(ETAG, eTag); set(ETAG, etag);
} }
/** /**

17
spring-web/src/main/java/org/springframework/web/util/WebUtils.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 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.
@ -39,6 +39,7 @@ import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
/** /**
@ -153,16 +154,15 @@ public abstract class WebUtils {
String root = servletContext.getRealPath("/"); String root = servletContext.getRealPath("/");
if (root == null) { if (root == null) {
throw new IllegalStateException( throw new IllegalStateException(
"Cannot set web app root system property when WAR file is not expanded"); "Cannot set web app root system property when WAR file is not expanded");
} }
String param = servletContext.getInitParameter(WEB_APP_ROOT_KEY_PARAM); String param = servletContext.getInitParameter(WEB_APP_ROOT_KEY_PARAM);
String key = (param != null ? param : DEFAULT_WEB_APP_ROOT_KEY); String key = (param != null ? param : DEFAULT_WEB_APP_ROOT_KEY);
String oldValue = System.getProperty(key); String oldValue = System.getProperty(key);
if (oldValue != null && !StringUtils.pathEquals(oldValue, root)) { if (oldValue != null && !StringUtils.pathEquals(oldValue, root)) {
throw new IllegalStateException( throw new IllegalStateException("Web app root system property already set to different value: '" +
"Web app root system property already set to different value: '" + key + "' = [" + oldValue + "] instead of [" + root + "] - " +
key + "' = [" + oldValue + "] instead of [" + root + "] - " + "Choose unique values for the 'webAppRootKey' context-param in your web.xml files!");
"Choose unique values for the 'webAppRootKey' context-param in your web.xml files!");
} }
System.setProperty(key, root); System.setProperty(key, root);
servletContext.log("Set web app root system property: '" + key + "' = [" + root + "]"); servletContext.log("Set web app root system property: '" + key + "' = [" + root + "]");
@ -814,7 +814,7 @@ public abstract class WebUtils {
* Check if the request is a same-origin one, based on {@code Origin}, {@code Host}, * Check if the request is a same-origin one, based on {@code Origin}, {@code Host},
* {@code Forwarded} and {@code X-Forwarded-Host} headers. * {@code Forwarded} and {@code X-Forwarded-Host} headers.
* @return {@code true} if the request is a same-origin one, {@code false} in case * @return {@code true} if the request is a same-origin one, {@code false} in case
* of cross-origin request. * of cross-origin request
* @since 4.2 * @since 4.2
*/ */
public static boolean isSameOrigin(HttpRequest request) { public static boolean isSameOrigin(HttpRequest request) {
@ -837,7 +837,8 @@ public abstract class WebUtils {
} }
UriComponents actualUrl = urlBuilder.build(); UriComponents actualUrl = urlBuilder.build();
UriComponents originUrl = UriComponentsBuilder.fromOriginHeader(origin).build(); UriComponents originUrl = UriComponentsBuilder.fromOriginHeader(origin).build();
return (actualUrl.getHost().equals(originUrl.getHost()) && getPort(actualUrl) == getPort(originUrl)); return (ObjectUtils.nullSafeEquals(actualUrl.getHost(), originUrl.getHost()) &&
getPort(actualUrl) == getPort(originUrl));
} }
private static int getPort(UriComponents uri) { private static int getPort(UriComponents uri) {

67
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/BeanTypeNotPresentCondition.java

@ -1,67 +0,0 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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.springframework.web.servlet.config.annotation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.ConfigurationCondition;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.ObjectUtils;
/**
* A simple configuration condition that checks for the absence of any beans
* of a given type.
*
* @author Rossen Stoyanchev
* @since 4.1
*/
class BeanTypeNotPresentCondition implements ConfigurationCondition {
private static final Log logger =
LogFactory.getLog("org.springframework.web.servlet.config.annotation.ViewResolution");
private final Class<?> beanType;
BeanTypeNotPresentCondition(Class<?> beanType) {
this.beanType = beanType;
}
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.PARSE_CONFIGURATION;
}
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
ListableBeanFactory factory = context.getBeanFactory();
String[] names = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(factory, this.beanType, false, false);
if (ObjectUtils.isEmpty(names)) {
logger.debug("No bean of type [" + this.beanType + "]. Conditional configuration applies.");
return true;
}
else {
logger.debug("Found bean of type [" + this.beanType + "]. Conditional configuration does not apply.");
return false;
}
}
}

2
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/UrlTag.java

@ -197,7 +197,7 @@ public class UrlTag extends HtmlEscapingAwareTag implements ParamAware {
* 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
*/ */
private String createUrl() throws JspException { String createUrl() throws JspException {
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
HttpServletResponse response = (HttpServletResponse) pageContext.getResponse(); HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();

234
spring-webmvc/src/test/java/org/springframework/web/servlet/tags/UrlTagTests.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2016 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.
@ -16,7 +16,6 @@
package org.springframework.web.servlet.tags; package org.springframework.web.servlet.tags;
import java.lang.reflect.Method;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -30,7 +29,6 @@ import org.junit.Test;
import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockPageContext; import org.springframework.mock.web.test.MockPageContext;
import org.springframework.util.ReflectionUtils;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -44,13 +42,15 @@ public class UrlTagTests extends AbstractTagTests {
private MockPageContext context; private MockPageContext context;
@Before @Before
public void setUp() throws Exception { public void setup() throws Exception {
context = createPageContext(); context = createPageContext();
tag = new UrlTag(); tag = new UrlTag();
tag.setPageContext(context); tag.setPageContext(context);
} }
@Test @Test
public void paramSupport() { public void paramSupport() {
assertThat(tag, instanceOf(ParamAware.class)); assertThat(tag, instanceOf(ParamAware.class));
@ -66,7 +66,6 @@ public class UrlTagTests extends AbstractTagTests {
@Test @Test
public void doEndTag() throws JspException { public void doEndTag() throws JspException {
tag.setValue("url/path"); tag.setValue("url/path");
tag.doStartTag(); tag.doStartTag();
int action = tag.doEndTag(); int action = tag.doEndTag();
@ -77,12 +76,10 @@ public class UrlTagTests extends AbstractTagTests {
public void varDefaultScope() throws JspException { public void varDefaultScope() throws JspException {
tag.setValue("url/path"); tag.setValue("url/path");
tag.setVar("var"); tag.setVar("var");
tag.doStartTag(); tag.doStartTag();
tag.doEndTag(); tag.doEndTag();
assertEquals("url/path", context.getAttribute("var", assertEquals("url/path", context.getAttribute("var", PageContext.PAGE_SCOPE));
PageContext.PAGE_SCOPE));
} }
@Test @Test
@ -90,19 +87,16 @@ public class UrlTagTests extends AbstractTagTests {
tag.setValue("url/path"); tag.setValue("url/path");
tag.setVar("var"); tag.setVar("var");
tag.setScope("request"); tag.setScope("request");
tag.doStartTag(); tag.doStartTag();
tag.doEndTag(); tag.doEndTag();
assertEquals("url/path", context.getAttribute("var", assertEquals("url/path", context.getAttribute("var", PageContext.REQUEST_SCOPE));
PageContext.REQUEST_SCOPE));
} }
@Test @Test
public void setHtmlEscapeDefault() throws JspException { public void setHtmlEscapeDefault() throws JspException {
tag.setValue("url/path"); tag.setValue("url/path");
tag.setVar("var"); tag.setVar("var");
tag.doStartTag(); tag.doStartTag();
Param param = new Param(); Param param = new Param();
@ -116,9 +110,7 @@ public class UrlTagTests extends AbstractTagTests {
tag.addParam(param); tag.addParam(param);
tag.doEndTag(); tag.doEndTag();
assertEquals("url/path?n%20me=v%26l%3De&name=value2", context.getAttribute("var"));
assertEquals("url/path?n%20me=v%26l%3De&name=value2", context
.getAttribute("var"));
} }
@Test @Test
@ -140,9 +132,7 @@ public class UrlTagTests extends AbstractTagTests {
tag.addParam(param); tag.addParam(param);
tag.doEndTag(); tag.doEndTag();
assertEquals("url/path?n%20me=v%26l%3De&name=value2", context.getAttribute("var"));
assertEquals("url/path?n%20me=v%26l%3De&name=value2", context
.getAttribute("var"));
} }
@Test @Test
@ -150,7 +140,6 @@ public class UrlTagTests extends AbstractTagTests {
tag.setValue("url/path"); tag.setValue("url/path");
tag.setVar("var"); tag.setVar("var");
tag.setHtmlEscape(true); tag.setHtmlEscape(true);
tag.doStartTag(); tag.doStartTag();
Param param = new Param(); Param param = new Param();
@ -164,9 +153,7 @@ public class UrlTagTests extends AbstractTagTests {
tag.addParam(param); tag.addParam(param);
tag.doEndTag(); tag.doEndTag();
assertEquals("url/path?n%20me=v%26l%3De&amp;name=value2", context.getAttribute("var"));
assertEquals("url/path?n%20me=v%26l%3De&amp;name=value2", context
.getAttribute("var"));
} }
@Test @Test
@ -174,7 +161,6 @@ public class UrlTagTests extends AbstractTagTests {
tag.setValue("url/path"); tag.setValue("url/path");
tag.setVar("var"); tag.setVar("var");
tag.setJavaScriptEscape(true); tag.setJavaScriptEscape(true);
tag.doStartTag(); tag.doStartTag();
Param param = new Param(); Param param = new Param();
@ -188,9 +174,7 @@ public class UrlTagTests extends AbstractTagTests {
tag.addParam(param); tag.addParam(param);
tag.doEndTag(); tag.doEndTag();
assertEquals("url\\/path?n%20me=v%26l%3De&name=value2", context.getAttribute("var"));
assertEquals("url\\/path?n%20me=v%26l%3De&name=value2", context
.getAttribute("var"));
} }
@Test @Test
@ -199,7 +183,6 @@ public class UrlTagTests extends AbstractTagTests {
tag.setVar("var"); tag.setVar("var");
tag.setHtmlEscape(true); tag.setHtmlEscape(true);
tag.setJavaScriptEscape(true); tag.setJavaScriptEscape(true);
tag.doStartTag(); tag.doStartTag();
Param param = new Param(); Param param = new Param();
@ -213,25 +196,22 @@ public class UrlTagTests extends AbstractTagTests {
tag.addParam(param); tag.addParam(param);
tag.doEndTag(); tag.doEndTag();
assertEquals("url\\/path?n%20me=v%26l%3De&amp;name=value2", context.getAttribute("var"));
assertEquals("url\\/path?n%20me=v%26l%3De&amp;name=value2", context
.getAttribute("var"));
} }
@Test @Test
public void createQueryStringNoParams() throws JspException { public void createQueryStringNoParams() throws JspException {
List<Param> params = new LinkedList<Param>(); List<Param> params = new LinkedList<>();
Set<String> usedParams = new HashSet<String>(); Set<String> usedParams = new HashSet<>();
String queryString = tag.createQueryString(params, usedParams, true); String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("", queryString); assertEquals("", queryString);
} }
@Test @Test
public void createQueryStringOneParam() throws JspException { public void createQueryStringOneParam() throws JspException {
List<Param> params = new LinkedList<Param>(); List<Param> params = new LinkedList<>();
Set<String> usedParams = new HashSet<String>(); Set<String> usedParams = new HashSet<>();
Param param = new Param(); Param param = new Param();
param.setName("name"); param.setName("name");
@ -239,15 +219,13 @@ public class UrlTagTests extends AbstractTagTests {
params.add(param); params.add(param);
String queryString = tag.createQueryString(params, usedParams, true); String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("?name=value", queryString); assertEquals("?name=value", queryString);
} }
@Test @Test
public void createQueryStringOneParamForExsistingQueryString() public void createQueryStringOneParamForExsistingQueryString() throws JspException {
throws JspException { List<Param> params = new LinkedList<>();
List<Param> params = new LinkedList<Param>(); Set<String> usedParams = new HashSet<>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param(); Param param = new Param();
param.setName("name"); param.setName("name");
@ -255,14 +233,13 @@ public class UrlTagTests extends AbstractTagTests {
params.add(param); params.add(param);
String queryString = tag.createQueryString(params, usedParams, false); String queryString = tag.createQueryString(params, usedParams, false);
assertEquals("&name=value", queryString); assertEquals("&name=value", queryString);
} }
@Test @Test
public void createQueryStringOneParamEmptyValue() throws JspException { public void createQueryStringOneParamEmptyValue() throws JspException {
List<Param> params = new LinkedList<Param>(); List<Param> params = new LinkedList<>();
Set<String> usedParams = new HashSet<String>(); Set<String> usedParams = new HashSet<>();
Param param = new Param(); Param param = new Param();
param.setName("name"); param.setName("name");
@ -270,14 +247,13 @@ public class UrlTagTests extends AbstractTagTests {
params.add(param); params.add(param);
String queryString = tag.createQueryString(params, usedParams, true); String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("?name=", queryString); assertEquals("?name=", queryString);
} }
@Test @Test
public void createQueryStringOneParamNullValue() throws JspException { public void createQueryStringOneParamNullValue() throws JspException {
List<Param> params = new LinkedList<Param>(); List<Param> params = new LinkedList<>();
Set<String> usedParams = new HashSet<String>(); Set<String> usedParams = new HashSet<>();
Param param = new Param(); Param param = new Param();
param.setName("name"); param.setName("name");
@ -285,31 +261,28 @@ public class UrlTagTests extends AbstractTagTests {
params.add(param); params.add(param);
String queryString = tag.createQueryString(params, usedParams, true); String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("?name", queryString); assertEquals("?name", queryString);
} }
@Test @Test
public void createQueryStringOneParamAlreadyUsed() throws JspException { public void createQueryStringOneParamAlreadyUsed() throws JspException {
List<Param> params = new LinkedList<Param>(); List<Param> params = new LinkedList<>();
Set<String> usedParams = new HashSet<String>(); Set<String> usedParams = new HashSet<>();
Param param = new Param(); Param param = new Param();
param.setName("name"); param.setName("name");
param.setValue("value"); param.setValue("value");
params.add(param); params.add(param);
usedParams.add("name"); usedParams.add("name");
String queryString = tag.createQueryString(params, usedParams, true); String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("", queryString); assertEquals("", queryString);
} }
@Test @Test
public void createQueryStringTwoParams() throws JspException { public void createQueryStringTwoParams() throws JspException {
List<Param> params = new LinkedList<Param>(); List<Param> params = new LinkedList<>();
Set<String> usedParams = new HashSet<String>(); Set<String> usedParams = new HashSet<>();
Param param = new Param(); Param param = new Param();
param.setName("name"); param.setName("name");
@ -322,14 +295,13 @@ public class UrlTagTests extends AbstractTagTests {
params.add(param); params.add(param);
String queryString = tag.createQueryString(params, usedParams, true); String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("?name=value&name=value2", queryString); assertEquals("?name=value&name=value2", queryString);
} }
@Test @Test
public void createQueryStringUrlEncoding() throws JspException { public void createQueryStringUrlEncoding() throws JspException {
List<Param> params = new LinkedList<Param>(); List<Param> params = new LinkedList<>();
Set<String> usedParams = new HashSet<String>(); Set<String> usedParams = new HashSet<>();
Param param = new Param(); Param param = new Param();
param.setName("n me"); param.setName("n me");
@ -342,14 +314,13 @@ public class UrlTagTests extends AbstractTagTests {
params.add(param); params.add(param);
String queryString = tag.createQueryString(params, usedParams, true); String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("?n%20me=v%26l%3De&name=value2", queryString); assertEquals("?n%20me=v%26l%3De&name=value2", queryString);
} }
@Test @Test
public void createQueryStringParamNullName() throws JspException { public void createQueryStringParamNullName() throws JspException {
List<Param> params = new LinkedList<Param>(); List<Param> params = new LinkedList<>();
Set<String> usedParams = new HashSet<String>(); Set<String> usedParams = new HashSet<>();
Param param = new Param(); Param param = new Param();
param.setName(null); param.setName(null);
@ -357,14 +328,13 @@ public class UrlTagTests extends AbstractTagTests {
params.add(param); params.add(param);
String queryString = tag.createQueryString(params, usedParams, true); String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("", queryString); assertEquals("", queryString);
} }
@Test @Test
public void createQueryStringParamEmptyName() throws JspException { public void createQueryStringParamEmptyName() throws JspException {
List<Param> params = new LinkedList<Param>(); List<Param> params = new LinkedList<>();
Set<String> usedParams = new HashSet<String>(); Set<String> usedParams = new HashSet<>();
Param param = new Param(); Param param = new Param();
param.setName(""); param.setName("");
@ -372,78 +342,65 @@ public class UrlTagTests extends AbstractTagTests {
params.add(param); params.add(param);
String queryString = tag.createQueryString(params, usedParams, true); String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("", queryString); assertEquals("", queryString);
} }
@Test @Test
public void replaceUriTemplateParamsNoParams() throws JspException { public void replaceUriTemplateParamsNoParams() throws JspException {
List<Param> params = new LinkedList<Param>(); List<Param> params = new LinkedList<>();
Set<String> usedParams = new HashSet<String>(); Set<String> usedParams = new HashSet<>();
String uri = tag.replaceUriTemplateParams("url/path", params,
usedParams);
String uri = tag.replaceUriTemplateParams("url/path", params, usedParams);
assertEquals("url/path", uri); assertEquals("url/path", uri);
assertEquals(0, usedParams.size()); assertEquals(0, usedParams.size());
} }
@Test @Test
public void replaceUriTemplateParamsTemplateWithoutParamMatch() public void replaceUriTemplateParamsTemplateWithoutParamMatch() throws JspException {
throws JspException { List<Param> params = new LinkedList<>();
List<Param> params = new LinkedList<Param>(); Set<String> usedParams = new HashSet<>();
Set<String> usedParams = new HashSet<String>();
String uri = tag.replaceUriTemplateParams("url/{path}", params,
usedParams);
String uri = tag.replaceUriTemplateParams("url/{path}", params, usedParams);
assertEquals("url/{path}", uri); assertEquals("url/{path}", uri);
assertEquals(0, usedParams.size()); assertEquals(0, usedParams.size());
} }
@Test @Test
public void replaceUriTemplateParamsTemplateWithParamMatch() public void replaceUriTemplateParamsTemplateWithParamMatch() throws JspException {
throws JspException { List<Param> params = new LinkedList<>();
List<Param> params = new LinkedList<Param>(); Set<String> usedParams = new HashSet<>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param(); Param param = new Param();
param.setName("name"); param.setName("name");
param.setValue("value"); param.setValue("value");
params.add(param); params.add(param);
String uri = tag.replaceUriTemplateParams("url/{name}", params, String uri = tag.replaceUriTemplateParams("url/{name}", params, usedParams);
usedParams);
assertEquals("url/value", uri); assertEquals("url/value", uri);
assertEquals(1, usedParams.size()); assertEquals(1, usedParams.size());
assertTrue(usedParams.contains("name")); assertTrue(usedParams.contains("name"));
} }
@Test @Test
public void replaceUriTemplateParamsTemplateWithParamMatchNamePreEncoding() public void replaceUriTemplateParamsTemplateWithParamMatchNamePreEncoding() throws JspException {
throws JspException { List<Param> params = new LinkedList<>();
List<Param> params = new LinkedList<Param>(); Set<String> usedParams = new HashSet<>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param(); Param param = new Param();
param.setName("n me"); param.setName("n me");
param.setValue("value"); param.setValue("value");
params.add(param); params.add(param);
String uri = tag.replaceUriTemplateParams("url/{n me}", params, String uri = tag.replaceUriTemplateParams("url/{n me}", params, usedParams);
usedParams);
assertEquals("url/value", uri); assertEquals("url/value", uri);
assertEquals(1, usedParams.size()); assertEquals(1, usedParams.size());
assertTrue(usedParams.contains("n me")); assertTrue(usedParams.contains("n me"));
} }
@Test @Test
public void replaceUriTemplateParamsTemplateWithParamMatchValueEncoded() public void replaceUriTemplateParamsTemplateWithParamMatchValueEncoded() throws JspException {
throws JspException { List<Param> params = new LinkedList<>();
List<Param> params = new LinkedList<Param>(); Set<String> usedParams = new HashSet<>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param(); Param param = new Param();
param.setName("name"); param.setName("name");
@ -458,13 +415,10 @@ public class UrlTagTests extends AbstractTagTests {
assertTrue(usedParams.contains("name")); assertTrue(usedParams.contains("name"));
} }
// SPR-11401 @Test // SPR-11401
public void replaceUriTemplateParamsTemplateWithPathSegment() throws JspException {
@Test List<Param> params = new LinkedList<>();
public void replaceUriTemplateParamsTemplateWithPathSegment() Set<String> usedParams = new HashSet<>();
throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param(); Param param = new Param();
param.setName("name"); param.setName("name");
@ -479,10 +433,9 @@ public class UrlTagTests extends AbstractTagTests {
} }
@Test @Test
public void replaceUriTemplateParamsTemplateWithPath() public void replaceUriTemplateParamsTemplateWithPath() throws JspException {
throws JspException { List<Param> params = new LinkedList<>();
List<Param> params = new LinkedList<Param>(); Set<String> usedParams = new HashSet<>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param(); Param param = new Param();
param.setName("name"); param.setName("name");
@ -490,7 +443,6 @@ public class UrlTagTests extends AbstractTagTests {
params.add(param); params.add(param);
String uri = tag.replaceUriTemplateParams("url/{name}", params, usedParams); String uri = tag.replaceUriTemplateParams("url/{name}", params, usedParams);
assertEquals("url/my/Id", uri); assertEquals("url/my/Id", uri);
assertEquals(1, usedParams.size()); assertEquals(1, usedParams.size());
assertTrue(usedParams.contains("name")); assertTrue(usedParams.contains("name"));
@ -499,89 +451,71 @@ public class UrlTagTests extends AbstractTagTests {
@Test @Test
public void createUrlRemoteServer() throws JspException { public void createUrlRemoteServer() throws JspException {
tag.setValue("http://www.springframework.org/"); tag.setValue("http://www.springframework.org/");
tag.doStartTag(); tag.doStartTag();
// String uri = tag.createUrl(); String uri = tag.createUrl();
String uri = invokeCreateUrl(tag);
assertEquals("http://www.springframework.org/", uri); assertEquals("http://www.springframework.org/", uri);
} }
@Test @Test
public void createUrlRelative() throws JspException { public void createUrlRelative() throws JspException {
tag.setValue("url/path"); tag.setValue("url/path");
tag.doStartTag(); tag.doStartTag();
String uri = invokeCreateUrl(tag); String uri = tag.createUrl();
assertEquals("url/path", uri); assertEquals("url/path", uri);
} }
@Test @Test
public void createUrlLocalContext() throws JspException { public void createUrlLocalContext() throws JspException {
((MockHttpServletRequest) context.getRequest()) ((MockHttpServletRequest) context.getRequest()).setContextPath("/app-context");
.setContextPath("/app-context");
tag.setValue("/url/path"); tag.setValue("/url/path");
tag.doStartTag(); tag.doStartTag();
String uri = invokeCreateUrl(tag); String uri = tag.createUrl();
assertEquals("/app-context/url/path", uri); assertEquals("/app-context/url/path", uri);
} }
@Test @Test
public void createUrlRemoteContext() throws JspException { public void createUrlRemoteContext() throws JspException {
((MockHttpServletRequest) context.getRequest()) ((MockHttpServletRequest) context.getRequest()).setContextPath("/app-context");
.setContextPath("/app-context");
tag.setValue("/url/path"); tag.setValue("/url/path");
tag.setContext("some-other-context"); tag.setContext("some-other-context");
tag.doStartTag(); tag.doStartTag();
String uri = invokeCreateUrl(tag); String uri = tag.createUrl();
assertEquals("/some-other-context/url/path", uri); assertEquals("/some-other-context/url/path", uri);
} }
@Test @Test
public void createUrlRemoteContextWithSlash() throws JspException { public void createUrlRemoteContextWithSlash() throws JspException {
((MockHttpServletRequest) context.getRequest()) ((MockHttpServletRequest) context.getRequest()).setContextPath("/app-context");
.setContextPath("/app-context");
tag.setValue("/url/path"); tag.setValue("/url/path");
tag.setContext("/some-other-context"); tag.setContext("/some-other-context");
tag.doStartTag(); tag.doStartTag();
String uri = invokeCreateUrl(tag); String uri = tag.createUrl();
assertEquals("/some-other-context/url/path", uri); assertEquals("/some-other-context/url/path", uri);
} }
@Test @Test
public void createUrlRemoteContextSingleSlash() throws JspException { public void createUrlRemoteContextSingleSlash() throws JspException {
((MockHttpServletRequest) context.getRequest()) ((MockHttpServletRequest) context.getRequest()).setContextPath("/app-context");
.setContextPath("/app-context");
tag.setValue("/url/path"); tag.setValue("/url/path");
tag.setContext("/"); tag.setContext("/");
tag.doStartTag(); tag.doStartTag();
String uri = invokeCreateUrl(tag); String uri = tag.createUrl();
assertEquals("/url/path", uri); assertEquals("/url/path", uri);
} }
@Test @Test
public void createUrlWithParams() throws JspException { public void createUrlWithParams() throws JspException {
tag.setValue("url/path"); tag.setValue("url/path");
tag.doStartTag(); tag.doStartTag();
Param param = new Param(); Param param = new Param();
@ -594,15 +528,13 @@ public class UrlTagTests extends AbstractTagTests {
param.setValue("v lue"); param.setValue("v lue");
tag.addParam(param); tag.addParam(param);
String uri = invokeCreateUrl(tag); String uri = tag.createUrl();
assertEquals("url/path?name=value&n%20me=v%20lue", uri); assertEquals("url/path?name=value&n%20me=v%20lue", uri);
} }
@Test @Test
public void createUrlWithTemplateParams() throws JspException { public void createUrlWithTemplateParams() throws JspException {
tag.setValue("url/{name}"); tag.setValue("url/{name}");
tag.doStartTag(); tag.doStartTag();
Param param = new Param(); Param param = new Param();
@ -615,16 +547,13 @@ public class UrlTagTests extends AbstractTagTests {
param.setValue("v lue"); param.setValue("v lue");
tag.addParam(param); tag.addParam(param);
String uri = invokeCreateUrl(tag); String uri = tag.createUrl();
assertEquals("url/value?n%20me=v%20lue", uri); assertEquals("url/value?n%20me=v%20lue", uri);
} }
@Test @Test
public void createUrlWithParamAndExsistingQueryString() public void createUrlWithParamAndExistingQueryString() throws JspException {
throws JspException {
tag.setValue("url/path?foo=bar"); tag.setValue("url/path?foo=bar");
tag.doStartTag(); tag.doStartTag();
Param param = new Param(); Param param = new Param();
@ -632,29 +561,8 @@ public class UrlTagTests extends AbstractTagTests {
param.setValue("value"); param.setValue("value");
tag.addParam(param); tag.addParam(param);
String uri = invokeCreateUrl(tag); String uri = tag.createUrl();
assertEquals("url/path?foo=bar&name=value", uri); assertEquals("url/path?foo=bar&name=value", uri);
} }
@Test
public void jspWriterOutput() {
// TODO assert that the output to the JspWriter is the expected output
}
@Test
public void servletRepsonseEncodeUrl() {
// TODO assert that HttpServletResponse.encodeURL(String) is invoked for
// non absolute urls
}
// support methods
private String invokeCreateUrl(UrlTag tag) {
Method createUrl = ReflectionUtils.findMethod(tag.getClass(),
"createUrl");
ReflectionUtils.makeAccessible(createUrl);
return (String) ReflectionUtils.invokeMethod(createUrl, tag);
}
} }

28
src/test/java/com/foo/ComponentBeanDefinitionParser.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2017 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.
@ -18,32 +18,30 @@ package com.foo;
import java.util.List; import java.util.List;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.CollectionUtils;
import org.springframework.util.xml.DomUtils; import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
public class ComponentBeanDefinitionParser extends AbstractBeanDefinitionParser { public class ComponentBeanDefinitionParser extends AbstractBeanDefinitionParser {
@Override @Override
protected AbstractBeanDefinition parseInternal(Element element, protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
ParserContext parserContext) {
return parseComponentElement(element); return parseComponentElement(element);
} }
private static AbstractBeanDefinition parseComponentElement(Element element) { private static AbstractBeanDefinition parseComponentElement(Element element) {
BeanDefinitionBuilder factory = BeanDefinitionBuilder BeanDefinitionBuilder factory = BeanDefinitionBuilder.rootBeanDefinition(ComponentFactoryBean.class);
.rootBeanDefinition(ComponentFactoryBean.class);
factory.addPropertyValue("parent", parseComponent(element)); factory.addPropertyValue("parent", parseComponent(element));
List<Element> childElements = DomUtils.getChildElementsByTagName( List<Element> childElements = DomUtils.getChildElementsByTagName(element, "component");
element, "component"); if (!CollectionUtils.isEmpty(childElements)) {
if (childElements != null && childElements.size() > 0) {
parseChildComponents(childElements, factory); parseChildComponents(childElements, factory);
} }
@ -51,19 +49,17 @@ public class ComponentBeanDefinitionParser extends AbstractBeanDefinitionParser
} }
private static BeanDefinition parseComponent(Element element) { private static BeanDefinition parseComponent(Element element) {
BeanDefinitionBuilder component = BeanDefinitionBuilder BeanDefinitionBuilder component = BeanDefinitionBuilder.rootBeanDefinition(Component.class);
.rootBeanDefinition(Component.class);
component.addPropertyValue("name", element.getAttribute("name")); component.addPropertyValue("name", element.getAttribute("name"));
return component.getBeanDefinition(); return component.getBeanDefinition();
} }
private static void parseChildComponents(List<Element> childElements, private static void parseChildComponents(List<Element> childElements, BeanDefinitionBuilder factory) {
BeanDefinitionBuilder factory) { ManagedList<BeanDefinition> children = new ManagedList<BeanDefinition>(childElements.size());
ManagedList<BeanDefinition> children = new ManagedList<BeanDefinition>(
childElements.size());
for (Element element : childElements) { for (Element element : childElements) {
children.add(parseComponentElement(element)); children.add(parseComponentElement(element));
} }
factory.addPropertyValue("children", children); factory.addPropertyValue("children", children);
} }
} }

Loading…
Cancel
Save