diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/YamlProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/YamlProcessor.java
index 1b4e2bdeea..6d929f2ba5 100644
--- a/spring-beans/src/main/java/org/springframework/beans/factory/config/YamlProcessor.java
+++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/YamlProcessor.java
@@ -432,8 +432,7 @@ public abstract class YamlProcessor {
/**
* {@link Constructor} that supports filtering of unsupported types.
*
If an unsupported type is encountered in a YAML document, an
- * {@link IllegalStateException} will be thrown from {@link #getClassForName(String)}.
- * @since 5.1.16
+ * {@link IllegalStateException} will be thrown from {@link #getClassForName}.
*/
private class FilteringConstructor extends Constructor {
@@ -441,7 +440,6 @@ public abstract class YamlProcessor {
super(loaderOptions);
}
-
@Override
protected Class> getClassForName(String name) throws ClassNotFoundException {
Assert.state(YamlProcessor.this.supportedTypes.contains(name),
diff --git a/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
index 6b4e5b6a4f..933fc7359c 100644
--- a/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
+++ b/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -79,6 +79,7 @@ import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
+import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
@@ -836,7 +837,7 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
// Publish early application events now that we finally have a multicaster...
Set earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
- if (earlyEventsToProcess != null) {
+ if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
diff --git a/spring-core/src/main/java/org/springframework/core/env/AbstractPropertyResolver.java b/spring-core/src/main/java/org/springframework/core/env/AbstractPropertyResolver.java
index d5f7fd1110..c3f29e106a 100644
--- a/spring-core/src/main/java/org/springframework/core/env/AbstractPropertyResolver.java
+++ b/spring-core/src/main/java/org/springframework/core/env/AbstractPropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -223,6 +223,9 @@ public abstract class AbstractPropertyResolver implements ConfigurablePropertyRe
* @see #setIgnoreUnresolvableNestedPlaceholders
*/
protected String resolveNestedPlaceholders(String value) {
+ if (value.isEmpty()) {
+ return value;
+ }
return (this.ignoreUnresolvableNestedPlaceholders ?
resolvePlaceholders(value) : resolveRequiredPlaceholders(value));
}
diff --git a/spring-core/src/main/java/org/springframework/core/env/EnumerablePropertySource.java b/spring-core/src/main/java/org/springframework/core/env/EnumerablePropertySource.java
index 0ef6ce4a77..2c1386d312 100644
--- a/spring-core/src/main/java/org/springframework/core/env/EnumerablePropertySource.java
+++ b/spring-core/src/main/java/org/springframework/core/env/EnumerablePropertySource.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -44,10 +44,20 @@ import org.springframework.util.ObjectUtils;
*/
public abstract class EnumerablePropertySource extends PropertySource {
+ /**
+ * Create a new {@code EnumerablePropertySource} with the given name and source object.
+ * @param name the associated name
+ * @param source the source object
+ */
public EnumerablePropertySource(String name, T source) {
super(name, source);
}
+ /**
+ * Create a new {@code EnumerablePropertySource} with the given name and with a new
+ * {@code Object} instance as the underlying source.
+ * @param name the associated name
+ */
protected EnumerablePropertySource(String name) {
super(name);
}
diff --git a/spring-core/src/main/java/org/springframework/core/env/MapPropertySource.java b/spring-core/src/main/java/org/springframework/core/env/MapPropertySource.java
index d08c6fb278..36597a5b24 100644
--- a/spring-core/src/main/java/org/springframework/core/env/MapPropertySource.java
+++ b/spring-core/src/main/java/org/springframework/core/env/MapPropertySource.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -23,6 +23,8 @@ import org.springframework.util.StringUtils;
/**
* {@link PropertySource} that reads keys and values from a {@code Map} object.
+ * The underlying map should not contain any {@code null} values in order to
+ * comply with {@link #getProperty} and {@link #containsProperty} semantics.
*
* @author Chris Beams
* @author Juergen Hoeller
@@ -31,6 +33,12 @@ import org.springframework.util.StringUtils;
*/
public class MapPropertySource extends EnumerablePropertySource> {
+ /**
+ * Create a new {@code MapPropertySource} with the given name and {@code Map}.
+ * @param name the associated name
+ * @param source the Map source (without {@code null} values in order to get
+ * consistent {@link #getProperty} and {@link #containsProperty} behavior)
+ */
public MapPropertySource(String name, Map source) {
super(name, source);
}
diff --git a/spring-core/src/main/java/org/springframework/core/env/PropertyResolver.java b/spring-core/src/main/java/org/springframework/core/env/PropertyResolver.java
index 5554463c44..173a1a3378 100644
--- a/spring-core/src/main/java/org/springframework/core/env/PropertyResolver.java
+++ b/spring-core/src/main/java/org/springframework/core/env/PropertyResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -98,7 +98,6 @@ public interface PropertyResolver {
* @return the resolved String (never {@code null})
* @throws IllegalArgumentException if given text is {@code null}
* @see #resolveRequiredPlaceholders
- * @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders(String)
*/
String resolvePlaceholders(String text);
@@ -109,7 +108,6 @@ public interface PropertyResolver {
* @return the resolved String (never {@code null})
* @throws IllegalArgumentException if given text is {@code null}
* or if any placeholders are unresolvable
- * @see org.springframework.util.SystemPropertyUtils#resolvePlaceholders(String, boolean)
*/
String resolveRequiredPlaceholders(String text) throws IllegalArgumentException;
diff --git a/spring-core/src/main/java/org/springframework/core/env/PropertySource.java b/spring-core/src/main/java/org/springframework/core/env/PropertySource.java
index 2cb6313064..c8a1da6bb8 100644
--- a/spring-core/src/main/java/org/springframework/core/env/PropertySource.java
+++ b/spring-core/src/main/java/org/springframework/core/env/PropertySource.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -68,6 +68,8 @@ public abstract class PropertySource {
/**
* Create a new {@code PropertySource} with the given name and source object.
+ * @param name the associated name
+ * @param source the source object
*/
public PropertySource(String name, T source) {
Assert.hasText(name, "Property source name must contain at least one character");
diff --git a/spring-core/src/main/java/org/springframework/util/CollectionUtils.java b/spring-core/src/main/java/org/springframework/util/CollectionUtils.java
index 1cd16243fd..1ec0510467 100644
--- a/spring-core/src/main/java/org/springframework/util/CollectionUtils.java
+++ b/spring-core/src/main/java/org/springframework/util/CollectionUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -16,7 +16,6 @@
package org.springframework.util;
-import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -24,7 +23,6 @@ import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -412,25 +410,28 @@ public abstract class CollectionUtils {
/**
* Adapt a {@code Map>} to an {@code MultiValueMap}.
- * @param map the original map
- * @return the multi-value map
+ * @param targetMap the original map
+ * @return the adapted multi-value map (wrapping the original map)
* @since 3.1
*/
- public static MultiValueMap toMultiValueMap(Map> map) {
- return new MultiValueMapAdapter<>(map);
+ public static MultiValueMap toMultiValueMap(Map> targetMap) {
+ Assert.notNull(targetMap, "'targetMap' must not be null");
+ return new MultiValueMapAdapter<>(targetMap);
}
/**
* Return an unmodifiable view of the specified multi-value map.
- * @param map the map for which an unmodifiable view is to be returned.
- * @return an unmodifiable view of the specified multi-value map.
+ * @param targetMap the map for which an unmodifiable view is to be returned.
+ * @return an unmodifiable view of the specified multi-value map
* @since 3.1
*/
@SuppressWarnings("unchecked")
- public static MultiValueMap unmodifiableMultiValueMap(MultiValueMap extends K, ? extends V> map) {
- Assert.notNull(map, "'map' must not be null");
- Map> result = new LinkedHashMap<>(map.size());
- map.forEach((key, value) -> {
+ public static MultiValueMap unmodifiableMultiValueMap(
+ MultiValueMap extends K, ? extends V> targetMap) {
+
+ Assert.notNull(targetMap, "'targetMap' must not be null");
+ Map> result = new LinkedHashMap<>(targetMap.size());
+ targetMap.forEach((key, value) -> {
List extends V> values = Collections.unmodifiableList(value);
result.put(key, (List) values);
});
@@ -467,141 +468,4 @@ public abstract class CollectionUtils {
}
- /**
- * Adapts a Map to the MultiValueMap contract.
- */
- @SuppressWarnings("serial")
- private static class MultiValueMapAdapter implements MultiValueMap, Serializable {
-
- private final Map> map;
-
- public MultiValueMapAdapter(Map> map) {
- Assert.notNull(map, "'map' must not be null");
- this.map = map;
- }
-
- @Override
- @Nullable
- public V getFirst(K key) {
- List values = this.map.get(key);
- return (values != null ? values.get(0) : null);
- }
-
- @Override
- public void add(K key, @Nullable V value) {
- List values = this.map.computeIfAbsent(key, k -> new LinkedList<>());
- values.add(value);
- }
-
- @Override
- public void addAll(K key, List extends V> values) {
- List currentValues = this.map.computeIfAbsent(key, k -> new LinkedList<>());
- currentValues.addAll(values);
- }
-
- @Override
- public void addAll(MultiValueMap values) {
- for (Entry> entry : values.entrySet()) {
- addAll(entry.getKey(), entry.getValue());
- }
- }
-
- @Override
- public void set(K key, @Nullable V value) {
- List values = new LinkedList<>();
- values.add(value);
- this.map.put(key, values);
- }
-
- @Override
- public void setAll(Map values) {
- values.forEach(this::set);
- }
-
- @Override
- public Map toSingleValueMap() {
- LinkedHashMap singleValueMap = new LinkedHashMap<>(this.map.size());
- this.map.forEach((key, value) -> singleValueMap.put(key, value.get(0)));
- return singleValueMap;
- }
-
- @Override
- public int size() {
- return this.map.size();
- }
-
- @Override
- public boolean isEmpty() {
- return this.map.isEmpty();
- }
-
- @Override
- public boolean containsKey(Object key) {
- return this.map.containsKey(key);
- }
-
- @Override
- public boolean containsValue(Object value) {
- return this.map.containsValue(value);
- }
-
- @Override
- public List get(Object key) {
- return this.map.get(key);
- }
-
- @Override
- public List put(K key, List value) {
- return this.map.put(key, value);
- }
-
- @Override
- public List remove(Object key) {
- return this.map.remove(key);
- }
-
- @Override
- public void putAll(Map extends K, ? extends List> map) {
- this.map.putAll(map);
- }
-
- @Override
- public void clear() {
- this.map.clear();
- }
-
- @Override
- public Set keySet() {
- return this.map.keySet();
- }
-
- @Override
- public Collection> values() {
- return this.map.values();
- }
-
- @Override
- public Set>> entrySet() {
- return this.map.entrySet();
- }
-
- @Override
- public boolean equals(@Nullable Object other) {
- if (this == other) {
- return true;
- }
- return this.map.equals(other);
- }
-
- @Override
- public int hashCode() {
- return this.map.hashCode();
- }
-
- @Override
- public String toString() {
- return this.map.toString();
- }
- }
-
}
diff --git a/spring-core/src/main/java/org/springframework/util/LinkedCaseInsensitiveMap.java b/spring-core/src/main/java/org/springframework/util/LinkedCaseInsensitiveMap.java
index 1b70fa5550..a7e24a7620 100644
--- a/spring-core/src/main/java/org/springframework/util/LinkedCaseInsensitiveMap.java
+++ b/spring-core/src/main/java/org/springframework/util/LinkedCaseInsensitiveMap.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -273,8 +273,8 @@ public class LinkedCaseInsensitiveMap implements Map, Serializable
}
@Override
- public boolean equals(@Nullable Object obj) {
- return this.targetMap.equals(obj);
+ public boolean equals(@Nullable Object other) {
+ return (this == other || this.targetMap.equals(other));
}
@Override
diff --git a/spring-core/src/main/java/org/springframework/util/LinkedMultiValueMap.java b/spring-core/src/main/java/org/springframework/util/LinkedMultiValueMap.java
index c3edb97971..00ef6b4d6b 100644
--- a/spring-core/src/main/java/org/springframework/util/LinkedMultiValueMap.java
+++ b/spring-core/src/main/java/org/springframework/util/LinkedMultiValueMap.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -17,14 +17,10 @@
package org.springframework.util;
import java.io.Serializable;
-import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-
-import org.springframework.lang.Nullable;
/**
* Simple implementation of {@link MultiValueMap} that wraps a {@link LinkedHashMap},
@@ -39,18 +35,16 @@ import org.springframework.lang.Nullable;
* @param the key type
* @param the value element type
*/
-public class LinkedMultiValueMap implements MultiValueMap, Serializable, Cloneable {
+public class LinkedMultiValueMap extends MultiValueMapAdapter implements Serializable, Cloneable {
private static final long serialVersionUID = 3801124242820219131L;
- private final Map> targetMap;
-
/**
* Create a new LinkedMultiValueMap that wraps a {@link LinkedHashMap}.
*/
public LinkedMultiValueMap() {
- this.targetMap = new LinkedHashMap<>();
+ super(new LinkedHashMap<>());
}
/**
@@ -59,7 +53,7 @@ public class LinkedMultiValueMap implements MultiValueMap, Serializa
* @param initialCapacity the initial capacity
*/
public LinkedMultiValueMap(int initialCapacity) {
- this.targetMap = new LinkedHashMap<>(initialCapacity);
+ super(new LinkedHashMap<>(initialCapacity));
}
/**
@@ -71,125 +65,7 @@ public class LinkedMultiValueMap implements MultiValueMap, Serializa
* @see #deepCopy()
*/
public LinkedMultiValueMap(Map> otherMap) {
- this.targetMap = new LinkedHashMap<>(otherMap);
- }
-
-
- // MultiValueMap implementation
-
- @Override
- @Nullable
- public V getFirst(K key) {
- List values = this.targetMap.get(key);
- return (values != null && !values.isEmpty() ? values.get(0) : null);
- }
-
- @Override
- public void add(K key, @Nullable V value) {
- List values = this.targetMap.computeIfAbsent(key, k -> new LinkedList<>());
- values.add(value);
- }
-
- @Override
- public void addAll(K key, List extends V> values) {
- List currentValues = this.targetMap.computeIfAbsent(key, k -> new LinkedList<>());
- currentValues.addAll(values);
- }
-
- @Override
- public void addAll(MultiValueMap values) {
- for (Entry> entry : values.entrySet()) {
- addAll(entry.getKey(), entry.getValue());
- }
- }
-
- @Override
- public void set(K key, @Nullable V value) {
- List values = new LinkedList<>();
- values.add(value);
- this.targetMap.put(key, values);
- }
-
- @Override
- public void setAll(Map values) {
- values.forEach(this::set);
- }
-
- @Override
- public Map toSingleValueMap() {
- LinkedHashMap singleValueMap = new LinkedHashMap<>(this.targetMap.size());
- this.targetMap.forEach((key, values) -> {
- if (values != null && !values.isEmpty()) {
- singleValueMap.put(key, values.get(0));
- }
- });
- return singleValueMap;
- }
-
-
- // Map implementation
-
- @Override
- public int size() {
- return this.targetMap.size();
- }
-
- @Override
- public boolean isEmpty() {
- return this.targetMap.isEmpty();
- }
-
- @Override
- public boolean containsKey(Object key) {
- return this.targetMap.containsKey(key);
- }
-
- @Override
- public boolean containsValue(Object value) {
- return this.targetMap.containsValue(value);
- }
-
- @Override
- @Nullable
- public List get(Object key) {
- return this.targetMap.get(key);
- }
-
- @Override
- @Nullable
- public List put(K key, List value) {
- return this.targetMap.put(key, value);
- }
-
- @Override
- @Nullable
- public List remove(Object key) {
- return this.targetMap.remove(key);
- }
-
- @Override
- public void putAll(Map extends K, ? extends List> map) {
- this.targetMap.putAll(map);
- }
-
- @Override
- public void clear() {
- this.targetMap.clear();
- }
-
- @Override
- public Set keySet() {
- return this.targetMap.keySet();
- }
-
- @Override
- public Collection> values() {
- return this.targetMap.values();
- }
-
- @Override
- public Set>> entrySet() {
- return this.targetMap.entrySet();
+ super(new LinkedHashMap<>(otherMap));
}
@@ -203,8 +79,8 @@ public class LinkedMultiValueMap implements MultiValueMap, Serializa
* @see #clone()
*/
public LinkedMultiValueMap deepCopy() {
- LinkedMultiValueMap copy = new LinkedMultiValueMap<>(this.targetMap.size());
- this.targetMap.forEach((key, value) -> copy.put(key, new LinkedList<>(value)));
+ LinkedMultiValueMap copy = new LinkedMultiValueMap<>(size());
+ forEach((key, values) -> copy.put(key, new LinkedList<>(values)));
return copy;
}
@@ -224,19 +100,4 @@ public class LinkedMultiValueMap implements MultiValueMap, Serializa
return new LinkedMultiValueMap<>(this);
}
- @Override
- public boolean equals(@Nullable Object obj) {
- return this.targetMap.equals(obj);
- }
-
- @Override
- public int hashCode() {
- return this.targetMap.hashCode();
- }
-
- @Override
- public String toString() {
- return this.targetMap.toString();
- }
-
}
diff --git a/spring-core/src/main/java/org/springframework/util/MultiValueMapAdapter.java b/spring-core/src/main/java/org/springframework/util/MultiValueMapAdapter.java
new file mode 100644
index 0000000000..cfbf79cb3b
--- /dev/null
+++ b/spring-core/src/main/java/org/springframework/util/MultiValueMapAdapter.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2002-2020 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
+ *
+ * https://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.util;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.springframework.lang.Nullable;
+
+/**
+ * Adapts a given {@link Map} to the {@link MultiValueMap} contract.
+ *
+ * @author Arjen Poutsma
+ * @author Juergen Hoeller
+ * @since 3.1
+ * @param the key type
+ * @param the value element type
+ * @see CollectionUtils#toMultiValueMap
+ * @see LinkedMultiValueMap
+ */
+@SuppressWarnings("serial")
+class MultiValueMapAdapter implements MultiValueMap, Serializable {
+
+ private final Map> targetMap;
+
+
+ MultiValueMapAdapter(Map> targetMap) {
+ this.targetMap = targetMap;
+ }
+
+
+ @Override
+ @Nullable
+ public V getFirst(K key) {
+ List values = this.targetMap.get(key);
+ return (values != null && !values.isEmpty() ? values.get(0) : null);
+ }
+
+ @Override
+ public void add(K key, @Nullable V value) {
+ List values = this.targetMap.computeIfAbsent(key, k -> new LinkedList<>());
+ values.add(value);
+ }
+
+ @Override
+ public void addAll(K key, List extends V> values) {
+ List currentValues = this.targetMap.computeIfAbsent(key, k -> new LinkedList<>());
+ currentValues.addAll(values);
+ }
+
+ @Override
+ public void addAll(MultiValueMap values) {
+ for (Entry> entry : values.entrySet()) {
+ addAll(entry.getKey(), entry.getValue());
+ }
+ }
+
+ @Override
+ public void set(K key, @Nullable V value) {
+ List values = new LinkedList<>();
+ values.add(value);
+ this.targetMap.put(key, values);
+ }
+
+ @Override
+ public void setAll(Map values) {
+ values.forEach(this::set);
+ }
+
+ @Override
+ public Map toSingleValueMap() {
+ Map singleValueMap = new LinkedHashMap<>(this.targetMap.size());
+ this.targetMap.forEach((key, values) -> {
+ if (values != null && !values.isEmpty()) {
+ singleValueMap.put(key, values.get(0));
+ }
+ });
+ return singleValueMap;
+ }
+
+ @Override
+ public int size() {
+ return this.targetMap.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return this.targetMap.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return this.targetMap.containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return this.targetMap.containsValue(value);
+ }
+
+ @Override
+ @Nullable
+ public List get(Object key) {
+ return this.targetMap.get(key);
+ }
+
+ @Override
+ @Nullable
+ public List put(K key, List value) {
+ return this.targetMap.put(key, value);
+ }
+
+ @Override
+ @Nullable
+ public List remove(Object key) {
+ return this.targetMap.remove(key);
+ }
+
+ @Override
+ public void putAll(Map extends K, ? extends List> map) {
+ this.targetMap.putAll(map);
+ }
+
+ @Override
+ public void clear() {
+ this.targetMap.clear();
+ }
+
+ @Override
+ public Set keySet() {
+ return this.targetMap.keySet();
+ }
+
+ @Override
+ public Collection> values() {
+ return this.targetMap.values();
+ }
+
+ @Override
+ public Set>> entrySet() {
+ return this.targetMap.entrySet();
+ }
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ return (this == other || this.targetMap.equals(other));
+ }
+
+ @Override
+ public int hashCode() {
+ return this.targetMap.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return this.targetMap.toString();
+ }
+
+}
diff --git a/spring-core/src/main/java/org/springframework/util/SystemPropertyUtils.java b/spring-core/src/main/java/org/springframework/util/SystemPropertyUtils.java
index c1769c6b63..7c5ac6bdf4 100644
--- a/spring-core/src/main/java/org/springframework/util/SystemPropertyUtils.java
+++ b/spring-core/src/main/java/org/springframework/util/SystemPropertyUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -78,6 +78,9 @@ public abstract class SystemPropertyUtils {
* and the "ignoreUnresolvablePlaceholders" flag is {@code false}
*/
public static String resolvePlaceholders(String text, boolean ignoreUnresolvablePlaceholders) {
+ if (text.isEmpty()) {
+ return text;
+ }
PropertyPlaceholderHelper helper = (ignoreUnresolvablePlaceholders ? nonStrictHelper : strictHelper);
return helper.replacePlaceholders(text, new SystemPropertyPlaceholderResolver(text));
}
diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcOperations.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcOperations.java
index f38fb2c851..16151ded69 100644
--- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcOperations.java
+++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcOperations.java
@@ -965,6 +965,8 @@ public interface JdbcOperations {
* @param pss object to set parameters on the PreparedStatement
* created by this method
* @return an array of the number of rows affected by each statement
+ * (may also contain special JDBC-defined negative values for affected rows such as
+ * {@link java.sql.Statement#SUCCESS_NO_INFO}/{@link java.sql.Statement#EXECUTE_FAILED})
* @throws DataAccessException if there is any problem issuing the update
*/
int[] batchUpdate(String sql, BatchPreparedStatementSetter pss) throws DataAccessException;
@@ -974,6 +976,8 @@ public interface JdbcOperations {
* @param sql the SQL statement to execute
* @param batchArgs the List of Object arrays containing the batch of arguments for the query
* @return an array containing the numbers of rows affected by each update in the batch
+ * (may also contain special JDBC-defined negative values for affected rows such as
+ * {@link java.sql.Statement#SUCCESS_NO_INFO}/{@link java.sql.Statement#EXECUTE_FAILED})
* @throws DataAccessException if there is any problem issuing the update
*/
int[] batchUpdate(String sql, List batchArgs) throws DataAccessException;
@@ -985,20 +989,24 @@ public interface JdbcOperations {
* @param argTypes the SQL types of the arguments
* (constants from {@code java.sql.Types})
* @return an array containing the numbers of rows affected by each update in the batch
+ * (may also contain special JDBC-defined negative values for affected rows such as
+ * {@link java.sql.Statement#SUCCESS_NO_INFO}/{@link java.sql.Statement#EXECUTE_FAILED})
* @throws DataAccessException if there is any problem issuing the update
*/
int[] batchUpdate(String sql, List batchArgs, int[] argTypes) throws DataAccessException;
/**
- * Execute multiple batches using the supplied SQL statement with the collect of supplied arguments.
- * The arguments' values will be set using the ParameterizedPreparedStatementSetter.
+ * Execute multiple batches using the supplied SQL statement with the collect of supplied
+ * arguments. The arguments' values will be set using the ParameterizedPreparedStatementSetter.
* Each batch should be of size indicated in 'batchSize'.
* @param sql the SQL statement to execute.
* @param batchArgs the List of Object arrays containing the batch of arguments for the query
* @param batchSize batch size
* @param pss the ParameterizedPreparedStatementSetter to use
- * @return an array containing for each batch another array containing the numbers of rows affected
- * by each update in the batch
+ * @return an array containing for each batch another array containing the numbers of
+ * rows affected by each update in the batch
+ * (may also contain special JDBC-defined negative values for affected rows such as
+ * {@link java.sql.Statement#SUCCESS_NO_INFO}/{@link java.sql.Statement#EXECUTE_FAILED})
* @throws DataAccessException if there is any problem issuing the update
* @since 3.1
*/
diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcOperations.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcOperations.java
index 2f123d327f..5d22b535e6 100644
--- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcOperations.java
+++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcOperations.java
@@ -530,6 +530,8 @@ public interface NamedParameterJdbcOperations {
* @param sql the SQL statement to execute
* @param batchValues the array of Maps containing the batch of arguments for the query
* @return an array containing the numbers of rows affected by each update in the batch
+ * (may also contain special JDBC-defined negative values for affected rows such as
+ * {@link java.sql.Statement#SUCCESS_NO_INFO}/{@link java.sql.Statement#EXECUTE_FAILED})
* @throws DataAccessException if there is any problem issuing the update
*/
int[] batchUpdate(String sql, Map[] batchValues);
@@ -537,8 +539,11 @@ public interface NamedParameterJdbcOperations {
/**
* Execute a batch using the supplied SQL statement with the batch of supplied arguments.
* @param sql the SQL statement to execute
- * @param batchArgs the array of {@link SqlParameterSource} containing the batch of arguments for the query
+ * @param batchArgs the array of {@link SqlParameterSource} containing the batch of
+ * arguments for the query
* @return an array containing the numbers of rows affected by each update in the batch
+ * (may also contain special JDBC-defined negative values for affected rows such as
+ * {@link java.sql.Statement#SUCCESS_NO_INFO}/{@link java.sql.Statement#EXECUTE_FAILED})
* @throws DataAccessException if there is any problem issuing the update
*/
int[] batchUpdate(String sql, SqlParameterSource[] batchArgs);
diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/support/OpenSessionInViewFilter.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/support/OpenSessionInViewFilter.java
index a68af6f778..ec23f51c02 100644
--- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/support/OpenSessionInViewFilter.java
+++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/support/OpenSessionInViewFilter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -51,11 +51,11 @@ import org.springframework.web.filter.OncePerRequestFilter;
* as well as for non-transactional execution (if configured appropriately).
*
* NOTE : This filter will by default not flush the Hibernate Session,
- * with the flush mode set to {@code FlushMode.NEVER}. It assumes to be used
+ * with the flush mode set to {@code FlushMode.MANUAL}. It assumes to be used
* in combination with service layer transactions that care for the flushing: The
* active transaction manager will temporarily change the flush mode to
* {@code FlushMode.AUTO} during a read-write transaction, with the flush
- * mode reset to {@code FlushMode.NEVER} at the end of each transaction.
+ * mode reset to {@code FlushMode.MANUAL} at the end of each transaction.
*
*
WARNING: Applying this filter to existing logic can cause issues that
* have not appeared before, through the use of a single Hibernate Session for the
diff --git a/spring-tx/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java b/spring-tx/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java
index 19f20f8571..df9132d13d 100644
--- a/spring-tx/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java
+++ b/spring-tx/src/main/java/org/springframework/transaction/support/TransactionSynchronizationManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -383,7 +383,7 @@ public abstract class TransactionSynchronizationManager {
* as argument for the {@code beforeCommit} callback, to be able
* to suppress change detection on commit. The present method is meant
* to be used for earlier read-only checks, for example to set the
- * flush mode of a Hibernate Session to "FlushMode.NEVER" upfront.
+ * flush mode of a Hibernate Session to "FlushMode.MANUAL" upfront.
* @see org.springframework.transaction.TransactionDefinition#isReadOnly()
* @see TransactionSynchronization#beforeCommit(boolean)
*/
diff --git a/spring-web/src/main/java/org/springframework/web/util/ServletContextPropertyUtils.java b/spring-web/src/main/java/org/springframework/web/util/ServletContextPropertyUtils.java
index 18709788aa..ffaefa75b4 100644
--- a/spring-web/src/main/java/org/springframework/web/util/ServletContextPropertyUtils.java
+++ b/spring-web/src/main/java/org/springframework/web/util/ServletContextPropertyUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.springframework.web.util;
import javax.servlet.ServletContext;
@@ -73,16 +74,18 @@ public abstract class ServletContextPropertyUtils {
* @see SystemPropertyUtils#PLACEHOLDER_SUFFIX
* @see SystemPropertyUtils#resolvePlaceholders(String, boolean)
*/
- public static String resolvePlaceholders(String text, ServletContext servletContext,
- boolean ignoreUnresolvablePlaceholders) {
+ public static String resolvePlaceholders(
+ String text, ServletContext servletContext, boolean ignoreUnresolvablePlaceholders) {
+ if (text.isEmpty()) {
+ return text;
+ }
PropertyPlaceholderHelper helper = (ignoreUnresolvablePlaceholders ? nonStrictHelper : strictHelper);
return helper.replacePlaceholders(text, new ServletContextPlaceholderResolver(text, servletContext));
}
- private static class ServletContextPlaceholderResolver
- implements PropertyPlaceholderHelper.PlaceholderResolver {
+ private static class ServletContextPlaceholderResolver implements PropertyPlaceholderHelper.PlaceholderResolver {
private final String text;