Merge branch '3.2.x' into master

Conflicts:
	gradle.properties
	spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
	spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerFactoryBean.java
	spring-core/src/main/java/org/springframework/core/convert/support/StringToEnumConverterFactory.java
	spring-core/src/main/java/org/springframework/core/env/ReadOnlySystemAttributesMap.java
	spring-jdbc/src/main/java/org/springframework/jdbc/datasource/LazyConnectionDataSourceProxy.java
	spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/AbstractLobHandler.java
	spring-web/src/main/java/org/springframework/http/client/BufferingClientHttpRequestWrapper.java
	spring-web/src/main/java/org/springframework/http/client/SimpleBufferingClientHttpRequest.java
	spring-web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java
	spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java
This commit is contained in:
Chris Beams
2013-03-04 15:41:15 +01:00
1450 changed files with 17678 additions and 42998 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -25,7 +25,6 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
@@ -145,7 +144,7 @@ public abstract class BridgeMethodResolver {
private static Method findGenericDeclaration(Method bridgeMethod) {
// Search parent types for method that has same signature as bridge.
Class superclass = bridgeMethod.getDeclaringClass().getSuperclass();
while (!Object.class.equals(superclass)) {
while (superclass != null && !Object.class.equals(superclass)) {
Method method = searchForMatch(superclass, bridgeMethod);
if (method != null && !method.isBridge()) {
return method;
@@ -219,8 +218,6 @@ public abstract class BridgeMethodResolver {
* @return whether signatures match as described
*/
public static boolean isVisibilityBridgeMethodPair(Method bridgeMethod, Method bridgedMethod) {
Assert.isTrue(bridgeMethod != null);
Assert.isTrue(bridgedMethod != null);
if (bridgeMethod == bridgedMethod) {
return true;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -26,11 +26,7 @@ import java.lang.reflect.WildcardType;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ConcurrentReferenceHashMap;
/**
@@ -47,12 +43,11 @@ import org.springframework.util.ConcurrentReferenceHashMap;
*/
public abstract class GenericTypeResolver {
private static final Log logger = LogFactory.getLog(GenericTypeResolver.class);
/** Cache from Class to TypeVariable Map */
private static final Map<Class, Map<TypeVariable, Type>> typeVariableCache =
new ConcurrentReferenceHashMap<Class, Map<TypeVariable,Type>>();
/**
* Determine the target type for the given parameter specification.
* @param methodParam the method parameter specification
@@ -93,7 +88,6 @@ public abstract class GenericTypeResolver {
/**
* Determine the target type for the generic return type of the given method,
* where formal type variables are declared on the given class.
*
* @param method the method to introspect
* @param clazz the class to resolve type variables against
* @return the corresponding generic parameter or return type
@@ -112,15 +106,12 @@ public abstract class GenericTypeResolver {
* Determine the target type for the generic return type of the given
* <em>generic method</em>, where formal type variables are declared on
* the given method itself.
*
* <p>For example, given a factory method with the following signature,
* if {@code resolveReturnTypeForGenericMethod()} is invoked with the reflected
* method for {@code creatProxy()} and an {@code Object[]} array containing
* {@code MyService.class}, {@code resolveReturnTypeForGenericMethod()} will
* infer that the target return type is {@code MyService}.
*
* <pre>{@code public static <T> T createProxy(Class<T> clazz)}</pre>
*
* <h4>Possible Return Values</h4>
* <ul>
* <li>the target return type, if it can be inferred</li>
@@ -134,27 +125,20 @@ public abstract class GenericTypeResolver {
* Method#getGenericParameterTypes() formal argument list} for the given
* method</li>
* </ul>
*
* @param method the method to introspect, never {@code null}
* @param args the arguments that will be supplied to the method when it is
* invoked, never {@code null}
* @return the resolved target return type, the standard return type, or
* {@code null}
* @return the resolved target return type, the standard return type, or {@code null}
* @since 3.2
* @see #resolveReturnType
*/
public static Class<?> resolveReturnTypeForGenericMethod(Method method, Object[] args) {
Assert.notNull(method, "method must not be null");
Assert.notNull(args, "args must not be null");
Assert.notNull(method, "Method must not be null");
Assert.notNull(args, "Argument array must not be null");
if (logger.isDebugEnabled()) {
logger.debug(String.format("Resolving return type for [%s] with concrete method arguments [%s].",
method.toGenericString(), ObjectUtils.nullSafeToString(args)));
}
final TypeVariable<Method>[] declaredTypeVariables = method.getTypeParameters();
final Type genericReturnType = method.getGenericReturnType();
final Type[] methodArgumentTypes = method.getGenericParameterTypes();
TypeVariable<Method>[] declaredTypeVariables = method.getTypeParameters();
Type genericReturnType = method.getGenericReturnType();
Type[] methodArgumentTypes = method.getGenericParameterTypes();
// No declared type variables to inspect, so just return the standard return type.
if (declaredTypeVariables.length == 0) {
@@ -172,11 +156,6 @@ public abstract class GenericTypeResolver {
boolean locallyDeclaredTypeVariableMatchesReturnType = false;
for (TypeVariable<Method> currentTypeVariable : declaredTypeVariables) {
if (currentTypeVariable.equals(genericReturnType)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format(
"Found declared type variable [%s] that matches the target return type [%s].",
currentTypeVariable, genericReturnType));
}
locallyDeclaredTypeVariableMatchesReturnType = true;
break;
}
@@ -184,39 +163,20 @@ public abstract class GenericTypeResolver {
if (locallyDeclaredTypeVariableMatchesReturnType) {
for (int i = 0; i < methodArgumentTypes.length; i++) {
final Type currentMethodArgumentType = methodArgumentTypes[i];
Type currentMethodArgumentType = methodArgumentTypes[i];
if (currentMethodArgumentType.equals(genericReturnType)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format(
"Found method argument type at index [%s] that matches the target return type.", i));
}
return args[i].getClass();
}
if (currentMethodArgumentType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) currentMethodArgumentType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (int j = 0; j < actualTypeArguments.length; j++) {
final Type typeArg = actualTypeArguments[j];
for (Type typeArg : actualTypeArguments) {
if (typeArg.equals(genericReturnType)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format(
"Found method argument type at index [%s] that is parameterized with a type argument that matches the target return type.",
i));
}
if (args[i] instanceof Class) {
return (Class<?>) args[i];
} else {
// Consider adding logic to determine the class of the
// J'th typeArg, if possible.
logger.info(String.format(
"Could not determine the target type for type argument [%s] for method [%s].",
typeArg, method.toGenericString()));
}
else {
// Consider adding logic to determine the class of the typeArg, if possible.
// For now, just fall back...
return method.getReturnType();
}
@@ -409,8 +369,7 @@ public abstract class GenericTypeResolver {
* all super types, enclosing types and interfaces.
*/
public static Map<TypeVariable, Type> getTypeVariableMap(Class clazz) {
Map<TypeVariable, Type> ref = typeVariableCache.get(clazz);
Map<TypeVariable, Type> typeVariableMap = (ref != null ? ref : null);
Map<TypeVariable, Type> typeVariableMap = typeVariableCache.get(clazz);
if (typeVariableMap == null) {
typeVariableMap = new HashMap<TypeVariable, Type>();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -65,15 +65,15 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
public String[] getParameterNames(Method method) {
Class<?> declaringClass = method.getDeclaringClass();
Method originalMethod = BridgeMethodResolver.findBridgedMethod(method);
Class<?> declaringClass = originalMethod.getDeclaringClass();
Map<Member, String[]> map = this.parameterNamesCache.get(declaringClass);
if (map == null) {
// initialize cache
map = inspectClass(declaringClass);
this.parameterNamesCache.put(declaringClass, map);
}
if (map != NO_DEBUG_INFO_MAP) {
return map.get(method);
return map.get(originalMethod);
}
return null;
}
@@ -82,14 +82,12 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
Class<?> declaringClass = ctor.getDeclaringClass();
Map<Member, String[]> map = this.parameterNamesCache.get(declaringClass);
if (map == null) {
// initialize cache
map = inspectClass(declaringClass);
this.parameterNamesCache.put(declaringClass, map);
}
if (map != NO_DEBUG_INFO_MAP) {
return map.get(ctor);
}
return null;
}

View File

@@ -45,4 +45,4 @@ public class NamedInheritableThreadLocal<T> extends InheritableThreadLocal<T> {
return this.name;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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,6 +16,10 @@
package org.springframework.core.annotation;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
@@ -37,7 +41,7 @@ public class AnnotationAwareOrderComparator extends OrderComparator {
/**
* Shared default instance of AnnotationAwareOrderComparator.
*/
public static AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();
public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();
@Override
@@ -46,7 +50,8 @@ public class AnnotationAwareOrderComparator extends OrderComparator {
return ((Ordered) obj).getOrder();
}
if (obj != null) {
Order order = obj.getClass().getAnnotation(Order.class);
Class<?> clazz = (obj instanceof Class ? (Class) obj : obj.getClass());
Order order = clazz.getAnnotation(Order.class);
if (order != null) {
return order.value();
}
@@ -54,4 +59,31 @@ public class AnnotationAwareOrderComparator extends OrderComparator {
return Ordered.LOWEST_PRECEDENCE;
}
/**
* Sort the given List with a default AnnotationAwareOrderComparator.
* <p>Optimized to skip sorting for lists with size 0 or 1,
* in order to avoid unnecessary array extraction.
* @param list the List to sort
* @see java.util.Collections#sort(java.util.List, java.util.Comparator)
*/
public static void sort(List<?> list) {
if (list.size() > 1) {
Collections.sort(list, INSTANCE);
}
}
/**
* Sort the given array with a default AnnotationAwareOrderComparator.
* <p>Optimized to skip sorting for lists with size 0 or 1,
* in order to avoid unnecessary array extraction.
* @param array the array to sort
* @see java.util.Arrays#sort(Object[], java.util.Comparator)
*/
public static void sort(Object[] array) {
if (array.length > 1) {
Arrays.sort(array, INSTANCE);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -19,7 +19,7 @@ package org.springframework.core.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
import java.util.WeakHashMap;
@@ -255,8 +255,9 @@ public abstract class AnnotationUtils {
* declared locally on the supplied {@code clazz}. The supplied {@link Class}
* may represent any type.
* <p>Note: This method does <strong>not</strong> determine if the annotation is
* {@link java.lang.annotation.Inherited inherited}. For greater clarity regarding inherited
* annotations, consider using {@link #isAnnotationInherited(Class, Class)} instead.
* {@linkplain java.lang.annotation.Inherited inherited}. For greater clarity
* regarding inherited annotations, consider using
* {@link #isAnnotationInherited(Class, Class)} instead.
* @param annotationType the Class object corresponding to the annotation type
* @param clazz the Class object corresponding to the class on which to check for the annotation
* @return {@code true} if an annotation for the specified {@code annotationType}
@@ -268,7 +269,7 @@ public abstract class AnnotationUtils {
Assert.notNull(annotationType, "Annotation type must not be null");
Assert.notNull(clazz, "Class must not be null");
boolean declaredLocally = false;
for (Annotation annotation : Arrays.asList(clazz.getDeclaredAnnotations())) {
for (Annotation annotation : clazz.getDeclaredAnnotations()) {
if (annotation.annotationType().equals(annotationType)) {
declaredLocally = true;
break;
@@ -279,16 +280,16 @@ public abstract class AnnotationUtils {
/**
* Determine whether an annotation for the specified {@code annotationType} is present
* on the supplied {@code clazz} and is {@link java.lang.annotation.Inherited inherited}
* i.e., not declared locally for the class).
* on the supplied {@code clazz} and is {@linkplain java.lang.annotation.Inherited inherited}
* (i.e., not declared locally for the class).
* <p>If the supplied {@code clazz} is an interface, only the interface itself will be checked.
* In accordance with standard meta-annotation semantics, the inheritance hierarchy for interfaces
* will not be traversed. See the {@link java.lang.annotation.Inherited JavaDoc} for the
* &#064;Inherited meta-annotation for further details regarding annotation inheritance.
* will not be traversed. See the {@linkplain java.lang.annotation.Inherited Javadoc} for the
* {@code @Inherited} meta-annotation for further details regarding annotation inheritance.
* @param annotationType the Class object corresponding to the annotation type
* @param clazz the Class object corresponding to the class on which to check for the annotation
* @return {@code true} if an annotation for the specified {@code annotationType} is present
* on the supplied {@code clazz} and is {@link java.lang.annotation.Inherited inherited}
* on the supplied {@code clazz} and is <em>inherited</em>
* @see Class#isAnnotationPresent(Class)
* @see #isAnnotationDeclaredLocally(Class, Class)
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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,6 +17,7 @@
package org.springframework.core.convert;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashMap;
@@ -33,6 +34,8 @@ import org.springframework.util.ObjectUtils;
* @author Keith Donald
* @author Andy Clement
* @author Juergen Hoeller
* @author Phillip Webb
* @author Sam Brannen
* @since 3.0
*/
public class TypeDescriptor {
@@ -75,7 +78,8 @@ public class TypeDescriptor {
/**
* Create a new type descriptor from a {@link MethodParameter}.
* Use this constructor when a source or target conversion point is a constructor parameter, method parameter, or method return value.
* <p>Use this constructor when a source or target conversion point is a
* constructor parameter, method parameter, or method return value.
* @param methodParameter the method parameter
*/
public TypeDescriptor(MethodParameter methodParameter) {
@@ -84,7 +88,7 @@ public class TypeDescriptor {
/**
* Create a new type descriptor from a {@link Field}.
* Use this constructor when source or target conversion point is a field.
* <p>Use this constructor when a source or target conversion point is a field.
* @param field the field
*/
public TypeDescriptor(Field field) {
@@ -93,7 +97,8 @@ public class TypeDescriptor {
/**
* Create a new type descriptor from a {@link Property}.
* Use this constructor when a source or target conversion point is a property on a Java class.
* <p>Use this constructor when a source or target conversion point is a
* property on a Java class.
* @param property the property
*/
public TypeDescriptor(Property property) {
@@ -103,8 +108,11 @@ public class TypeDescriptor {
/**
* Create a new type descriptor from the given type.
* Use this to instruct the conversion system to convert an object to a specific target type, when no type location such as a method parameter or field is available to provide additional conversion context.
* Generally prefer use of {@link #forObject(Object)} for constructing type descriptors from source objects, as it handles the null object case.
* <p>Use this to instruct the conversion system to convert an object to a
* specific target type, when no type location such as a method parameter or
* field is available to provide additional conversion context.
* <p>Generally prefer use of {@link #forObject(Object)} for constructing type
* descriptors from source objects, as it handles the {@code null} object case.
* @param type the class
* @return the type descriptor
*/
@@ -114,12 +122,15 @@ public class TypeDescriptor {
}
/**
* Create a new type descriptor from a java.util.Collection type.
* Useful for converting to typed Collections.
* For example, a List&lt;String&gt; could be converted to a List&lt;EmailAddress&gt; by converting to a targetType built with this method.
* The method call to construct such a TypeDescriptor would look something like: collection(List.class, TypeDescriptor.valueOf(EmailAddress.class));
* Create a new type descriptor from a {@link java.util.Collection} type.
* <p>Useful for converting to typed Collections.
* <p>For example, a {@code List<String>} could be converted to a
* {@code List<EmailAddress>} by converting to a targetType built with this method.
* The method call to construct such a {@code TypeDescriptor} would look something
* like: {@code collection(List.class, TypeDescriptor.valueOf(EmailAddress.class));}
* @param collectionType the collection type, which must implement {@link Collection}.
* @param elementTypeDescriptor a descriptor for the collection's element type, used to convert collection elements
* @param elementTypeDescriptor a descriptor for the collection's element type,
* used to convert collection elements
* @return the collection type descriptor
*/
public static TypeDescriptor collection(Class<?> collectionType, TypeDescriptor elementTypeDescriptor) {
@@ -130,9 +141,9 @@ public class TypeDescriptor {
}
/**
* Create a new type descriptor from a java.util.Map type.
* Useful for Converting to typed Maps.
* For example, a Map&lt;String, String&gt; could be converted to a Map&lt;Id, EmailAddress&gt; by converting to a targetType built with this method:
* Create a new type descriptor from a {@link java.util.Map} type.
* <p>Useful for converting to typed Maps.
* <p>For example, a Map&lt;String, String&gt; could be converted to a Map&lt;Id, EmailAddress&gt; by converting to a targetType built with this method:
* The method call to construct such a TypeDescriptor would look something like: map(Map.class, TypeDescriptor.valueOf(Id.class), TypeDescriptor.valueOf(EmailAddress.class));
* @param mapType the map type, which must implement {@link Map}
* @param keyTypeDescriptor a descriptor for the map's key type, used to convert map keys
@@ -146,19 +157,44 @@ public class TypeDescriptor {
return new TypeDescriptor(mapType, keyTypeDescriptor, valueTypeDescriptor);
}
/**
* Create a new type descriptor as an array of the specified type.
* <p>For example to create a {@code Map<String,String>[]} use
* {@code TypeDescriptor.array(TypeDescriptor.map(Map.class, TypeDescriptor.value(String.class), TypeDescriptor.value(String.class)))}.
* @param elementTypeDescriptor the {@link TypeDescriptor} of the array element or {@code null}
* @return an array {@link TypeDescriptor} or {@code null} if {@code elementTypeDescriptor} is {@code null}
* @since 3.2.1
*/
public static TypeDescriptor array(TypeDescriptor elementTypeDescriptor) {
if(elementTypeDescriptor == null) {
return null;
}
Class<?> type = Array.newInstance(elementTypeDescriptor.getType(), 0).getClass();
return new TypeDescriptor(type, elementTypeDescriptor, null, null, elementTypeDescriptor.getAnnotations());
}
/**
* Creates a type descriptor for a nested type declared within the method parameter.
* For example, if the methodParameter is a List&lt;String&gt; and the nestingLevel is 1, the nested type descriptor will be String.class.
* If the methodParameter is a List<List<String>> and the nestingLevel is 2, the nested type descriptor will also be a String.class.
* If the methodParameter is a Map<Integer, String> and the nesting level is 1, the nested type descriptor will be String, derived from the map value.
* If the methodParameter is a List<Map<Integer, String>> and the nesting level is 2, the nested type descriptor will be String, derived from the map value.
* Returns null if a nested type cannot be obtained because it was not declared.
* For example, if the method parameter is a List&lt;?&gt;, the nested type descriptor returned will be <tt>null</tt>.
* <p>For example, if the methodParameter is a {@code List<String>} and the
* nesting level is 1, the nested type descriptor will be String.class.
* <p>If the methodParameter is a {@code List<List<String>>} and the nesting
* level is 2, the nested type descriptor will also be a String.class.
* <p>If the methodParameter is a {@code Map<Integer, String>} and the nesting
* level is 1, the nested type descriptor will be String, derived from the map value.
* <p>If the methodParameter is a {@code List<Map<Integer, String>>} and the
* nesting level is 2, the nested type descriptor will be String, derived from the map value.
* <p>Returns {@code null} if a nested type cannot be obtained because it was not declared.
* For example, if the method parameter is a {@code List<?>}, the nested type
* descriptor returned will be {@code null}.
* @param methodParameter the method parameter with a nestingLevel of 1
* @param nestingLevel the nesting level of the collection/array element or map key/value declaration within the method parameter
* @return the nested type descriptor at the specified nesting level, or null if it could not be obtained
* @throws IllegalArgumentException if the nesting level of the input {@link MethodParameter} argument is not 1
* @throws IllegalArgumentException if the types up to the specified nesting level are not of collection, array, or map types
* @param nestingLevel the nesting level of the collection/array element or
* map key/value declaration within the method parameter
* @return the nested type descriptor at the specified nesting level, or null
* if it could not be obtained
* @throws IllegalArgumentException if the nesting level of the input
* {@link MethodParameter} argument is not 1
* @throws IllegalArgumentException if the types up to the specified nesting
* level are not of collection, array, or map types
*/
public static TypeDescriptor nested(MethodParameter methodParameter, int nestingLevel) {
if (methodParameter.getNestingLevel() != 1) {
@@ -169,16 +205,23 @@ public class TypeDescriptor {
/**
* Creates a type descriptor for a nested type declared within the field.
* <p>For example, if the field is a {@code List&lt;String&gt;} and the nestingLevel is 1, the nested type descriptor will be {@code String.class}.
* If the field is a {@code List&lt;List&lt;String&gt;&gt;} and the nestingLevel is 2, the nested type descriptor will also be a {@code String.class}.
* If the field is a {@code Map&lt;Integer, String&gt;} and the nestingLevel is 1, the nested type descriptor will be String, derived from the map value.
* If the field is a {@code List&lt;Map&lt;Integer, String&gt;&gt;} and the nestingLevel is 2, the nested type descriptor will be String, derived from the map value.
* Returns {@code null} if a nested type cannot be obtained because it was not declared.
* For example, if the field is a {@code List&lt;?&gt;}, the nested type descriptor returned will be {@code null}.
* <p>For example, if the field is a {@code List<String>} and the nesting
* level is 1, the nested type descriptor will be {@code String.class}.
* <p>If the field is a {@code List<List<String>>} and the nesting level is
* 2, the nested type descriptor will also be a {@code String.class}.
* <p>If the field is a {@code Map<Integer, String>} and the nesting level
* is 1, the nested type descriptor will be String, derived from the map value.
* <p>If the field is a {@code List<Map<Integer, String>>} and the nesting
* level is 2, the nested type descriptor will be String, derived from the map value.
* <p>Returns {@code null} if a nested type cannot be obtained because it was not declared.
* For example, if the field is a {@code List<?>}, the nested type descriptor returned will be {@code null}.
* @param field the field
* @param nestingLevel the nesting level of the collection/array element or map key/value declaration within the field
* @return the nested type descriptor at the specified nestingLevel, or null if it could not be obtained
* @throws IllegalArgumentException if the types up to the specified nesting level are not of collection, array, or map types
* @param nestingLevel the nesting level of the collection/array element or
* map key/value declaration within the field
* @return the nested type descriptor at the specified nesting level, or null
* if it could not be obtained
* @throws IllegalArgumentException if the types up to the specified nesting
* level are not of collection, array, or map types
*/
public static TypeDescriptor nested(Field field, int nestingLevel) {
return nested(new FieldDescriptor(field), nestingLevel);
@@ -186,16 +229,24 @@ public class TypeDescriptor {
/**
* Creates a type descriptor for a nested type declared within the property.
* <p>For example, if the property is a {@code List&lt;String&gt;} and the nestingLevel is 1, the nested type descriptor will be {@code String.class}.
* If the property is a {@code List&lt;List&lt;String&gt;&gt;} and the nestingLevel is 2, the nested type descriptor will also be a {@code String.class}.
* If the property is a {@code Map&lt;Integer, String&gt;} and the nestingLevel is 1, the nested type descriptor will be String, derived from the map value.
* If the property is a {@code List&lt;Map&lt;Integer, String&gt;&gt;} and the nestingLevel is 2, the nested type descriptor will be String, derived from the map value.
* Returns {@code null} if a nested type cannot be obtained because it was not declared.
* For example, if the property is a {@code List&lt;?&gt;}, the nested type descriptor returned will be {@code null}.
* <p>For example, if the property is a {@code List<String>} and the nesting
* level is 1, the nested type descriptor will be {@code String.class}.
* <p>If the property is a {@code List<List<String>>} and the nesting level
* is 2, the nested type descriptor will also be a {@code String.class}.
* <p>If the property is a {@code Map<Integer, String>} and the nesting level
* is 1, the nested type descriptor will be String, derived from the map value.
* <p>If the property is a {@code List<Map<Integer, String>>} and the nesting
* level is 2, the nested type descriptor will be String, derived from the map value.
* <p>Returns {@code null} if a nested type cannot be obtained because it was not declared.
* For example, if the property is a {@code List<?>}, the nested type descriptor
* returned will be {@code null}.
* @param property the property
* @param nestingLevel the nesting level of the collection/array element or map key/value declaration within the property
* @return the nested type descriptor at the specified nestingLevel, or {@code null} if it could not be obtained
* @throws IllegalArgumentException if the types up to the specified nesting level are not of collection, array, or map types
* @param nestingLevel the nesting level of the collection/array element or
* map key/value declaration within the property
* @return the nested type descriptor at the specified nesting level, or
* {@code null} if it could not be obtained
* @throws IllegalArgumentException if the types up to the specified nesting
* level are not of collection, array, or map types
*/
public static TypeDescriptor nested(Property property, int nestingLevel) {
return nested(new BeanPropertyDescriptor(property), nestingLevel);
@@ -203,8 +254,8 @@ public class TypeDescriptor {
/**
* Create a new type descriptor for an object.
* Use this factory method to introspect a source object before asking the conversion system to convert it to some another type.
* If the provided object is null, returns null, else calls {@link #valueOf(Class)} to build a TypeDescriptor from the object's class.
* <p>Use this factory method to introspect a source object before asking the conversion system to convert it to some another type.
* <p>If the provided object is null, returns null, else calls {@link #valueOf(Class)} to build a TypeDescriptor from the object's class.
* @param source the source object
* @return the type descriptor
*/
@@ -214,7 +265,7 @@ public class TypeDescriptor {
/**
* The type of the backing class, method parameter, field, or property described by this TypeDescriptor.
* Returns primitive types as-is.
* <p>Returns primitive types as-is.
* <p>See {@link #getObjectType()} for a variation of this operation that resolves primitive types
* to their corresponding Object types if necessary.
* @return the type, or {@code null}
@@ -235,7 +286,7 @@ public class TypeDescriptor {
/**
* Narrows this {@link TypeDescriptor} by setting its type to the class of the provided value.
* If the value is {@code null}, no narrowing is performed and this TypeDescriptor is returned unchanged.
* <p>If the value is {@code null}, no narrowing is performed and this TypeDescriptor is returned unchanged.
* <p>Designed to be called by binding frameworks when they read property, field, or method return values.
* Allows such frameworks to narrow a TypeDescriptor built from a declared property, field, or method return value type.
* For example, a field declared as {@code java.lang.Object} would be narrowed to {@code java.util.HashMap}
@@ -255,7 +306,6 @@ public class TypeDescriptor {
/**
* Cast this {@link TypeDescriptor} to a superclass or implemented interface
* preserving annotations and nested type context.
*
* @param superType the super type to cast to (can be {@code null}
* @return a new TypeDescriptor for the up-cast type
* @throws IllegalArgumentException if this type is not assignable to the super-type
@@ -324,7 +374,7 @@ public class TypeDescriptor {
/**
* Returns true if an object of this type descriptor can be assigned to the location described by the given type descriptor.
* For example, valueOf(String.class).isAssignableTo(valueOf(CharSequence.class)) returns true because a String value can be assigned to a CharSequence variable.
* <p>For example, valueOf(String.class).isAssignableTo(valueOf(CharSequence.class)) returns true because a String value can be assigned to a CharSequence variable.
* On the other hand, valueOf(Number.class).isAssignableTo(valueOf(Integer.class)) returns false because, while all Integers are Numbers, not all Numbers are Integers.
* <p>
* For arrays, collections, and maps, element and key/value types are checked if declared.
@@ -382,10 +432,10 @@ public class TypeDescriptor {
/**
* If this type is a {@link Collection} or an Array, creates a element TypeDescriptor from the provided collection or array element.
* Narrows the {@link #getElementTypeDescriptor() elementType} property to the class of the provided collection or array element.
* <p>Narrows the {@link #getElementTypeDescriptor() elementType} property to the class of the provided collection or array element.
* For example, if this describes a java.util.List&lt;java.lang.Number&lt; and the element argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
* If this describes a java.util.List&lt;?&gt; and the element argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well.
* Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
* <p>Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
* @param element the collection or array element
* @return a element type descriptor, narrowed to the type of the provided element
* @throws IllegalStateException if this type is not a java.util.Collection or Array type
@@ -417,10 +467,10 @@ public class TypeDescriptor {
/**
* If this type is a {@link Map}, creates a mapKey {@link TypeDescriptor} from the provided map key.
* Narrows the {@link #getMapKeyTypeDescriptor() mapKeyType} property to the class of the provided map key.
* <p>Narrows the {@link #getMapKeyTypeDescriptor() mapKeyType} property to the class of the provided map key.
* For example, if this describes a java.util.Map&lt;java.lang.Number, java.lang.String&lt; and the key argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
* If this describes a java.util.Map&lt;?, ?&gt; and the key argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well.
* Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
* <p>If this describes a java.util.Map&lt;?, ?&gt; and the key argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well.
* <p>Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
* @param mapKey the map key
* @return the map key type descriptor
* @throws IllegalStateException if this type is not a java.util.Map
@@ -432,7 +482,7 @@ public class TypeDescriptor {
/**
* If this type is a {@link Map} and its value type is parameterized, returns the map's value type.
* If the Map's value type is not parameterized, returns null indicating the value type is not declared.
* <p>If the Map's value type is not parameterized, returns null indicating the value type is not declared.
* @return the Map value type, or {@code null} if this type is a Map but its value type is not parameterized
* @throws IllegalStateException if this type is not a java.util.Map
*/
@@ -443,10 +493,10 @@ public class TypeDescriptor {
/**
* If this type is a {@link Map}, creates a mapValue {@link TypeDescriptor} from the provided map value.
* Narrows the {@link #getMapValueTypeDescriptor() mapValueType} property to the class of the provided map value.
* <p>Narrows the {@link #getMapValueTypeDescriptor() mapValueType} property to the class of the provided map value.
* For example, if this describes a java.util.Map&lt;java.lang.String, java.lang.Number&lt; and the value argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
* If this describes a java.util.Map&lt;?, ?&gt; and the value argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well.
* Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
* <p>Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
* @param mapValue the map value
* @return the map value type descriptor
* @throws IllegalStateException if this type is not a java.util.Map

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -18,6 +18,7 @@ package org.springframework.core.convert.support;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.util.Assert;
/**
* Converts from a String to a java.lang.Enum by calling {@link Enum#valueOf(Class, String)}.
@@ -29,7 +30,13 @@ import org.springframework.core.convert.converter.ConverterFactory;
final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {
public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
return new StringToEnum(targetType);
Class<?> enumType = targetType;
while(enumType != null && !enumType.isEnum()) {
enumType = enumType.getSuperclass();
}
Assert.notNull(enumType, "The target type " + targetType.getName()
+ " does not refer to an enum");
return new StringToEnum(enumType);
}
private class StringToEnum<T extends Enum> implements Converter<String, T> {

View File

@@ -41,4 +41,4 @@ public class MapPropertySource extends EnumerablePropertySource<Map<String, Obje
return this.source.keySet().toArray(EMPTY_NAMES_ARRAY);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2013 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.
@@ -31,13 +31,12 @@ import java.util.Properties;
*
* @author Chris Beams
* @since 3.1
* @see org.springframework.mock.env.MockPropertySource
*/
public class PropertiesPropertySource extends MapPropertySource {
@SuppressWarnings({ "unchecked", "rawtypes" })
public PropertiesPropertySource(String name, Properties source) {
super(name, (Map)source);
super(name, (Map) source);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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,17 +17,21 @@
package org.springframework.core.env;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import org.springframework.util.Assert;
/**
* Read-only {@code Map<String, String>} implementation that is backed by system properties or environment
* variables.
* Read-only {@code Map<String, String>} implementation that is backed by system
* properties or environment variables.
*
* <p>Used by {@link AbstractApplicationContext} when a {@link SecurityManager} prohibits access to {@link
* System#getProperties()} or {@link System#getenv()}.
* <p>Used by {@link AbstractApplicationContext} when a {@link SecurityManager} prohibits
* access to {@link System#getProperties()} or {@link System#getenv()}. It is for this
* reason that the implementations of {@link #keySet()}, {@link #entrySet()}, and
* {@link #values()} always return empty even though {@link #get(Object)} may in fact
* return non-null if the current security manager allows access to individual keys.
*
* @author Arjen Poutsma
* @author Chris Beams
@@ -85,7 +89,7 @@ abstract class ReadOnlySystemAttributesMap implements Map<String, String> {
}
public Set<String> keySet() {
throw new UnsupportedOperationException();
return Collections.emptySet();
}
public void putAll(Map<? extends String, ? extends String> m) {
@@ -93,11 +97,11 @@ abstract class ReadOnlySystemAttributesMap implements Map<String, String> {
}
public Collection<String> values() {
throw new UnsupportedOperationException();
return Collections.emptySet();
}
public Set<Entry<String, String>> entrySet() {
throw new UnsupportedOperationException();
return Collections.emptySet();
}
}

View File

@@ -83,4 +83,4 @@ class SimpleCommandLineArgsParser {
return commandLineArgs;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2013 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.
@@ -76,7 +76,7 @@ public class SystemEnvironmentPropertySource extends MapPropertySource {
*/
@Override
public boolean containsProperty(String name) {
return resolvePropertyName(name) != null;
return getProperty(name) != null;
}
/**
@@ -88,10 +88,6 @@ public class SystemEnvironmentPropertySource extends MapPropertySource {
public Object getProperty(String name) {
Assert.notNull(name, "property name must not be null");
String actualName = resolvePropertyName(name);
if (actualName == null) {
// at this point we know the property does not exist
return null;
}
if (logger.isDebugEnabled() && !name.equals(actualName)) {
logger.debug(String.format(
"PropertySource [%s] does not contain '%s', but found equivalent '%s'",
@@ -102,8 +98,8 @@ public class SystemEnvironmentPropertySource extends MapPropertySource {
/**
* Check to see if this property source contains a property with the given name, or
* any underscore / uppercase variation thereof. Return the resolved name or
* {@code null} if none found.
* any underscore / uppercase variation thereof. Return the resolved name if one is
* found or otherwise the original name. Never returns {@code null}.
*/
private String resolvePropertyName(String name) {
if (super.containsProperty(name)) {
@@ -127,6 +123,6 @@ public class SystemEnvironmentPropertySource extends MapPropertySource {
}
}
return null;
return name;
}
}

View File

@@ -205,18 +205,14 @@ public class ClassPathResource extends AbstractFileResolvingResource {
*/
public String getDescription() {
StringBuilder builder = new StringBuilder("class path resource [");
String pathToUse = path;
if (this.clazz != null && !pathToUse.startsWith("/")) {
builder.append(ClassUtils.classPackageAsResourcePath(this.clazz));
builder.append('/');
}
if (pathToUse.startsWith("/")) {
pathToUse = pathToUse.substring(1);
}
builder.append(pathToUse);
builder.append(']');
return builder.toString();
@@ -232,9 +228,9 @@ public class ClassPathResource extends AbstractFileResolvingResource {
}
if (obj instanceof ClassPathResource) {
ClassPathResource otherRes = (ClassPathResource) obj;
return (this.path.equals(otherRes.path)
&& ObjectUtils.nullSafeEquals(this.classLoader, otherRes.classLoader) && ObjectUtils.nullSafeEquals(
this.clazz, otherRes.clazz));
return (this.path.equals(otherRes.path) &&
ObjectUtils.nullSafeEquals(this.classLoader, otherRes.classLoader) &&
ObjectUtils.nullSafeEquals(this.clazz, otherRes.clazz));
}
return false;
}

View File

@@ -257,4 +257,4 @@ public abstract class VfsUtils {
protected static String doGetPath(Object resource) {
return (String) ReflectionUtils.invokeMethod(VIRTUAL_FILE_METHOD_GET_PATH_NAME, resource);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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,8 +17,10 @@
package org.springframework.core.io.support;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
@@ -39,7 +41,9 @@ public class EncodedResource {
private final Resource resource;
private final String encoding;
private String encoding;
private Charset charset;
/**
@@ -48,7 +52,8 @@ public class EncodedResource {
* @param resource the Resource to hold
*/
public EncodedResource(Resource resource) {
this(resource, null);
Assert.notNull(resource, "Resource must not be null");
this.resource = resource;
}
/**
@@ -63,6 +68,18 @@ public class EncodedResource {
this.encoding = encoding;
}
/**
* Create a new EncodedResource for the given Resource,
* using the specified encoding.
* @param resource the Resource to hold
* @param charset the charset to use for reading from the resource
*/
public EncodedResource(Resource resource, Charset charset) {
Assert.notNull(resource, "Resource must not be null");
this.resource = resource;
this.charset = charset;
}
/**
* Return the Resource held.
@@ -79,13 +96,36 @@ public class EncodedResource {
return this.encoding;
}
/**
* Return the charset to use for reading from the resource,
* or {@code null} if none specified.
*/
public final Charset getCharset() {
return this.charset;
}
/**
* Determine whether a {@link Reader} is required as opposed to an {@link InputStream},
* i.e. whether an encoding or a charset has been specified.
* @see #getReader()
* @see #getInputStream()
*/
public boolean requiresReader() {
return (this.encoding != null || this.charset != null);
}
/**
* Open a {@code java.io.Reader} for the specified resource,
* using the specified encoding (if any).
* @throws IOException if opening the Reader failed
* @see #requiresReader()
*/
public Reader getReader() throws IOException {
if (this.encoding != null) {
if (this.charset != null) {
return new InputStreamReader(this.resource.getInputStream(), this.charset);
}
else if (this.encoding != null) {
return new InputStreamReader(this.resource.getInputStream(), this.encoding);
}
else {
@@ -93,6 +133,16 @@ public class EncodedResource {
}
}
/**
* Open an {@code java.io.InputStream} for the specified resource,
* typically assuming that there is no specific encoding to use.
* @throws IOException if opening the InputStream failed
* @see #requiresReader()
*/
public InputStream getInputStream() throws IOException {
return this.resource.getInputStream();
}
@Override
public boolean equals(Object obj) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -658,6 +658,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
/**
* VFS visitor for path matching purposes.
*/
@SuppressWarnings("unused")
private static class PatternVirtualFileVisitor implements InvocationHandler {
private final String subPattern;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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,8 +17,6 @@
package org.springframework.core.io.support;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
import org.apache.commons.logging.Log;
@@ -39,9 +37,6 @@ import org.springframework.util.PropertiesPersister;
*/
public abstract class PropertiesLoaderSupport {
public static final String XML_FILE_EXTENSION = ".xml";
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
@@ -167,7 +162,7 @@ public abstract class PropertiesLoaderSupport {
/**
* Load properties into the given instance.
* @param props the Properties instance to load into
* @throws java.io.IOException in case of I/O errors
* @throws IOException in case of I/O errors
* @see #setLocations
*/
protected void loadProperties(Properties props) throws IOException {
@@ -176,21 +171,9 @@ public abstract class PropertiesLoaderSupport {
if (logger.isInfoEnabled()) {
logger.info("Loading properties file from " + location);
}
InputStream is = null;
try {
is = location.getInputStream();
String filename = location.getFilename();
if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
this.propertiesPersister.loadFromXml(props, is);
}
else {
if (this.fileEncoding != null) {
this.propertiesPersister.load(props, new InputStreamReader(is, this.fileEncoding));
}
else {
this.propertiesPersister.load(props, is);
}
}
PropertiesLoaderUtils.fillProperties(
props, new EncodedResource(location, this.fileEncoding), this.propertiesPersister);
}
catch (IOException ex) {
if (this.ignoreResourceNotFound) {
@@ -202,11 +185,6 @@ public abstract class PropertiesLoaderSupport {
throw ex;
}
}
finally {
if (is != null) {
is.close();
}
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -18,6 +18,7 @@ package org.springframework.core.io.support;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
@@ -26,6 +27,8 @@ import java.util.Properties;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.DefaultPropertiesPersister;
import org.springframework.util.PropertiesPersister;
import org.springframework.util.ResourceUtils;
/**
@@ -42,11 +45,76 @@ import org.springframework.util.ResourceUtils;
*/
public abstract class PropertiesLoaderUtils {
private static final String XML_FILE_EXTENSION = ".xml";
/**
* Load properties from the given resource.
* Load properties from the given EncodedResource,
* potentially defining a specific encoding for the properties file.
* @see #fillProperties(java.util.Properties, EncodedResource)
*/
public static Properties loadProperties(EncodedResource resource) throws IOException {
Properties props = new Properties();
fillProperties(props, resource);
return props;
}
/**
* Fill the given properties from the given EncodedResource,
* potentially defining a specific encoding for the properties file.
* @param props the Properties instance to load into
* @param resource the resource to load from
* @throws IOException in case of I/O errors
*/
public static void fillProperties(Properties props, EncodedResource resource)
throws IOException {
fillProperties(props, resource, new DefaultPropertiesPersister());
}
/**
* Actually load properties from the given EncodedResource into the given Properties instance.
* @param props the Properties instance to load into
* @param resource the resource to load from
* @param persister the PropertiesPersister to use
* @throws IOException in case of I/O errors
*/
static void fillProperties(Properties props, EncodedResource resource, PropertiesPersister persister)
throws IOException {
InputStream stream = null;
Reader reader = null;
try {
String filename = resource.getResource().getFilename();
if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
stream = resource.getInputStream();
persister.loadFromXml(props, stream);
}
else if (resource.requiresReader()) {
reader = resource.getReader();
persister.load(props, reader);
}
else {
stream = resource.getInputStream();
persister.load(props, stream);
}
}
finally {
if (stream != null) {
stream.close();
}
if (reader != null) {
reader.close();
}
}
}
/**
* Load properties from the given resource (in ISO-8859-1 encoding).
* @param resource the resource to load from
* @return the populated Properties instance
* @throws IOException if loading failed
* @see #fillProperties(java.util.Properties, Resource)
*/
public static Properties loadProperties(Resource resource) throws IOException {
Properties props = new Properties();
@@ -55,7 +123,7 @@ public abstract class PropertiesLoaderUtils {
}
/**
* Fill the given properties from the given resource.
* Fill the given properties from the given resource (in ISO-8859-1 encoding).
* @param props the Properties instance to fill
* @param resource the resource to load from
* @throws IOException if loading failed
@@ -63,7 +131,13 @@ public abstract class PropertiesLoaderUtils {
public static void fillProperties(Properties props, Resource resource) throws IOException {
InputStream is = resource.getInputStream();
try {
props.load(is);
String filename = resource.getFilename();
if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
props.loadFromXML(is);
}
else {
props.load(is);
}
}
finally {
is.close();
@@ -71,8 +145,8 @@ public abstract class PropertiesLoaderUtils {
}
/**
* Load all properties from the given class path resource,
* using the default class loader.
* Load all properties from the specified class path resource
* (in ISO-8859-1 encoding), using the default class loader.
* <p>Merges properties if more than one resource of the same name
* found in the class path.
* @param resourceName the name of the class path resource
@@ -84,8 +158,8 @@ public abstract class PropertiesLoaderUtils {
}
/**
* Load all properties from the given class path resource,
* using the given class loader.
* Load all properties from the specified class path resource
* (in ISO-8859-1 encoding), using the given class loader.
* <p>Merges properties if more than one resource of the same name
* found in the class path.
* @param resourceName the name of the class path resource
@@ -100,24 +174,26 @@ public abstract class PropertiesLoaderUtils {
if (clToUse == null) {
clToUse = ClassUtils.getDefaultClassLoader();
}
Properties properties = new Properties();
Properties props = new Properties();
Enumeration urls = clToUse.getResources(resourceName);
while (urls.hasMoreElements()) {
URL url = (URL) urls.nextElement();
InputStream is = null;
URLConnection con = url.openConnection();
ResourceUtils.useCachesIfNecessary(con);
InputStream is = con.getInputStream();
try {
URLConnection con = url.openConnection();
ResourceUtils.useCachesIfNecessary(con);
is = con.getInputStream();
properties.load(is);
}
finally {
if (is != null) {
is.close();
if (resourceName != null && resourceName.endsWith(XML_FILE_EXTENSION)) {
props.loadFromXML(is);
}
else {
props.load(is);
}
}
finally {
is.close();
}
}
return properties;
return props;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2013 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,30 +17,51 @@
package org.springframework.core.io.support;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Subclass of {@link PropertiesPropertySource} that loads a {@link Properties}
* object from a given {@link org.springframework.core.io.Resource} or resource location such as
* {@code "classpath:/com/myco/foo.properties"} or {@code "file:/path/to/file.properties"}.
* {@code "classpath:/com/myco/foo.properties"} or {@code "file:/path/to/file.xml"}.
* Both traditional and XML-based properties file formats are supported, however in order
* for XML processing to take effect, the underlying {@code Resource}'s
* {@link org.springframework.core.io.Resource#getFilename() getFilename()} method must
* return non-{@code null} and end in ".xml".
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
*/
public class ResourcePropertySource extends PropertiesPropertySource {
/**
* Create a PropertySource having the given name based on Properties
* loaded from the given resource.
* loaded from the given encoded resource.
*/
public ResourcePropertySource(String name, EncodedResource resource) throws IOException {
super(name, PropertiesLoaderUtils.loadProperties(resource));
}
/**
* Create a PropertySource based on Properties loaded from the given resource.
* The name of the PropertySource will be generated based on the
* {@link Resource#getDescription() description} of the given resource.
*/
public ResourcePropertySource(EncodedResource resource) throws IOException {
this(getNameForResource(resource.getResource()), resource);
}
/**
* Create a PropertySource having the given name based on Properties
* loaded from the given encoded resource.
*/
public ResourcePropertySource(String name, Resource resource) throws IOException {
super(name, loadPropertiesForResource(resource));
super(name, PropertiesLoaderUtils.loadProperties(new EncodedResource(resource)));
}
/**
@@ -58,17 +79,7 @@ public class ResourcePropertySource extends PropertiesPropertySource {
* resource (assuming it is prefixed with {@code classpath:}).
*/
public ResourcePropertySource(String name, String location, ClassLoader classLoader) throws IOException {
this(name, getResourceForLocation(location, classLoader));
}
/**
* Create a PropertySource having the given name based on Properties loaded from
* the given resource location. The default thread context class loader will be
* used to load the resource (assuming the location string is prefixed with
* {@code classpath:}.
*/
public ResourcePropertySource(String name, String location) throws IOException {
this(name, location, ClassUtils.getDefaultClassLoader());
this(name, new DefaultResourceLoader(classLoader).getResource(location));
}
/**
@@ -79,7 +90,17 @@ public class ResourcePropertySource extends PropertiesPropertySource {
* resource.
*/
public ResourcePropertySource(String location, ClassLoader classLoader) throws IOException {
this(getResourceForLocation(location, classLoader));
this(new DefaultResourceLoader(classLoader).getResource(location));
}
/**
* Create a PropertySource having the given name based on Properties loaded from
* the given resource location. The default thread context class loader will be
* used to load the resource (assuming the location string is prefixed with
* {@code classpath:}.
*/
public ResourcePropertySource(String name, String location) throws IOException {
this(name, new DefaultResourceLoader().getResource(location));
}
/**
@@ -88,28 +109,12 @@ public class ResourcePropertySource extends PropertiesPropertySource {
* {@link Resource#getDescription() description} of the resource.
*/
public ResourcePropertySource(String location) throws IOException {
this(getResourceForLocation(location, ClassUtils.getDefaultClassLoader()));
this(new DefaultResourceLoader().getResource(location));
}
private static Resource getResourceForLocation(String location, ClassLoader classLoader) {
return new PathMatchingResourcePatternResolver(classLoader).getResource(location);
}
private static Properties loadPropertiesForResource(Resource resource) throws IOException {
Properties props = new Properties();
InputStream is = resource.getInputStream();
props.load(is);
try {
is.close();
} catch (IOException ex) {
// ignore
}
return props;
}
/**
* Returns the description string for the resource, and if empty returns
* Return the description string for the resource, and if empty returns
* the class name of the resource plus its identity hash code.
*/
private static String getNameForResource(Resource resource) {

View File

@@ -258,4 +258,4 @@ final class AnnotationAttributesReadingVisitor extends RecursiveAnnotationAttrib
this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames);
}
}
}
}

View File

@@ -97,4 +97,4 @@ final class MethodMetadataReadingVisitor extends MethodVisitor implements Method
public String getDeclaringClassName() {
return this.declaringClassName;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -21,6 +21,7 @@ import java.io.IOException;
import java.io.InputStream;
import org.springframework.asm.ClassReader;
import org.springframework.core.NestedIOException;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
@@ -47,10 +48,14 @@ final class SimpleMetadataReader implements MetadataReader {
SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException {
InputStream is = new BufferedInputStream(resource.getInputStream());
ClassReader classReader = null;
ClassReader classReader;
try {
classReader = new ClassReader(is);
}
catch (IllegalArgumentException ex) {
throw new NestedIOException("ASM ClassReader failed to parse class file - " +
"probably due to a new Java class file version that isn't supported yet: " + resource, ex);
}
finally {
is.close();
}
@@ -64,6 +69,7 @@ final class SimpleMetadataReader implements MetadataReader {
this.resource = resource;
}
public Resource getResource() {
return this.resource;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -60,12 +60,18 @@ public class AntPathMatcher implements PathMatcher {
private final Map<String, AntPathStringMatcher> stringMatcherCache =
new ConcurrentHashMap<String, AntPathStringMatcher>(256);
private boolean trimTokens = true;
/** Set the path separator to use for pattern parsing. Default is "/", as in Ant. */
public void setPathSeparator(String pathSeparator) {
this.pathSeparator = (pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR);
}
/** Whether to trim tokenized paths and patterns. */
public void setTrimTokens(boolean trimTokens) {
this.trimTokens = trimTokens;
}
public boolean isPattern(String path) {
return (path.indexOf('*') != -1 || path.indexOf('?') != -1);
@@ -95,8 +101,8 @@ public class AntPathMatcher implements PathMatcher {
return false;
}
String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator);
String[] pathDirs = StringUtils.tokenizeToStringArray(path, this.pathSeparator);
String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator, this.trimTokens, true);
String[] pathDirs = StringUtils.tokenizeToStringArray(path, this.pathSeparator, this.trimTokens, true);
int pattIdxStart = 0;
int pattIdxEnd = pattDirs.length - 1;
@@ -246,8 +252,8 @@ public class AntPathMatcher implements PathMatcher {
* does <strong>not</strong> enforce this.
*/
public String extractPathWithinPattern(String pattern, String path) {
String[] patternParts = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator);
String[] pathParts = StringUtils.tokenizeToStringArray(path, this.pathSeparator);
String[] patternParts = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator, this.trimTokens, true);
String[] pathParts = StringUtils.tokenizeToStringArray(path, this.pathSeparator, this.trimTokens, true);
StringBuilder builder = new StringBuilder();
@@ -311,7 +317,9 @@ public class AntPathMatcher implements PathMatcher {
else if (!StringUtils.hasText(pattern2)) {
return pattern1;
}
else if (!pattern1.equals(pattern2) && !pattern1.contains("{") && match(pattern1, pattern2)) {
boolean pattern1ContainsUriVar = pattern1.indexOf('{') != -1;
if (!pattern1.equals(pattern2) && !pattern1ContainsUriVar && match(pattern1, pattern2)) {
// /* + /hotel -> /hotel ; "/*.*" + "/*.html" -> /*.html
// However /user + /user -> /usr/user ; /{foo} + /bar -> /{foo}/bar
return pattern2;
@@ -338,7 +346,7 @@ public class AntPathMatcher implements PathMatcher {
}
else {
int dotPos1 = pattern1.indexOf('.');
if (dotPos1 == -1) {
if (dotPos1 == -1 || pattern1ContainsUriVar) {
// simply concatenate the two patterns
if (pattern1.endsWith("/") || pattern2.startsWith("/")) {
return pattern1 + pattern2;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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
@@ -334,8 +334,9 @@ public abstract class Assert {
public static void isInstanceOf(Class type, Object obj, String message) {
notNull(type, "Type to check against must not be null");
if (!type.isInstance(obj)) {
throw new IllegalArgumentException(message +
". Object of class [" + (obj != null ? obj.getClass().getName() : "null") +
throw new IllegalArgumentException(
(StringUtils.hasLength(message) ? message + " " : "") +
"Object of class [" + (obj != null ? obj.getClass().getName() : "null") +
"] must be an instance of " + type);
}
}

View File

@@ -72,4 +72,4 @@ public class CompositeIterator<E> implements Iterator<E> {
public void remove() {
throw new UnsupportedOperationException("Remove is not supported");
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -33,8 +33,8 @@ import java.util.Properties;
*
* <p>Allows for reading from any Reader and writing to any Writer, for example
* to specify a charset for a properties file. This is a capability that standard
* {@code java.util.Properties} unfortunately lacks up until JDK 1.5:
* You can only load files using the ISO-8859-1 charset there.
* {@code java.util.Properties} unfortunately lacked up until JDK 1.5:
* You were only able to load files using the ISO-8859-1 charset there.
*
* <p>Loading from and storing to a stream delegates to {@code Properties.load}
* and {@code Properties.store}, respectively, to be fully compatible with
@@ -49,20 +49,11 @@ import java.util.Properties;
* an encoding for a Reader/Writer (like ReloadableResourceBundleMessageSource's
* "defaultEncoding" and "fileEncodings" properties).
*
* <p>As of Spring 1.2.2, this implementation also supports properties XML files,
* through the {@code loadFromXml} and {@code storeToXml} methods.
* The default implementations delegate to JDK 1.5's corresponding methods,
* throwing an exception if running on an older JDK. Those implementations
* could be subclassed to apply custom XML handling on JDK 1.4, for example.
*
* @author Juergen Hoeller
* @since 10.03.2004
* @see java.util.Properties
* @see java.util.Properties#load
* @see java.util.Properties#store
* @see org.springframework.context.support.ReloadableResourceBundleMessageSource#setPropertiesPersister
* @see org.springframework.context.support.ReloadableResourceBundleMessageSource#setDefaultEncoding
* @see org.springframework.context.support.ReloadableResourceBundleMessageSource#setFileEncodings
*/
public class DefaultPropertiesPersister implements PropertiesPersister {
@@ -228,30 +219,15 @@ public class DefaultPropertiesPersister implements PropertiesPersister {
public void loadFromXml(Properties props, InputStream is) throws IOException {
try {
props.loadFromXML(is);
}
catch (NoSuchMethodError err) {
throw new IOException("Cannot load properties XML file - not running on JDK 1.5+: " + err.getMessage());
}
props.loadFromXML(is);
}
public void storeToXml(Properties props, OutputStream os, String header) throws IOException {
try {
props.storeToXML(os, header);
}
catch (NoSuchMethodError err) {
throw new IOException("Cannot store properties XML file - not running on JDK 1.5+: " + err.getMessage());
}
props.storeToXML(os, header);
}
public void storeToXml(Properties props, OutputStream os, String header, String encoding) throws IOException {
try {
props.storeToXML(os, header, encoding);
}
catch (NoSuchMethodError err) {
throw new IOException("Cannot store properties XML file - not running on JDK 1.5+: " + err.getMessage());
}
props.storeToXML(os, header, encoding);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -31,19 +31,19 @@ import java.io.StringWriter;
import java.io.Writer;
/**
* Simple utility methods for file and stream copying.
* All copy methods use a block size of 4096 bytes,
* and close all affected streams when done.
* Simple utility methods for file and stream copying. All copy methods use a block size
* of 4096 bytes, and close all affected streams when done. A variation of the copy
* methods from this class that leave streams open can be found in {@link StreamUtils}.
*
* <p>Mainly for use within the framework,
* but also useful for application code.
* <p>Mainly for use within the framework, but also useful for application code.
*
* @author Juergen Hoeller
* @since 06.10.2003
* @see StreamUtils
*/
public abstract class FileCopyUtils {
public static final int BUFFER_SIZE = 4096;
public static final int BUFFER_SIZE = StreamUtils.BUFFER_SIZE;
//---------------------------------------------------------------------
@@ -106,15 +106,7 @@ public abstract class FileCopyUtils {
Assert.notNull(in, "No InputStream specified");
Assert.notNull(out, "No OutputStream specified");
try {
int byteCount = 0;
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = -1;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
byteCount += bytesRead;
}
out.flush();
return byteCount;
return StreamUtils.copy(in, out);
}
finally {
try {
@@ -208,7 +200,7 @@ public abstract class FileCopyUtils {
/**
* Copy the contents of the given String to the given output Writer.
* Closes the write when done.
* Closes the writer when done.
* @param in the String to copy from
* @param out the Writer to copy to
* @throws IOException in case of I/O errors

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -481,7 +481,7 @@ public abstract class ObjectUtils {
}
/**
* Return the same value as {@code {@link Boolean#hashCode()}}.
* Return the same value as {@link Boolean#hashCode()}}.
* @see Boolean#hashCode()
*/
public static int hashCode(boolean bool) {
@@ -489,7 +489,7 @@ public abstract class ObjectUtils {
}
/**
* Return the same value as {@code {@link Double#hashCode()}}.
* Return the same value as {@link Double#hashCode()}}.
* @see Double#hashCode()
*/
public static int hashCode(double dbl) {
@@ -498,7 +498,7 @@ public abstract class ObjectUtils {
}
/**
* Return the same value as {@code {@link Float#hashCode()}}.
* Return the same value as {@link Float#hashCode()}}.
* @see Float#hashCode()
*/
public static int hashCode(float flt) {
@@ -506,7 +506,7 @@ public abstract class ObjectUtils {
}
/**
* Return the same value as {@code {@link Long#hashCode()}}.
* Return the same value as {@link Long#hashCode()}}.
* @see Long#hashCode()
*/
public static int hashCode(long lng) {

View File

@@ -0,0 +1,183 @@
/*
* Copyright 2002-2013 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.io.ByteArrayOutputStream;
import java.io.FilterInputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
/**
* Simple utility methods for dealing with streams. The copy methods of this class are
* similar to those defined in {@link FileCopyUtils} except that all affected streams are
* left open when done. All copy methods use a block size of 4096 bytes.
*
* <p>Mainly for use within the framework, but also useful for application code.
*
* @author Juergen Hoeller
* @author Phillip Webb
* @since 3.2.2
* @see FileCopyUtils
*/
public abstract class StreamUtils {
public static final int BUFFER_SIZE = 4096;
/**
* Copy the contents of the given InputStream into a new byte array.
* Leaves the stream open when done.
* @param in the stream to copy from
* @return the new byte array that has been copied to
* @throws IOException in case of I/O errors
*/
public static byte[] copyToByteArray(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
copy(in, out);
return out.toByteArray();
}
/**
* Copy the contents of the given InputStream into a String.
* Leaves the stream open when done.
* @param in the InputStream to copy from
* @return the String that has been copied to
* @throws IOException in case of I/O errors
*/
public static String copyToString(InputStream in, Charset charset) throws IOException {
Assert.notNull(in, "No InputStream specified");
StringBuilder out = new StringBuilder();
InputStreamReader reader = new InputStreamReader(in, charset);
char[] buffer = new char[BUFFER_SIZE];
int bytesRead = -1;
while ((bytesRead = reader.read(buffer)) != -1) {
out.append(buffer, 0, bytesRead);
}
return out.toString();
}
/**
* Copy the contents of the given byte array to the given OutputStream.
* Leaves the stream open when done.
* @param in the byte array to copy from
* @param out the OutputStream to copy to
* @throws IOException in case of I/O errors
*/
public static void copy(byte[] in, OutputStream out) throws IOException {
Assert.notNull(in, "No input byte array specified");
Assert.notNull(out, "No OutputStream specified");
out.write(in);
}
/**
* Copy the contents of the given String to the given output OutputStream.
* Leaves the stream open when done.
* @param in the String to copy from
* @param charset the Charset
* @param out the OutputStream to copy to
* @throws IOException in case of I/O errors
*/
public static void copy(String in, Charset charset, OutputStream out) throws IOException {
Assert.notNull(in, "No input String specified");
Assert.notNull(charset, "No charset specified");
Assert.notNull(out, "No OutputStream specified");
Writer writer = new OutputStreamWriter(out, charset);
writer.write(in);
writer.flush();
}
/**
* Copy the contents of the given InputStream to the given OutputStream.
* Leaves both streams open when done.
* @param in the InputStream to copy from
* @param out the OutputStream to copy to
* @return the number of bytes copied
* @throws IOException in case of I/O errors
*/
public static int copy(InputStream in, OutputStream out) throws IOException {
Assert.notNull(in, "No InputStream specified");
Assert.notNull(out, "No OutputStream specified");
int byteCount = 0;
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = -1;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
byteCount += bytesRead;
}
out.flush();
return byteCount;
}
/**
* Returns a variant of the given {@link InputStream} where calling
* {@link InputStream#close() close()} has no effect.
* @param in the InputStream to decorate
* @return a version of the InputStream that ignores calls to close
*/
public static InputStream nonClosing(InputStream in) {
Assert.notNull(in, "No InputStream specified");
return new NonClosingInputStream(in);
}
/**
* Returns a variant of the given {@link OutputStream} where calling
* {@link OutputStream#close() close()} has no effect.
* @param out the OutputStream to decorate
* @return a version of the OutputStream that ignores calls to close
*/
public static OutputStream nonClosing(OutputStream out) {
Assert.notNull(out, "No OutputStream specified");
return new NonClosingOutputStream(out);
}
private static class NonClosingInputStream extends FilterInputStream {
public NonClosingInputStream(InputStream in) {
super(in);
}
@Override
public void close() throws IOException {
}
}
private static class NonClosingOutputStream extends FilterOutputStream {
public NonClosingOutputStream(OutputStream out) {
super(out);
}
@Override
public void write(byte[] b, int off, int let) throws IOException {
// It is critical that we override this method for performance
out.write(b, off, let);
}
@Override
public void close() throws IOException {
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -24,24 +24,24 @@ import javax.xml.transform.sax.SAXResult;
import org.xml.sax.ContentHandler;
/**
* Implementation of the {@code Result} tagging interface for StAX writers. Can be constructed with a
* {@code XMLEventConsumer} or a {@code XMLStreamWriter}.
* Implementation of the {@code Result} tagging interface for StAX writers. Can be constructed with
* an {@code XMLEventConsumer} or an {@code XMLStreamWriter}.
*
* <p>This class is necessary because there is no implementation of {@code Source} for StaxReaders in JAXP 1.3.
* There is a {@code StAXResult} in JAXP 1.4 (JDK 1.6), but this class is kept around for back-ward compatibility
* reasons.
* <p>This class is necessary because there is no implementation of {@code Source} for StaxReaders
* in JAXP 1.3. There is a {@code StAXResult} in JAXP 1.4 (JDK 1.6), but this class is kept around
* for backwards compatibility reasons.
*
* <p>Even though {@code StaxResult} extends from {@code SAXResult}, calling the methods of
* {@code SAXResult} is <strong>not supported</strong>. In general, the only supported operation on this class is
* to use the {@code ContentHandler} obtained via {@link #getHandler()} to parse an input source using an
* {@code XMLReader}. Calling {@link #setHandler(org.xml.sax.ContentHandler)} will result in
* {@code UnsupportedOperationException}s.
* {@code SAXResult} is <strong>not supported</strong>. In general, the only supported operation
* on this class is to use the {@code ContentHandler} obtained via {@link #getHandler()} to parse an
* input source using an {@code XMLReader}. Calling {@link #setHandler(org.xml.sax.ContentHandler)}
* will result in {@code UnsupportedOperationException}s.
*
* @author Arjen Poutsma
* @since 3.0
* @see XMLEventWriter
* @see XMLStreamWriter
* @see javax.xml.transform.Transformer
* @since 3.0
*/
class StaxResult extends SAXResult {
@@ -49,9 +49,9 @@ class StaxResult extends SAXResult {
private XMLStreamWriter streamWriter;
/**
* Constructs a new instance of the {@code StaxResult} with the specified {@code XMLStreamWriter}.
*
* Construct a new instance of the {@code StaxResult} with the specified {@code XMLStreamWriter}.
* @param streamWriter the {@code XMLStreamWriter} to write to
*/
StaxResult(XMLStreamWriter streamWriter) {
@@ -60,8 +60,7 @@ class StaxResult extends SAXResult {
}
/**
* Constructs a new instance of the {@code StaxResult} with the specified {@code XMLEventWriter}.
*
* Construct a new instance of the {@code StaxResult} with the specified {@code XMLEventWriter}.
* @param eventWriter the {@code XMLEventWriter} to write to
*/
StaxResult(XMLEventWriter eventWriter) {
@@ -70,9 +69,8 @@ class StaxResult extends SAXResult {
}
/**
* Constructs a new instance of the {@code StaxResult} with the specified {@code XMLEventWriter} and
* {@code XMLEventFactory}.
*
* Construct a new instance of the {@code StaxResult} with the specified {@code XMLEventWriter}
* and {@code XMLEventFactory}.
* @param eventWriter the {@code XMLEventWriter} to write to
* @param eventFactory the {@code XMLEventFactory} to use for creating events
*/
@@ -81,35 +79,35 @@ class StaxResult extends SAXResult {
this.eventWriter = eventWriter;
}
/**
* Returns the {@code XMLEventWriter} used by this {@code StaxResult}. If this {@code StaxResult} was
* created with an {@code XMLStreamWriter}, the result will be {@code null}.
*
* Return the {@code XMLEventWriter} used by this {@code StaxResult}. If this {@code StaxResult}
* was created with an {@code XMLStreamWriter}, the result will be {@code null}.
* @return the StAX event writer used by this result
* @see #StaxResult(javax.xml.stream.XMLEventWriter)
*/
XMLEventWriter getXMLEventWriter() {
return eventWriter;
return this.eventWriter;
}
/**
* Returns the {@code XMLStreamWriter} used by this {@code StaxResult}. If this {@code StaxResult} was
* created with an {@code XMLEventConsumer}, the result will be {@code null}.
*
* Return the {@code XMLStreamWriter} used by this {@code StaxResult}. If this {@code StaxResult}
* was created with an {@code XMLEventConsumer}, the result will be {@code null}.
* @return the StAX stream writer used by this result
* @see #StaxResult(javax.xml.stream.XMLStreamWriter)
*/
XMLStreamWriter getXMLStreamWriter() {
return streamWriter;
return this.streamWriter;
}
/**
* Throws a {@code UnsupportedOperationException}.
*
* Throws an {@code UnsupportedOperationException}.
* @throws UnsupportedOperationException always
*/
@Override
public void setHandler(ContentHandler handler) {
throw new UnsupportedOperationException("setHandler is not supported");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -24,24 +24,24 @@ import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
/**
* Implementation of the {@code Source} tagging interface for StAX readers. Can be constructed with a
* {@code XMLEventReader} or a {@code XMLStreamReader}.
* Implementation of the {@code Source} tagging interface for StAX readers. Can be constructed with
* an {@code XMLEventReader} or an {@code XMLStreamReader}.
*
* <p>This class is necessary because there is no implementation of {@code Source} for StAX Readers in JAXP 1.3.
* There is a {@code StAXSource} in JAXP 1.4 (JDK 1.6), but this class is kept around for back-ward compatibility
* reasons.
* <p>This class is necessary because there is no implementation of {@code Source} for StAX Readers
* in JAXP 1.3. There is a {@code StAXSource} in JAXP 1.4 (JDK 1.6), but this class is kept around
* for backwards compatibility reasons.
*
* <p>Even though {@code StaxSource} extends from {@code SAXSource}, calling the methods of
* {@code SAXSource} is <strong>not supported</strong>. In general, the only supported operation on this class is
* to use the {@code XMLReader} obtained via {@link #getXMLReader()} to parse the input source obtained via {@link
* #getInputSource()}. Calling {@link #setXMLReader(XMLReader)} or {@link #setInputSource(InputSource)} will result in
* {@code UnsupportedOperationException}s.
* {@code SAXSource} is <strong>not supported</strong>. In general, the only supported operation
* on this class is to use the {@code XMLReader} obtained via {@link #getXMLReader()} to parse the
* input source obtained via {@link #getInputSource()}. Calling {@link #setXMLReader(XMLReader)}
* or {@link #setInputSource(InputSource)} will result in {@code UnsupportedOperationException}s.
*
* @author Arjen Poutsma
* @since 3.0
* @see XMLEventReader
* @see XMLStreamReader
* @see javax.xml.transform.Transformer
* @since 3.0
*/
class StaxSource extends SAXSource {
@@ -49,11 +49,11 @@ class StaxSource extends SAXSource {
private XMLStreamReader streamReader;
/**
* Constructs a new instance of the {@code StaxSource} with the specified {@code XMLStreamReader}. The
* supplied stream reader must be in {@code XMLStreamConstants.START_DOCUMENT} or
* Construct a new instance of the {@code StaxSource} with the specified {@code XMLStreamReader}.
* The supplied stream reader must be in {@code XMLStreamConstants.START_DOCUMENT} or
* {@code XMLStreamConstants.START_ELEMENT} state.
*
* @param streamReader the {@code XMLStreamReader} to read from
* @throws IllegalStateException if the reader is not at the start of a document or element
*/
@@ -63,10 +63,9 @@ class StaxSource extends SAXSource {
}
/**
* Constructs a new instance of the {@code StaxSource} with the specified {@code XMLEventReader}. The
* supplied event reader must be in {@code XMLStreamConstants.START_DOCUMENT} or
* Construct a new instance of the {@code StaxSource} with the specified {@code XMLEventReader}.
* The supplied event reader must be in {@code XMLStreamConstants.START_DOCUMENT} or
* {@code XMLStreamConstants.START_ELEMENT} state.
*
* @param eventReader the {@code XMLEventReader} to read from
* @throws IllegalStateException if the reader is not at the start of a document or element
*/
@@ -75,31 +74,30 @@ class StaxSource extends SAXSource {
this.eventReader = eventReader;
}
/**
* Returns the {@code XMLEventReader} used by this {@code StaxSource}. If this {@code StaxSource} was
* created with an {@code XMLStreamReader}, the result will be {@code null}.
*
* Return the {@code XMLEventReader} used by this {@code StaxSource}. If this {@code StaxSource}
* was created with an {@code XMLStreamReader}, the result will be {@code null}.
* @return the StAX event reader used by this source
* @see StaxSource#StaxSource(javax.xml.stream.XMLEventReader)
*/
XMLEventReader getXMLEventReader() {
return eventReader;
return this.eventReader;
}
/**
* Returns the {@code XMLStreamReader} used by this {@code StaxSource}. If this {@code StaxSource} was
* created with an {@code XMLEventReader}, the result will be {@code null}.
*
* Return the {@code XMLStreamReader} used by this {@code StaxSource}. If this {@code StaxSource}
* was created with an {@code XMLEventReader}, the result will be {@code null}.
* @return the StAX event reader used by this source
* @see StaxSource#StaxSource(javax.xml.stream.XMLEventReader)
*/
XMLStreamReader getXMLStreamReader() {
return streamReader;
return this.streamReader;
}
/**
* Throws a {@code UnsupportedOperationException}.
*
* Throws an {@code UnsupportedOperationException}.
* @throws UnsupportedOperationException always
*/
@Override
@@ -108,12 +106,12 @@ class StaxSource extends SAXSource {
}
/**
* Throws a {@code UnsupportedOperationException}.
*
* Throws an {@code UnsupportedOperationException}.
* @throws UnsupportedOperationException always
*/
@Override
public void setXMLReader(XMLReader reader) {
throw new UnsupportedOperationException("setXMLReader is not supported");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -45,14 +45,15 @@ import org.springframework.util.ClassUtils;
*/
public abstract class StaxUtils {
// JAXP 1.4 is only available on JDK 1.6+
private static boolean jaxp14Available =
ClassUtils.isPresent("javax.xml.transform.stax.StAXSource", StaxUtils.class.getClassLoader());
// Stax Source
/**
* Create a custom, non-JAXP 1.4 StAX {@link Source} for the given {@link XMLStreamReader}.
*
* @param streamReader the StAX stream reader
* @return a source wrapping the {@code streamReader}
*/
@@ -62,9 +63,8 @@ public abstract class StaxUtils {
/**
* Create a StAX {@link Source} for the given {@link XMLStreamReader}.
*
* <p>If JAXP 1.4 is available, this method returns a {@link StAXSource}; otherwise it returns a
* custom StAX Source.
* <p>If JAXP 1.4 is available, this method returns a {@link StAXSource};
* otherwise it returns a custom StAX Source.
* @param streamReader the StAX stream reader
* @return a source wrapping the {@code streamReader}
* @see #createCustomStaxSource(XMLStreamReader)
@@ -80,7 +80,6 @@ public abstract class StaxUtils {
/**
* Create a custom, non-JAXP 1.4 StAX {@link Source} for the given {@link XMLEventReader}.
*
* @param eventReader the StAX event reader
* @return a source wrapping the {@code eventReader}
*/
@@ -90,9 +89,8 @@ public abstract class StaxUtils {
/**
* Create a StAX {@link Source} for the given {@link XMLEventReader}.
*
* <p>If JAXP 1.4 is available, this method returns a {@link StAXSource}; otherwise it returns a
* custom StAX Source.
* <p>If JAXP 1.4 is available, this method returns a {@link StAXSource};
* otherwise it returns a custom StAX Source.
* @param eventReader the StAX event reader
* @return a source wrapping the {@code eventReader}
* @throws XMLStreamException in case of StAX errors
@@ -116,11 +114,11 @@ public abstract class StaxUtils {
return (source instanceof StaxSource || (jaxp14Available && Jaxp14StaxHandler.isStaxSource(source)));
}
// Stax Result
/**
* Create a custom, non-JAXP 1.4 StAX {@link Result} for the given {@link XMLStreamWriter}.
*
* @param streamWriter the StAX stream writer
* @return a source wrapping the {@code streamWriter}
*/
@@ -130,9 +128,8 @@ public abstract class StaxUtils {
/**
* Create a StAX {@link Result} for the given {@link XMLStreamWriter}.
*
* <p>If JAXP 1.4 is available, this method returns a {@link StAXResult}; otherwise it returns a
* custom StAX Result.
* <p>If JAXP 1.4 is available, this method returns a {@link StAXResult};
* otherwise it returns a custom StAX Result.
* @param streamWriter the StAX stream writer
* @return a result wrapping the {@code streamWriter}
* @see #createCustomStaxResult(XMLStreamWriter)
@@ -148,7 +145,6 @@ public abstract class StaxUtils {
/**
* Create a custom, non-JAXP 1.4 StAX {@link Result} for the given {@link XMLEventWriter}.
*
* @param eventWriter the StAX event writer
* @return a source wrapping the {@code eventWriter}
*/
@@ -158,7 +154,6 @@ public abstract class StaxUtils {
/**
* Create a StAX {@link Result} for the given {@link XMLEventWriter}.
*
* <p>If JAXP 1.4 is available, this method returns a {@link StAXResult}; otherwise it returns a
* custom StAX Result.
* @param eventWriter the StAX event writer
@@ -177,8 +172,8 @@ public abstract class StaxUtils {
/**
* Indicate whether the given {@link javax.xml.transform.Result} is a StAX Result.
* @return {@code true} if {@code result} is a custom Stax Result or JAXP
* 1.4 {@link StAXResult}; {@code false} otherwise.
* @return {@code true} if {@code result} is a custom Stax Result or JAXP 1.4
* {@link StAXResult}; {@code false} otherwise.
*/
public static boolean isStaxResult(Result result) {
return (result instanceof StaxResult || (jaxp14Available && Jaxp14StaxHandler.isStaxResult(result)));
@@ -327,6 +322,7 @@ public abstract class StaxUtils {
return new XMLEventStreamWriter(eventWriter, eventFactory);
}
/**
* Inner class to avoid a static JAXP 1.4 dependency.
*/
@@ -349,11 +345,11 @@ public abstract class StaxUtils {
}
private static boolean isStaxSource(Source source) {
return source instanceof StAXSource;
return (source instanceof StAXSource);
}
private static boolean isStaxResult(Result result) {
return result instanceof StAXResult;
return (result instanceof StAXResult);
}
private static XMLStreamReader getXMLStreamReader(Source source) {