replaced Commons Collections dependency with Spring-provided LinkedCaseInsensitiveMap; revised CollectionFactory and Spring Map implementations for consistency
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@1166 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
parent
52c241e14f
commit
8a49660e47
|
|
@ -36,12 +36,7 @@ import java.util.TreeSet;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
import org.apache.commons.collections.map.CaseInsensitiveMap;
|
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||||
import org.apache.commons.collections.map.ListOrderedMap;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for collections, being aware of Commons Collection 3.x's extended
|
* Factory for collections, being aware of Commons Collection 3.x's extended
|
||||||
|
|
@ -58,13 +53,6 @@ import org.springframework.util.ClassUtils;
|
||||||
*/
|
*/
|
||||||
public abstract class CollectionFactory {
|
public abstract class CollectionFactory {
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(CollectionFactory.class);
|
|
||||||
|
|
||||||
/** Whether the Commons Collections 3.x library is present on the classpath */
|
|
||||||
private static final boolean commonsCollections3Available =
|
|
||||||
ClassUtils.isPresent("org.apache.commons.collections.map.CaseInsensitiveMap",
|
|
||||||
CollectionFactory.class.getClassLoader());
|
|
||||||
|
|
||||||
private static final Set<Class> approximableCollectionTypes = new HashSet<Class>(10);
|
private static final Set<Class> approximableCollectionTypes = new HashSet<Class>(10);
|
||||||
|
|
||||||
private static final Set<Class> approximableMapTypes = new HashSet<Class>(6);
|
private static final Set<Class> approximableMapTypes = new HashSet<Class>(6);
|
||||||
|
|
@ -129,23 +117,15 @@ public abstract class CollectionFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a linked case-insensitive Map if possible: if Commons Collections
|
* Create a linked case-insensitive Map if possible: This implementation
|
||||||
* 3.x is available, a CaseInsensitiveMap with ListOrderedMap decorator will
|
* always returns a {@link org.springframework.util.LinkedCaseInsensitiveMap}.
|
||||||
* be created. Else, a JDK {@link java.util.LinkedHashMap} will be used.
|
|
||||||
* @param initialCapacity the initial capacity of the Map
|
* @param initialCapacity the initial capacity of the Map
|
||||||
* @return the new Map instance
|
* @return the new Map instance
|
||||||
* @see org.apache.commons.collections.map.CaseInsensitiveMap
|
* @deprecated as of Spring 3.0, for usage on JDK 1.5 or higher
|
||||||
* @see org.apache.commons.collections.map.ListOrderedMap
|
|
||||||
*/
|
*/
|
||||||
public static <K,V> Map<K,V> createLinkedCaseInsensitiveMapIfPossible(int initialCapacity) {
|
@Deprecated
|
||||||
if (commonsCollections3Available) {
|
public static Map createLinkedCaseInsensitiveMapIfPossible(int initialCapacity) {
|
||||||
logger.trace("Creating [org.apache.commons.collections.map.ListOrderedMap/CaseInsensitiveMap]");
|
return new LinkedCaseInsensitiveMap(initialCapacity);
|
||||||
return CommonsCollectionFactory.createListOrderedCaseInsensitiveMap(initialCapacity);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logger.debug("Falling back to [java.util.LinkedHashMap] for linked case-insensitive map");
|
|
||||||
return new LinkedHashMap<K,V>(initialCapacity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -157,8 +137,8 @@ public abstract class CollectionFactory {
|
||||||
* @deprecated as of Spring 2.5, for usage on JDK 1.4 or higher
|
* @deprecated as of Spring 2.5, for usage on JDK 1.4 or higher
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static <K,V> Map<K,V> createIdentityMapIfPossible(int initialCapacity) {
|
public static Map createIdentityMapIfPossible(int initialCapacity) {
|
||||||
return new IdentityHashMap<K,V>(initialCapacity);
|
return new IdentityHashMap(initialCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -170,8 +150,8 @@ public abstract class CollectionFactory {
|
||||||
* @deprecated as of Spring 3.0, for usage on JDK 1.5 or higher
|
* @deprecated as of Spring 3.0, for usage on JDK 1.5 or higher
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static <K,V> Map<K,V> createConcurrentMapIfPossible(int initialCapacity) {
|
public static Map createConcurrentMapIfPossible(int initialCapacity) {
|
||||||
return new ConcurrentHashMap<K,V>(initialCapacity);
|
return new ConcurrentHashMap(initialCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -183,8 +163,8 @@ public abstract class CollectionFactory {
|
||||||
* @deprecated as of Spring 3.0, for usage on JDK 1.5 or higher
|
* @deprecated as of Spring 3.0, for usage on JDK 1.5 or higher
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static <K,V> ConcurrentMap<K,V> createConcurrentMap(int initialCapacity) {
|
public static ConcurrentMap createConcurrentMap(int initialCapacity) {
|
||||||
return new JdkConcurrentHashMap<K,V>(initialCapacity);
|
return new JdkConcurrentHashMap(initialCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -246,26 +226,12 @@ public abstract class CollectionFactory {
|
||||||
* @see java.util.LinkedHashMap
|
* @see java.util.LinkedHashMap
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <K,V> Map<K,V> createApproximateMap(Object map, int initialCapacity) {
|
public static Map createApproximateMap(Object map, int initialCapacity) {
|
||||||
if (map instanceof SortedMap) {
|
if (map instanceof SortedMap) {
|
||||||
return new TreeMap<K,V>(((SortedMap<K,V>) map).comparator());
|
return new TreeMap(((SortedMap) map).comparator());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new LinkedHashMap<K,V>(initialCapacity);
|
return new LinkedHashMap(initialCapacity);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Actual creation of Commons Collections.
|
|
||||||
* In separate inner class to avoid runtime dependency on Commons Collections 3.x.
|
|
||||||
*/
|
|
||||||
private static abstract class CommonsCollectionFactory {
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static <K,V> Map<K,V> createListOrderedCaseInsensitiveMap(int initialCapacity) {
|
|
||||||
// Commons Collections does not support initial capacity of 0.
|
|
||||||
return ListOrderedMap.decorate(new CaseInsensitiveMap(initialCapacity == 0 ? 1 : initialCapacity));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,7 +240,7 @@ public abstract class CollectionFactory {
|
||||||
* ConcurrentMap adapter for the JDK ConcurrentHashMap class.
|
* ConcurrentMap adapter for the JDK ConcurrentHashMap class.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
private static class JdkConcurrentHashMap<K,V> extends ConcurrentHashMap<K,V> implements ConcurrentMap<K,V> {
|
private static class JdkConcurrentHashMap extends ConcurrentHashMap implements ConcurrentMap {
|
||||||
|
|
||||||
private JdkConcurrentHashMap(int initialCapacity) {
|
private JdkConcurrentHashMap(int initialCapacity) {
|
||||||
super(initialCapacity);
|
super(initialCapacity);
|
||||||
|
|
|
||||||
|
|
@ -33,14 +33,14 @@ import java.util.Map;
|
||||||
* is available on Java 5+ anyway
|
* is available on Java 5+ anyway
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public interface ConcurrentMap<K,V> extends Map<K,V> {
|
public interface ConcurrentMap extends Map {
|
||||||
|
|
||||||
V putIfAbsent(K key, V value);
|
Object putIfAbsent(Object key, Object value);
|
||||||
|
|
||||||
boolean remove(Object key, Object value);
|
boolean remove(Object key, Object value);
|
||||||
|
|
||||||
boolean replace(K key, V oldValue, V newValue);
|
boolean replace(Object key, Object oldValue, Object newValue);
|
||||||
|
|
||||||
V replace(K key, V value);
|
Object replace(Object key, Object value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 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.util;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link LinkedHashMap} variant that stores String keys in a case-insensitive
|
||||||
|
* manner, for example for key-based access in a results table.
|
||||||
|
*
|
||||||
|
* <p>Preserves the original order as well as the original casing of keys,
|
||||||
|
* while allowing for contains, get and remove calls with any case of key.
|
||||||
|
*
|
||||||
|
* <p>Does <i>not</i> support <code>null</code> keys.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.0
|
||||||
|
*/
|
||||||
|
public class LinkedCaseInsensitiveMap<V> extends LinkedHashMap<String, V> {
|
||||||
|
|
||||||
|
private final Map<String, String> caseInsensitiveKeys;
|
||||||
|
|
||||||
|
private final Locale locale;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new LinkedCaseInsensitiveMap for the default Locale.
|
||||||
|
* @see java.lang.String#toLowerCase()
|
||||||
|
*/
|
||||||
|
public LinkedCaseInsensitiveMap() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new LinkedCaseInsensitiveMap that stores lower-case keys
|
||||||
|
* according to the given Locale.
|
||||||
|
* @param locale the Locale to use for lower-case conversion
|
||||||
|
* @see java.lang.String#toLowerCase(java.util.Locale)
|
||||||
|
*/
|
||||||
|
public LinkedCaseInsensitiveMap(Locale locale) {
|
||||||
|
super();
|
||||||
|
this.caseInsensitiveKeys = new HashMap<String, String>();
|
||||||
|
this.locale = (locale != null ? locale : Locale.getDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new LinkedCaseInsensitiveMap that wraps a {@link LinkedHashMap}
|
||||||
|
* with the given initial capacity and stores lower-case keys according
|
||||||
|
* to the default Locale.
|
||||||
|
* @param initialCapacity the initial capacity
|
||||||
|
* @see java.lang.String#toLowerCase()
|
||||||
|
*/
|
||||||
|
public LinkedCaseInsensitiveMap(int initialCapacity) {
|
||||||
|
this(initialCapacity, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new LinkedCaseInsensitiveMap that wraps a {@link LinkedHashMap}
|
||||||
|
* with the given initial capacity and stores lower-case keys according
|
||||||
|
* to the given Locale.
|
||||||
|
* @param initialCapacity the initial capacity
|
||||||
|
* @param locale the Locale to use for lower-case conversion
|
||||||
|
* @see java.lang.String#toLowerCase(java.util.Locale)
|
||||||
|
*/
|
||||||
|
public LinkedCaseInsensitiveMap(int initialCapacity, Locale locale) {
|
||||||
|
super(initialCapacity);
|
||||||
|
this.caseInsensitiveKeys = new HashMap<String, String>(initialCapacity);
|
||||||
|
this.locale = (locale != null ? locale : Locale.getDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V put(String key, V value) {
|
||||||
|
this.caseInsensitiveKeys.put(convertKey(key), key);
|
||||||
|
return super.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(Object key) {
|
||||||
|
return (key instanceof String && this.caseInsensitiveKeys.containsKey(convertKey((String) key)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V get(Object key) {
|
||||||
|
if (key instanceof String) {
|
||||||
|
return super.get(this.caseInsensitiveKeys.get(convertKey((String) key)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V remove(Object key) {
|
||||||
|
if (key instanceof String ) {
|
||||||
|
return super.remove(this.caseInsensitiveKeys.remove(convertKey((String) key)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
this.caseInsensitiveKeys.clear();
|
||||||
|
super.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given key to a case-insensitive key.
|
||||||
|
* <p>The default implementation converts the key
|
||||||
|
* to lower-case according to this Map's Locale.
|
||||||
|
* @param key the user-specified key
|
||||||
|
* @return the key to use for storing
|
||||||
|
* @see java.lang.String#toLowerCase(java.util.Locale)
|
||||||
|
*/
|
||||||
|
protected String convertKey(String key) {
|
||||||
|
return key.toLowerCase(this.locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -24,11 +24,12 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple implementation of {@link MultiValueMap} that wraps a plain {@code Map}
|
* Simple implementation of {@link MultiValueMap} that wraps a {@link LinkedHashMap},
|
||||||
* (by default a {@link LinkedHashMap}, storing multiple values in a {@link LinkedList}.
|
* storing multiple values in a {@link LinkedList}.
|
||||||
*
|
*
|
||||||
* <p>This Map implementation is generally not thread-safe. It is primarily designed
|
* <p>This Map implementation is generally not thread-safe. It is primarily designed
|
||||||
* for data structures exposed from request objects, for use in a single thread only.
|
* for data structures exposed from request objects, for use in a single thread only.
|
||||||
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
|
|
@ -37,15 +38,17 @@ public class LinkedMultiValueMap<K, V> implements MultiValueMap<K, V> {
|
||||||
|
|
||||||
private final Map<K, List<V>> targetMap;
|
private final Map<K, List<V>> targetMap;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new SimpleMultiValueMap that wraps a newly created {@link LinkedHashMap}.
|
* Create a new LinkedMultiValueMap that wraps a {@link LinkedHashMap}.
|
||||||
*/
|
*/
|
||||||
public LinkedMultiValueMap() {
|
public LinkedMultiValueMap() {
|
||||||
this.targetMap = new LinkedHashMap<K, List<V>>();
|
this.targetMap = new LinkedHashMap<K, List<V>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new SimpleMultiValueMap that wraps a newly created {@link LinkedHashMap} with the given initial capacity.
|
* Create a new LinkedMultiValueMap that wraps a {@link LinkedHashMap}
|
||||||
|
* with the given initial capacity.
|
||||||
* @param initialCapacity the initial capacity
|
* @param initialCapacity the initial capacity
|
||||||
*/
|
*/
|
||||||
public LinkedMultiValueMap(int initialCapacity) {
|
public LinkedMultiValueMap(int initialCapacity) {
|
||||||
|
|
@ -53,17 +56,15 @@ public class LinkedMultiValueMap<K, V> implements MultiValueMap<K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new SimpleMultiValueMap that wraps the given target Map.
|
* Copy constructor: Create a new LinkedMultiValueMap with the same mappings
|
||||||
* <p>Note: The given Map will be used as active underlying Map.
|
* as the specified Map.
|
||||||
* Any changes in the underlying map will be reflected in the
|
* @param otherMap the Map whose mappings are to be placed in this Map
|
||||||
* MultiValueMap object, and vice versa.
|
|
||||||
* @param targetMap the target Map to wrap
|
|
||||||
*/
|
*/
|
||||||
public LinkedMultiValueMap(Map<K, List<V>> targetMap) {
|
public LinkedMultiValueMap(Map<K, List<V>> otherMap) {
|
||||||
Assert.notNull(targetMap, "'targetMap' must not be null");
|
this.targetMap = new LinkedHashMap<K, List<V>>(otherMap);
|
||||||
this.targetMap = targetMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MultiValueMap implementation
|
// MultiValueMap implementation
|
||||||
|
|
||||||
public void add(K key, V value) {
|
public void add(K key, V value) {
|
||||||
|
|
@ -86,6 +87,7 @@ public class LinkedMultiValueMap<K, V> implements MultiValueMap<K, V> {
|
||||||
this.targetMap.put(key, values);
|
this.targetMap.put(key, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Map implementation
|
// Map implementation
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
|
|
@ -136,6 +138,7 @@ public class LinkedMultiValueMap<K, V> implements MultiValueMap<K, V> {
|
||||||
return this.targetMap.entrySet();
|
return this.targetMap.entrySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
return this.targetMap.equals(obj);
|
return this.targetMap.equals(obj);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2007 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -21,8 +21,8 @@ import java.sql.ResultSetMetaData;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
|
||||||
import org.springframework.jdbc.support.JdbcUtils;
|
import org.springframework.jdbc.support.JdbcUtils;
|
||||||
|
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link RowMapper} implementation that creates a <code>java.util.Map</code>
|
* {@link RowMapper} implementation that creates a <code>java.util.Map</code>
|
||||||
|
|
@ -61,16 +61,15 @@ public class ColumnMapRowMapper implements RowMapper<Map<String, Object>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a Map instance to be used as column map.
|
* Create a Map instance to be used as column map.
|
||||||
* <p>By default, a linked case-insensitive Map will be created if possible,
|
* <p>By default, a linked case-insensitive Map will be created.
|
||||||
* else a plain HashMap (see Spring's CollectionFactory).
|
|
||||||
* @param columnCount the column count, to be used as initial
|
* @param columnCount the column count, to be used as initial
|
||||||
* capacity for the Map
|
* capacity for the Map
|
||||||
* @return the new Map instance
|
* @return the new Map instance
|
||||||
* @see org.springframework.core.CollectionFactory#createLinkedCaseInsensitiveMapIfPossible
|
* @see org.springframework.util.LinkedCaseInsensitiveMap
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected Map<String, Object> createColumnMap(int columnCount) {
|
protected Map<String, Object> createColumnMap(int columnCount) {
|
||||||
return CollectionFactory.createLinkedCaseInsensitiveMapIfPossible(columnCount);
|
return new LinkedCaseInsensitiveMap<Object>(columnCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -35,7 +35,6 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
import org.springframework.dao.support.DataAccessUtils;
|
import org.springframework.dao.support.DataAccessUtils;
|
||||||
|
|
@ -48,6 +47,7 @@ import org.springframework.jdbc.support.KeyHolder;
|
||||||
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
|
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
|
||||||
import org.springframework.jdbc.support.rowset.SqlRowSet;
|
import org.springframework.jdbc.support.rowset.SqlRowSet;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <b>This is the central class in the JDBC core package.</b>
|
* <b>This is the central class in the JDBC core package.</b>
|
||||||
|
|
@ -1161,16 +1161,14 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a Map instance to be used as results map.
|
* Create a Map instance to be used as results map.
|
||||||
* <p>If "isResultsMapCaseInsensitive" has been set to true, a linked case-insensitive Map
|
* <p>If "isResultsMapCaseInsensitive" has been set to true,
|
||||||
* will be created if possible, else a plain HashMap (see Spring's CollectionFactory).
|
* a linked case-insensitive Map will be created.
|
||||||
* @return the results Map instance
|
* @return the results Map instance
|
||||||
* @see #setResultsMapCaseInsensitive
|
* @see #setResultsMapCaseInsensitive
|
||||||
* @see org.springframework.core.CollectionFactory#createLinkedCaseInsensitiveMapIfPossible
|
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected Map<String, Object> createResultsMap() {
|
protected Map<String, Object> createResultsMap() {
|
||||||
if (isResultsMapCaseInsensitive()) {
|
if (isResultsMapCaseInsensitive()) {
|
||||||
return CollectionFactory.createLinkedCaseInsensitiveMapIfPossible(16);
|
return new LinkedCaseInsensitiveMap<Object>();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new LinkedHashMap<String, Object>();
|
return new LinkedHashMap<String, Object>();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -29,11 +29,10 @@ import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.easymock.MockControl;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.easymock.MockControl;
|
||||||
|
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
|
|
@ -49,6 +48,7 @@ import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
|
||||||
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
|
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
|
||||||
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
|
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
|
||||||
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractorAdapter;
|
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractorAdapter;
|
||||||
|
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mock object based tests for JdbcTemplate.
|
* Mock object based tests for JdbcTemplate.
|
||||||
|
|
@ -1954,8 +1954,7 @@ public class JdbcTemplateTests extends AbstractJdbcTests {
|
||||||
JdbcTemplate template = new JdbcTemplate(mockDataSource);
|
JdbcTemplate template = new JdbcTemplate(mockDataSource);
|
||||||
try {
|
try {
|
||||||
template.call(new CallableStatementCreator() {
|
template.call(new CallableStatementCreator() {
|
||||||
public CallableStatement createCallableStatement(Connection conn)
|
public CallableStatement createCallableStatement(Connection conn) throws SQLException {
|
||||||
throws SQLException {
|
|
||||||
return conn.prepareCall("my query");
|
return conn.prepareCall("my query");
|
||||||
}
|
}
|
||||||
}, params);
|
}, params);
|
||||||
|
|
@ -2005,13 +2004,11 @@ public class JdbcTemplateTests extends AbstractJdbcTests {
|
||||||
params.add(new SqlOutParameter("a", 12));
|
params.add(new SqlOutParameter("a", 12));
|
||||||
|
|
||||||
Map out = template.call(new CallableStatementCreator() {
|
Map out = template.call(new CallableStatementCreator() {
|
||||||
public CallableStatement createCallableStatement(Connection conn)
|
public CallableStatement createCallableStatement(Connection conn) throws SQLException {
|
||||||
throws SQLException {
|
|
||||||
return conn.prepareCall("my query");
|
return conn.prepareCall("my query");
|
||||||
}
|
}
|
||||||
}, params);
|
}, params);
|
||||||
assertTrue("this should have been an Apache Commons Collections class",
|
assertTrue("this should have been a LinkedCaseInsensitiveMap", out instanceof LinkedCaseInsensitiveMap);
|
||||||
out.getClass().getName().startsWith("org.apache.commons.collections.map"));
|
|
||||||
assertNotNull("we should have gotten the result with upper case", out.get("A"));
|
assertNotNull("we should have gotten the result with upper case", out.get("A"));
|
||||||
assertNotNull("we should have gotten the result with lower case", out.get("a"));
|
assertNotNull("we should have gotten the result with lower case", out.get("a"));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mock implementation of the {@link javax.servlet.http.HttpServletRequest}
|
* Mock implementation of the {@link javax.servlet.http.HttpServletRequest}
|
||||||
|
|
@ -142,10 +143,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
|
||||||
|
|
||||||
private Cookie[] cookies;
|
private Cookie[] cookies;
|
||||||
|
|
||||||
/**
|
private final Map<String, HeaderValueHolder> headers = new LinkedCaseInsensitiveMap<HeaderValueHolder>();
|
||||||
* The key is the lowercase header name; the value is a {@link HeaderValueHolder} object.
|
|
||||||
*/
|
|
||||||
private final Map<String, HeaderValueHolder> headers = new LinkedHashMap<String, HeaderValueHolder>();
|
|
||||||
|
|
||||||
private String method;
|
private String method;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import java.io.UnsupportedEncodingException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -35,6 +34,7 @@ import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||||
import org.springframework.web.util.WebUtils;
|
import org.springframework.web.util.WebUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -88,10 +88,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
|
||||||
|
|
||||||
private final List<Cookie> cookies = new ArrayList<Cookie>();
|
private final List<Cookie> cookies = new ArrayList<Cookie>();
|
||||||
|
|
||||||
/**
|
private final Map<String, HeaderValueHolder> headers = new LinkedCaseInsensitiveMap<HeaderValueHolder>();
|
||||||
* The key is the lowercase header name; the value is a {@link HeaderValueHolder} object.
|
|
||||||
*/
|
|
||||||
private final Map<String, HeaderValueHolder> headers = new HashMap<String, HeaderValueHolder>();
|
|
||||||
|
|
||||||
private int status = HttpServletResponse.SC_OK;
|
private int status = HttpServletResponse.SC_OK;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mock implementation of the {@link javax.servlet.http.HttpServletRequest}
|
* Mock implementation of the {@link javax.servlet.http.HttpServletRequest}
|
||||||
|
|
@ -142,10 +143,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
|
||||||
|
|
||||||
private Cookie[] cookies;
|
private Cookie[] cookies;
|
||||||
|
|
||||||
/**
|
private final Map<String, HeaderValueHolder> headers = new LinkedCaseInsensitiveMap<HeaderValueHolder>();
|
||||||
* The key is the lowercase header name; the value is a {@link HeaderValueHolder} object.
|
|
||||||
*/
|
|
||||||
private final Map<String, HeaderValueHolder> headers = new LinkedHashMap<String, HeaderValueHolder>();
|
|
||||||
|
|
||||||
private String method;
|
private String method;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import java.io.UnsupportedEncodingException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -35,6 +34,7 @@ import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||||
import org.springframework.web.util.WebUtils;
|
import org.springframework.web.util.WebUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -88,10 +88,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
|
||||||
|
|
||||||
private final List<Cookie> cookies = new ArrayList<Cookie>();
|
private final List<Cookie> cookies = new ArrayList<Cookie>();
|
||||||
|
|
||||||
/**
|
private final Map<String, HeaderValueHolder> headers = new LinkedCaseInsensitiveMap<HeaderValueHolder>();
|
||||||
* The key is the lowercase header name; the value is a {@link HeaderValueHolder} object.
|
|
||||||
*/
|
|
||||||
private final Map<String, HeaderValueHolder> headers = new HashMap<String, HeaderValueHolder>();
|
|
||||||
|
|
||||||
private int status = HttpServletResponse.SC_OK;
|
private int status = HttpServletResponse.SC_OK;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
|
@ -64,7 +64,7 @@ public class HttpHeaders implements MultiValueMap<String, String> {
|
||||||
private static String LOCATION = "Location";
|
private static String LOCATION = "Location";
|
||||||
|
|
||||||
|
|
||||||
private final Map<String, List<String>> headers = CollectionFactory.createLinkedCaseInsensitiveMapIfPossible(5);
|
private final Map<String, List<String>> headers = new LinkedCaseInsensitiveMap<List<String>>(8);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -303,6 +303,7 @@ public class HttpHeaders implements MultiValueMap<String, String> {
|
||||||
return this.headers.entrySet();
|
return this.headers.entrySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object other) {
|
public boolean equals(Object other) {
|
||||||
if (this == other) {
|
if (this == other) {
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,9 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.core.CollectionFactory;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -102,7 +102,7 @@ public class MediaType implements Comparable<MediaType> {
|
||||||
this.type = type.toLowerCase(Locale.ENGLISH);
|
this.type = type.toLowerCase(Locale.ENGLISH);
|
||||||
this.subtype = subtype.toLowerCase(Locale.ENGLISH);
|
this.subtype = subtype.toLowerCase(Locale.ENGLISH);
|
||||||
if (!CollectionUtils.isEmpty(parameters)) {
|
if (!CollectionUtils.isEmpty(parameters)) {
|
||||||
this.parameters = CollectionFactory.createLinkedCaseInsensitiveMapIfPossible(parameters.size());
|
this.parameters = new LinkedCaseInsensitiveMap<String>(parameters.size());
|
||||||
this.parameters.putAll(parameters);
|
this.parameters.putAll(parameters);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -282,31 +282,29 @@ public class MediaType implements Comparable<MediaType> {
|
||||||
Assert.hasLength(mediaType, "'mediaType' must not be empty");
|
Assert.hasLength(mediaType, "'mediaType' must not be empty");
|
||||||
String[] parts = StringUtils.tokenizeToStringArray(mediaType, ";");
|
String[] parts = StringUtils.tokenizeToStringArray(mediaType, ";");
|
||||||
|
|
||||||
Map<String, String> parameters;
|
|
||||||
if (parts.length <= 1) {
|
|
||||||
parameters = null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
parameters = new LinkedHashMap<String, String>(parts.length - 1);
|
|
||||||
}
|
|
||||||
for (int i = 1; i < parts.length; i++) {
|
|
||||||
String part = parts[i];
|
|
||||||
int idx = part.indexOf('=');
|
|
||||||
if (idx != -1) {
|
|
||||||
String name = part.substring(0, idx);
|
|
||||||
String value = part.substring(idx + 1, part.length());
|
|
||||||
parameters.put(name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String fullType = parts[0].trim();
|
String fullType = parts[0].trim();
|
||||||
|
|
||||||
// java.net.HttpURLConnection returns a *; q=.2 Accept header
|
// java.net.HttpURLConnection returns a *; q=.2 Accept header
|
||||||
if (WILDCARD_TYPE.equals(fullType)) {
|
if (WILDCARD_TYPE.equals(fullType)) {
|
||||||
fullType = "*/*";
|
fullType = "*/*";
|
||||||
}
|
}
|
||||||
int idx = fullType.indexOf('/');
|
int subIndex = fullType.indexOf('/');
|
||||||
String type = fullType.substring(0, idx);
|
String type = fullType.substring(0, subIndex);
|
||||||
String subtype = fullType.substring(idx + 1, fullType.length());
|
String subtype = fullType.substring(subIndex + 1, fullType.length());
|
||||||
|
|
||||||
|
Map<String, String> parameters = null;
|
||||||
|
if (parts.length > 1) {
|
||||||
|
parameters = new LinkedHashMap<String, String>(parts.length - 1);
|
||||||
|
for (int i = 1; i < parts.length; i++) {
|
||||||
|
String part = parts[i];
|
||||||
|
int eqIndex = part.indexOf('=');
|
||||||
|
if (eqIndex != -1) {
|
||||||
|
String name = part.substring(0, eqIndex);
|
||||||
|
String value = part.substring(eqIndex + 1, part.length());
|
||||||
|
parameters.put(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new MediaType(type, subtype, parameters);
|
return new MediaType(type, subtype, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ import org.springframework.http.HttpStatus;
|
||||||
/**
|
/**
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
*/
|
*/
|
||||||
public class ServletHttpResponseTest {
|
public class ServletHttpResponseTests {
|
||||||
|
|
||||||
private ServletServerHttpResponse response;
|
private ServletServerHttpResponse response;
|
||||||
|
|
||||||
|
|
@ -42,6 +42,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mock implementation of the {@link javax.servlet.http.HttpServletRequest}
|
* Mock implementation of the {@link javax.servlet.http.HttpServletRequest}
|
||||||
|
|
@ -142,10 +143,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
|
||||||
|
|
||||||
private Cookie[] cookies;
|
private Cookie[] cookies;
|
||||||
|
|
||||||
/**
|
private final Map<String, HeaderValueHolder> headers = new LinkedCaseInsensitiveMap<HeaderValueHolder>();
|
||||||
* The key is the lowercase header name; the value is a {@link HeaderValueHolder} object.
|
|
||||||
*/
|
|
||||||
private final Map<String, HeaderValueHolder> headers = new LinkedHashMap<String, HeaderValueHolder>();
|
|
||||||
|
|
||||||
private String method;
|
private String method;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import java.io.UnsupportedEncodingException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -35,6 +34,7 @@ import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||||
import org.springframework.web.util.WebUtils;
|
import org.springframework.web.util.WebUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -88,10 +88,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
|
||||||
|
|
||||||
private final List<Cookie> cookies = new ArrayList<Cookie>();
|
private final List<Cookie> cookies = new ArrayList<Cookie>();
|
||||||
|
|
||||||
/**
|
private final Map<String, HeaderValueHolder> headers = new LinkedCaseInsensitiveMap<HeaderValueHolder>();
|
||||||
* The key is the lowercase header name; the value is a {@link HeaderValueHolder} object.
|
|
||||||
*/
|
|
||||||
private final Map<String, HeaderValueHolder> headers = new HashMap<String, HeaderValueHolder>();
|
|
||||||
|
|
||||||
private int status = HttpServletResponse.SC_OK;
|
private int status = HttpServletResponse.SC_OK;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue