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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,4 +45,4 @@ public class NamedInheritableThreadLocal<T> extends InheritableThreadLocal<T> {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
* @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)
|
||||
*/
|
||||
|
||||
@@ -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<String> could be converted to a List<EmailAddress> 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<String, String> could be converted to a Map<Id, EmailAddress> 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<String, String> could be converted to a Map<Id, EmailAddress> 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<String> 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<?>, 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<String>} and the nestingLevel is 1, the nested type descriptor will be {@code String.class}.
|
||||
* If the field is a {@code List<List<String>>} and the nestingLevel is 2, the nested type descriptor will also be a {@code String.class}.
|
||||
* If the field is a {@code Map<Integer, String>} and the nestingLevel is 1, the nested type descriptor will be String, derived from the map value.
|
||||
* If the field is a {@code List<Map<Integer, String>>} 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<?>}, 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<String>} and the nestingLevel is 1, the nested type descriptor will be {@code String.class}.
|
||||
* If the property is a {@code List<List<String>>} and the nestingLevel is 2, the nested type descriptor will also be a {@code String.class}.
|
||||
* If the property is a {@code Map<Integer, String>} and the nestingLevel is 1, the nested type descriptor will be String, derived from the map value.
|
||||
* If the property is a {@code List<Map<Integer, String>>} 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<?>}, 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<java.lang.Number< and the element argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
|
||||
* If this describes a java.util.List<?> 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<java.lang.Number, java.lang.String< and the key argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
|
||||
* If this describes a java.util.Map<?, ?> 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<?, ?> 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<java.lang.String, java.lang.Number< and the value argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
|
||||
* If this describes a java.util.Map<?, ?> 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
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -41,4 +41,4 @@ public class MapPropertySource extends EnumerablePropertySource<Map<String, Obje
|
||||
return this.source.keySet().toArray(EMPTY_NAMES_ARRAY);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -83,4 +83,4 @@ class SimpleCommandLineArgsParser {
|
||||
return commandLineArgs;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -258,4 +258,4 @@ final class AnnotationAttributesReadingVisitor extends RecursiveAnnotationAttrib
|
||||
this.metaAnnotationMap.put(annotationClass.getName(), metaAnnotationTypeNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,4 +97,4 @@ final class MethodMetadataReadingVisitor extends MethodVisitor implements Method
|
||||
public String getDeclaringClassName() {
|
||||
return this.declaringClassName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,4 +72,4 @@ public class CompositeIterator<E> implements Iterator<E> {
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Remove is not supported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user