Merge branch '3.2.x' into cleanup-3.2.x
This commit is contained in:
@@ -87,7 +87,7 @@ present in the framework.
|
||||
|
||||
```java
|
||||
/*
|
||||
* 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.
|
||||
@@ -108,16 +108,16 @@ package ...;
|
||||
## Update Apache license header to modified files as necessary
|
||||
|
||||
Always check the date range in the license header. For example, if you've
|
||||
modified a file in 2012 whose header still reads
|
||||
modified a file in 2013 whose header still reads
|
||||
|
||||
```java
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
```
|
||||
|
||||
then be sure to update it to 2012 appropriately
|
||||
then be sure to update it to 2013 appropriately
|
||||
|
||||
```java
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
```
|
||||
|
||||
## Use @since tags for newly-added public API types and methods
|
||||
|
||||
@@ -689,7 +689,7 @@ project("spring-test-mvc") {
|
||||
description = "Spring Test MVC Framework"
|
||||
merge.into = project(":spring-test")
|
||||
dependencies {
|
||||
provided(project(":spring-context"))
|
||||
optional(project(":spring-context"))
|
||||
provided(project(":spring-webmvc"))
|
||||
provided("javax.servlet:javax.servlet-api:3.0.1")
|
||||
optional("org.hamcrest:hamcrest-core:1.3")
|
||||
|
||||
@@ -128,7 +128,13 @@ class MergePlugin implements Plugin<Project> {
|
||||
(ExcludeRule.GROUP_KEY) : it.group,
|
||||
(ExcludeRule.MODULE_KEY) : it.module])
|
||||
}
|
||||
intoConfiguration.dependencies.addAll(configuration.dependencies)
|
||||
configuration.dependencies.each {
|
||||
def intoCompile = project.merge.into.configurations.getByName("compile")
|
||||
// Protect against changing a compile scope dependency (SPR-10218)
|
||||
if(!intoCompile.dependencies.contains(it)) {
|
||||
intoConfiguration.dependencies.add(it)
|
||||
}
|
||||
}
|
||||
project.merge.into.install.repositories.mavenInstaller.pom.scopeMappings.addMapping(
|
||||
mapping.priority + 100, intoConfiguration, mapping.scope)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,11 @@ def customizePom(pom, gradleProject) {
|
||||
dep.scope == "test"
|
||||
}
|
||||
|
||||
// sort to make pom dependencies order consistent to ease comparison of older poms
|
||||
generatedPom.dependencies = generatedPom.dependencies.sort { dep ->
|
||||
"$dep.scope:$dep.groupId:$dep.artifactId"
|
||||
}
|
||||
|
||||
// add all items necessary for maven central publication
|
||||
generatedPom.project {
|
||||
name = gradleProject.description
|
||||
|
||||
@@ -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.
|
||||
@@ -54,6 +54,7 @@ import org.springframework.core.type.StandardAnnotationMetadata;
|
||||
import org.springframework.core.type.classreading.MetadataReader;
|
||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.springframework.context.annotation.MetadataUtils.*;
|
||||
@@ -228,7 +229,7 @@ class ConfigurationClassParser {
|
||||
|
||||
// process any @Import annotations
|
||||
Set<String> imports = getImports(metadata.getClassName(), null, new HashSet<String>());
|
||||
if (imports != null && !imports.isEmpty()) {
|
||||
if (!CollectionUtils.isEmpty(imports)) {
|
||||
processImport(configClass, imports.toArray(new String[imports.size()]), true);
|
||||
}
|
||||
|
||||
@@ -292,9 +293,8 @@ class ConfigurationClassParser {
|
||||
* @return a set of all {@link Import#value() import values} or {@code null}
|
||||
* @throws IOException if there is any problem reading metadata from the named class
|
||||
*/
|
||||
private Set<String> getImports(String className, Set<String> imports,
|
||||
Set<String> visited) throws IOException {
|
||||
if (visited.add(className)) {
|
||||
private Set<String> getImports(String className, Set<String> imports, Set<String> visited) throws IOException {
|
||||
if (visited.add(className) && !className.startsWith("java")) {
|
||||
AnnotationMetadata metadata = metadataReaderFactory.getMetadataReader(className).getAnnotationMetadata();
|
||||
for (String annotationType : metadata.getAnnotationTypes()) {
|
||||
imports = getImports(annotationType, imports, visited);
|
||||
@@ -331,7 +331,7 @@ class ConfigurationClassParser {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
else if (new AssignableTypeFilter(ImportBeanDefinitionRegistrar.class).match(reader, metadataReaderFactory)) {
|
||||
else if (new AssignableTypeFilter(ImportBeanDefinitionRegistrar.class).match(reader, this.metadataReaderFactory)) {
|
||||
// the candidate class is an ImportBeanDefinitionRegistrar -> delegate to it to register additional bean definitions
|
||||
try {
|
||||
ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(
|
||||
@@ -360,17 +360,16 @@ class ConfigurationClassParser {
|
||||
private void invokeAwareMethods(ImportBeanDefinitionRegistrar registrar) {
|
||||
if (registrar instanceof Aware) {
|
||||
if (registrar instanceof ResourceLoaderAware) {
|
||||
((ResourceLoaderAware) registrar).setResourceLoader(resourceLoader);
|
||||
((ResourceLoaderAware) registrar).setResourceLoader(this.resourceLoader);
|
||||
}
|
||||
if (registrar instanceof BeanClassLoaderAware) {
|
||||
ClassLoader classLoader =
|
||||
registry instanceof ConfigurableBeanFactory ?
|
||||
((ConfigurableBeanFactory) registry).getBeanClassLoader() :
|
||||
resourceLoader.getClassLoader();
|
||||
ClassLoader classLoader = (this.registry instanceof ConfigurableBeanFactory ?
|
||||
((ConfigurableBeanFactory) this.registry).getBeanClassLoader() :
|
||||
this.resourceLoader.getClassLoader());
|
||||
((BeanClassLoaderAware) registrar).setBeanClassLoader(classLoader);
|
||||
}
|
||||
if (registrar instanceof BeanFactoryAware && registry instanceof BeanFactory) {
|
||||
((BeanFactoryAware) registrar).setBeanFactory((BeanFactory) registry);
|
||||
if (registrar instanceof BeanFactoryAware && this.registry instanceof BeanFactory) {
|
||||
((BeanFactoryAware) registrar).setBeanFactory((BeanFactory) this.registry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -398,6 +397,7 @@ class ConfigurationClassParser {
|
||||
return this.importStack;
|
||||
}
|
||||
|
||||
|
||||
interface ImportRegistry {
|
||||
|
||||
String getImportingClassFor(String importedClass);
|
||||
@@ -470,4 +470,5 @@ class ConfigurationClassParser {
|
||||
new Location(importStack.peek().getResource(), metadata));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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,23 +17,32 @@
|
||||
package org.springframework.expression.spel.ast;
|
||||
|
||||
import org.springframework.expression.TypedValue;
|
||||
import org.springframework.expression.spel.*;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.InternalParseException;
|
||||
import org.springframework.expression.spel.SpelEvaluationException;
|
||||
import org.springframework.expression.spel.SpelMessage;
|
||||
import org.springframework.expression.spel.SpelParseException;
|
||||
|
||||
/**
|
||||
* Common superclass for nodes representing literals (boolean, string, number, etc).
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public abstract class Literal extends SpelNodeImpl {
|
||||
|
||||
protected String literalValue;
|
||||
private final String originalValue;
|
||||
|
||||
public Literal(String payload, int pos) {
|
||||
|
||||
public Literal(String originalValue, int pos) {
|
||||
super(pos);
|
||||
this.literalValue = payload;
|
||||
this.originalValue = originalValue;
|
||||
}
|
||||
|
||||
public abstract TypedValue getLiteralValue();
|
||||
|
||||
public final String getOriginalValue() {
|
||||
return this.originalValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TypedValue getValueInternal(ExpressionState state) throws SpelEvaluationException {
|
||||
@@ -50,10 +59,13 @@ public abstract class Literal extends SpelNodeImpl {
|
||||
return toString();
|
||||
}
|
||||
|
||||
|
||||
public abstract TypedValue getLiteralValue();
|
||||
|
||||
|
||||
/**
|
||||
* Process the string form of a number, using the specified base if supplied and return an appropriate literal to
|
||||
* hold it. Any suffix to indicate a long will be taken into account (either 'l' or 'L' is supported).
|
||||
*
|
||||
* @param numberToken the token holding the number as its payload (eg. 1234 or 0xCAFE)
|
||||
* @param radix the base of number
|
||||
* @return a subtype of Literal that can represent it
|
||||
@@ -62,7 +74,8 @@ public abstract class Literal extends SpelNodeImpl {
|
||||
try {
|
||||
int value = Integer.parseInt(numberToken, radix);
|
||||
return new IntLiteral(numberToken, pos, value);
|
||||
} catch (NumberFormatException nfe) {
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
throw new InternalParseException(new SpelParseException(pos>>16, nfe, SpelMessage.NOT_AN_INTEGER, numberToken));
|
||||
}
|
||||
}
|
||||
@@ -71,25 +84,26 @@ public abstract class Literal extends SpelNodeImpl {
|
||||
try {
|
||||
long value = Long.parseLong(numberToken, radix);
|
||||
return new LongLiteral(numberToken, pos, value);
|
||||
} catch (NumberFormatException nfe) {
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
throw new InternalParseException(new SpelParseException(pos>>16, nfe, SpelMessage.NOT_A_LONG, numberToken));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Literal getRealLiteral(String numberToken, int pos, boolean isFloat) {
|
||||
try {
|
||||
if (isFloat) {
|
||||
float value = Float.parseFloat(numberToken);
|
||||
return new FloatLiteral(numberToken, pos, value);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
double value = Double.parseDouble(numberToken);
|
||||
return new RealLiteral(numberToken, pos, value);
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
throw new InternalParseException(new SpelParseException(pos>>16, nfe, SpelMessage.NOT_A_REAL, numberToken));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -183,6 +183,8 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
|
||||
private int registeredWithDestination = 0;
|
||||
|
||||
private volatile boolean recovering = false;
|
||||
|
||||
private Runnable stopCallback;
|
||||
|
||||
private Object currentRecoveryMarker = new Object();
|
||||
@@ -758,6 +760,9 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
super.establishSharedConnection();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ex instanceof JMSException) {
|
||||
invokeExceptionListener((JMSException) ex);
|
||||
}
|
||||
logger.debug("Could not establish shared JMS Connection - " +
|
||||
"leaving it up to asynchronous invokers to establish a Connection as soon as possible", ex);
|
||||
}
|
||||
@@ -796,7 +801,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
/**
|
||||
* Handle the given exception that arose during setup of a listener.
|
||||
* Called for every such exception in every concurrent listener.
|
||||
* <p>The default implementation logs the exception at info level
|
||||
* <p>The default implementation logs the exception at warn level
|
||||
* if not recovered yet, and at debug level if already recovered.
|
||||
* Can be overridden in subclasses.
|
||||
* @param ex the exception to handle
|
||||
@@ -837,7 +842,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
|
||||
/**
|
||||
* Recover this listener container after a listener failed to set itself up,
|
||||
* for example reestablishing the underlying Connection.
|
||||
* for example re-establishing the underlying Connection.
|
||||
* <p>The default implementation delegates to DefaultMessageListenerContainer's
|
||||
* recovery-capable {@link #refreshConnectionUntilSuccessful()} method, which will
|
||||
* try to re-establish a Connection to the JMS provider both for the shared
|
||||
@@ -846,8 +851,14 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
* @see #refreshDestination()
|
||||
*/
|
||||
protected void recoverAfterListenerSetupFailure() {
|
||||
refreshConnectionUntilSuccessful();
|
||||
refreshDestination();
|
||||
this.recovering = true;
|
||||
try {
|
||||
refreshConnectionUntilSuccessful();
|
||||
refreshDestination();
|
||||
}
|
||||
finally {
|
||||
this.recovering = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -856,9 +867,11 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
* Connection, so either needs to operate on the shared Connection or on a
|
||||
* temporary Connection that just gets established for validation purposes.
|
||||
* <p>The default implementation retries until it successfully established a
|
||||
* Connection, for as long as this message listener container is active.
|
||||
* Connection, for as long as this message listener container is running.
|
||||
* Applies the specified recovery interval between retries.
|
||||
* @see #setRecoveryInterval
|
||||
* @see #start()
|
||||
* @see #stop()
|
||||
*/
|
||||
protected void refreshConnectionUntilSuccessful() {
|
||||
while (isRunning()) {
|
||||
@@ -874,16 +887,19 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
break;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ex instanceof JMSException) {
|
||||
invokeExceptionListener((JMSException) ex);
|
||||
}
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append("Could not refresh JMS Connection for destination '");
|
||||
msg.append(getDestinationDescription()).append("' - retrying in ");
|
||||
msg.append(this.recoveryInterval).append(" ms. Cause: ");
|
||||
msg.append(ex instanceof JMSException ? JmsUtils.buildExceptionMessage((JMSException) ex) : ex.getMessage());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.warn(msg, ex);
|
||||
logger.error(msg, ex);
|
||||
}
|
||||
else {
|
||||
logger.warn(msg);
|
||||
logger.error(msg);
|
||||
}
|
||||
}
|
||||
sleepInbetweenRecoveryAttempts();
|
||||
@@ -925,6 +941,17 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this listener container is currently in a recovery attempt.
|
||||
* <p>May be used to detect recovery phases but also the end of a recovery phase,
|
||||
* with {@code isRecovering()} switching to {@code false} after having been found
|
||||
* to return {@code true} before.
|
||||
* @see #recoverAfterListenerSetupFailure()
|
||||
*/
|
||||
public final boolean isRecovering() {
|
||||
return this.recovering;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Inner classes used as internal adapters
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -294,7 +295,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
|
||||
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
checkActive();
|
||||
return Collections.enumeration(this.attributes.keySet());
|
||||
return Collections.enumeration(new LinkedHashSet<String>(this.attributes.keySet()));
|
||||
}
|
||||
|
||||
public String getCharacterEncoding() {
|
||||
|
||||
@@ -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.
|
||||
@@ -22,6 +22,7 @@ import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpSession;
|
||||
@@ -50,6 +51,7 @@ public class MockHttpSession implements HttpSession {
|
||||
|
||||
public static final String SESSION_COOKIE_NAME = "JSESSION";
|
||||
|
||||
|
||||
private static int nextId = 1;
|
||||
|
||||
private final String id;
|
||||
@@ -141,7 +143,7 @@ public class MockHttpSession implements HttpSession {
|
||||
}
|
||||
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
return Collections.enumeration(this.attributes.keySet());
|
||||
return Collections.enumeration(new LinkedHashSet<String>(this.attributes.keySet()));
|
||||
}
|
||||
|
||||
public String[] getValueNames() {
|
||||
|
||||
@@ -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.UnsupportedEncodingException;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import javax.el.ELContext;
|
||||
import javax.servlet.Servlet;
|
||||
@@ -249,7 +250,7 @@ public class MockPageContext extends PageContext {
|
||||
}
|
||||
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
return Collections.enumeration(this.attributes.keySet());
|
||||
return Collections.enumeration(new LinkedHashSet<String>(this.attributes.keySet()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -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.
|
||||
@@ -29,7 +29,6 @@ import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.activation.FileTypeMap;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.Servlet;
|
||||
@@ -434,7 +433,7 @@ public class MockServletContext implements ServletContext {
|
||||
}
|
||||
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
return Collections.enumeration(this.attributes.keySet());
|
||||
return Collections.enumeration(new LinkedHashSet<String>(this.attributes.keySet()));
|
||||
}
|
||||
|
||||
public void setAttribute(String name, Object value) {
|
||||
|
||||
@@ -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.
|
||||
@@ -28,7 +28,6 @@ import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
import javax.activation.FileTypeMap;
|
||||
import javax.portlet.PortletContext;
|
||||
import javax.portlet.PortletRequestDispatcher;
|
||||
@@ -210,7 +209,7 @@ public class MockPortletContext implements PortletContext {
|
||||
}
|
||||
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
return new Vector<String>(this.attributes.keySet()).elements();
|
||||
return Collections.enumeration(new LinkedHashSet<String>(this.attributes.keySet()));
|
||||
}
|
||||
|
||||
public void setAttribute(String name, Object value) {
|
||||
|
||||
@@ -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,13 +21,12 @@ import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.portlet.PortalContext;
|
||||
import javax.portlet.PortletContext;
|
||||
import javax.portlet.PortletMode;
|
||||
@@ -332,7 +331,7 @@ public class MockPortletRequest implements PortletRequest {
|
||||
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
checkActive();
|
||||
return new Vector<String>(this.attributes.keySet()).elements();
|
||||
return Collections.enumeration(new LinkedHashSet<String>(this.attributes.keySet()));
|
||||
}
|
||||
|
||||
public void setParameters(Map<String, String[]> parameters) {
|
||||
|
||||
@@ -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,10 +18,10 @@ package org.springframework.mock.web.portlet;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Vector;
|
||||
import javax.portlet.PortletContext;
|
||||
import javax.portlet.PortletSession;
|
||||
import javax.servlet.http.HttpSessionBindingEvent;
|
||||
@@ -51,9 +51,9 @@ public class MockPortletSession implements PortletSession {
|
||||
|
||||
private final PortletContext portletContext;
|
||||
|
||||
private final Map<String, Object> portletAttributes = new HashMap<String, Object>();
|
||||
private final Map<String, Object> portletAttributes = new LinkedHashMap<String, Object>();
|
||||
|
||||
private final Map<String, Object> applicationAttributes = new HashMap<String, Object>();
|
||||
private final Map<String, Object> applicationAttributes = new LinkedHashMap<String, Object>();
|
||||
|
||||
private boolean invalid = false;
|
||||
|
||||
@@ -92,15 +92,15 @@ public class MockPortletSession implements PortletSession {
|
||||
}
|
||||
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
return new Vector<String>(this.portletAttributes.keySet()).elements();
|
||||
return Collections.enumeration(new LinkedHashSet<String>(this.portletAttributes.keySet()));
|
||||
}
|
||||
|
||||
public Enumeration<String> getAttributeNames(int scope) {
|
||||
if (scope == PortletSession.PORTLET_SCOPE) {
|
||||
return new Vector<String>(this.portletAttributes.keySet()).elements();
|
||||
return Collections.enumeration(new LinkedHashSet<String>(this.portletAttributes.keySet()));
|
||||
}
|
||||
else if (scope == PortletSession.APPLICATION_SCOPE) {
|
||||
return new Vector<String>(this.applicationAttributes.keySet()).elements();
|
||||
return Collections.enumeration(new LinkedHashSet<String>(this.applicationAttributes.keySet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -41,7 +41,8 @@ import org.springframework.util.StringUtils;
|
||||
/**
|
||||
* Utility methods for working with {@link ContextLoader ContextLoaders} and
|
||||
* {@link SmartContextLoader SmartContextLoaders} and resolving resource locations,
|
||||
* annotated classes, and active bean definition profiles.
|
||||
* annotated classes, active bean definition profiles, and application context
|
||||
* initializers.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 3.1
|
||||
@@ -50,6 +51,7 @@ import org.springframework.util.StringUtils;
|
||||
* @see ContextConfiguration
|
||||
* @see ContextConfigurationAttributes
|
||||
* @see ActiveProfiles
|
||||
* @see ApplicationContextInitializer
|
||||
* @see MergedContextConfiguration
|
||||
*/
|
||||
abstract class ContextLoaderUtils {
|
||||
@@ -78,7 +80,7 @@ abstract class ContextLoaderUtils {
|
||||
* either {@value #DEFAULT_CONTEXT_LOADER_CLASS_NAME}
|
||||
* or {@value #DEFAULT_WEB_CONTEXT_LOADER_CLASS_NAME} will be used as the
|
||||
* default context loader class name. For details on the class resolution
|
||||
* process, see {@link #resolveContextLoaderClass()}.
|
||||
* process, see {@link #resolveContextLoaderClass}.
|
||||
*
|
||||
* @param testClass the test class for which the {@code ContextLoader}
|
||||
* should be resolved; must not be {@code null}
|
||||
@@ -89,8 +91,9 @@ abstract class ContextLoaderUtils {
|
||||
* {@code ContextLoader} class to use; may be {@code null} or <em>empty</em>
|
||||
* @return the resolved {@code ContextLoader} for the supplied
|
||||
* {@code testClass} (never {@code null})
|
||||
* @see #resolveContextLoaderClass()
|
||||
* @see #resolveContextLoaderClass
|
||||
*/
|
||||
@SuppressWarnings("javadoc")
|
||||
static ContextLoader resolveContextLoader(Class<?> testClass,
|
||||
List<ContextConfigurationAttributes> configAttributesList, String defaultContextLoaderClassName) {
|
||||
Assert.notNull(testClass, "Class must not be null");
|
||||
@@ -348,11 +351,11 @@ abstract class ContextLoaderUtils {
|
||||
* @param defaultContextLoaderClassName the name of the default
|
||||
* {@code ContextLoader} class to use (may be {@code null})
|
||||
* @return the merged context configuration
|
||||
* @see #resolveContextLoader()
|
||||
* @see #resolveContextConfigurationAttributes()
|
||||
* @see SmartContextLoader#processContextConfiguration()
|
||||
* @see ContextLoader#processLocations()
|
||||
* @see #resolveActiveProfiles()
|
||||
* @see #resolveContextLoader
|
||||
* @see #resolveContextConfigurationAttributes
|
||||
* @see SmartContextLoader#processContextConfiguration
|
||||
* @see ContextLoader#processLocations
|
||||
* @see #resolveActiveProfiles
|
||||
* @see MergedContextConfiguration
|
||||
*/
|
||||
static MergedContextConfiguration buildMergedContextConfiguration(Class<?> testClass,
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.http;
|
||||
|
||||
/**
|
||||
* Exception thrown from {@link MediaType#parseMediaType(String)} in case of
|
||||
* encountering an invalid media type specification String.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.2.2
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class InvalidMediaTypeException extends IllegalArgumentException {
|
||||
|
||||
private String mediaType;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new InvalidMediaTypeException for the given media type.
|
||||
* @param mediaType the offending media type
|
||||
* @param msg a detail message indicating the invalid part
|
||||
*/
|
||||
public InvalidMediaTypeException(String mediaType, String msg) {
|
||||
super("Invalid media type \"" + mediaType + "\": " + msg);
|
||||
this.mediaType = mediaType;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the offending media type.
|
||||
*/
|
||||
public String getMediaType() {
|
||||
return this.mediaType;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.http;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
@@ -321,8 +322,8 @@ public class MediaType implements Comparable<MediaType> {
|
||||
* @throws IllegalArgumentException if any of the parameters contain illegal characters
|
||||
*/
|
||||
public MediaType(String type, String subtype, Map<String, String> parameters) {
|
||||
Assert.hasLength(type, "'type' must not be empty");
|
||||
Assert.hasLength(subtype, "'subtype' must not be empty");
|
||||
Assert.hasLength(type, "type must not be empty");
|
||||
Assert.hasLength(subtype, "subtype must not be empty");
|
||||
checkToken(type);
|
||||
checkToken(subtype);
|
||||
this.type = type.toLowerCase(Locale.ENGLISH);
|
||||
@@ -347,11 +348,11 @@ public class MediaType implements Comparable<MediaType> {
|
||||
* @throws IllegalArgumentException in case of illegal characters
|
||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-2.2">HTTP 1.1, section 2.2</a>
|
||||
*/
|
||||
private void checkToken(String s) {
|
||||
for (int i=0; i < s.length(); i++ ) {
|
||||
char ch = s.charAt(i);
|
||||
private void checkToken(String token) {
|
||||
for (int i=0; i < token.length(); i++ ) {
|
||||
char ch = token.charAt(i);
|
||||
if (!TOKEN.get(ch)) {
|
||||
throw new IllegalArgumentException("Invalid token character '" + ch + "' in token \"" + s + "\"");
|
||||
throw new IllegalArgumentException("Invalid token character '" + ch + "' in token \"" + token + "\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -681,7 +682,7 @@ public class MediaType implements Comparable<MediaType> {
|
||||
* Parse the given String into a single {@code MediaType}.
|
||||
* @param mediaType the string to parse
|
||||
* @return the media type
|
||||
* @throws IllegalArgumentException if the string cannot be parsed
|
||||
* @throws InvalidMediaTypeException if the string cannot be parsed
|
||||
*/
|
||||
public static MediaType parseMediaType(String mediaType) {
|
||||
Assert.hasLength(mediaType, "'mediaType' must not be empty");
|
||||
@@ -694,15 +695,15 @@ public class MediaType implements Comparable<MediaType> {
|
||||
}
|
||||
int subIndex = fullType.indexOf('/');
|
||||
if (subIndex == -1) {
|
||||
throw new IllegalArgumentException("\"" + mediaType + "\" does not contain '/'");
|
||||
throw new InvalidMediaTypeException(mediaType, "does not contain '/'");
|
||||
}
|
||||
if (subIndex == fullType.length() - 1) {
|
||||
throw new IllegalArgumentException("\"" + mediaType + "\" does not contain subtype after '/'");
|
||||
throw new InvalidMediaTypeException(mediaType, "does not contain subtype after '/'");
|
||||
}
|
||||
String type = fullType.substring(0, subIndex);
|
||||
String subtype = fullType.substring(subIndex + 1, fullType.length());
|
||||
if (WILDCARD_TYPE.equals(type) && !WILDCARD_TYPE.equals(subtype)) {
|
||||
throw new IllegalArgumentException("A wildcard type is legal only in '*/*' (all media types).");
|
||||
throw new InvalidMediaTypeException(mediaType, "wildcard type is legal only in '*/*' (all media types)");
|
||||
}
|
||||
|
||||
Map<String, String> parameters = null;
|
||||
@@ -719,7 +720,15 @@ public class MediaType implements Comparable<MediaType> {
|
||||
}
|
||||
}
|
||||
|
||||
return new MediaType(type, subtype, parameters);
|
||||
try {
|
||||
return new MediaType(type, subtype, parameters);
|
||||
}
|
||||
catch (UnsupportedCharsetException ex) {
|
||||
throw new InvalidMediaTypeException(mediaType, "unsupported charset '" + ex.getCharsetName() + "'");
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
throw new InvalidMediaTypeException(mediaType, ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -97,12 +97,12 @@ public class MediaTypeTests {
|
||||
assertEquals("Invalid toString() returned", "text/plain;q=0.7", result);
|
||||
}
|
||||
|
||||
@Test(expected= IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void slashInType() {
|
||||
new MediaType("text/plain");
|
||||
}
|
||||
|
||||
@Test(expected= IllegalArgumentException.class)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void slashInSubtype() {
|
||||
new MediaType("text", "/");
|
||||
}
|
||||
@@ -122,57 +122,57 @@ public class MediaTypeTests {
|
||||
assertEquals("Invalid quality factor", 0.2D, mediaType.getQualityValue(), 0D);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = InvalidMediaTypeException.class)
|
||||
public void parseMediaTypeNoSubtype() {
|
||||
MediaType.parseMediaType("audio");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = InvalidMediaTypeException.class)
|
||||
public void parseMediaTypeNoSubtypeSlash() {
|
||||
MediaType.parseMediaType("audio/");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = InvalidMediaTypeException.class)
|
||||
public void parseMediaTypeTypeRange() {
|
||||
MediaType.parseMediaType("*/json");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = InvalidMediaTypeException.class)
|
||||
public void parseMediaTypeIllegalType() {
|
||||
MediaType.parseMediaType("audio(/basic");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = InvalidMediaTypeException.class)
|
||||
public void parseMediaTypeIllegalSubtype() {
|
||||
MediaType.parseMediaType("audio/basic)");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = InvalidMediaTypeException.class)
|
||||
public void parseMediaTypeEmptyParameterAttribute() {
|
||||
MediaType.parseMediaType("audio/*;=value");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = InvalidMediaTypeException.class)
|
||||
public void parseMediaTypeEmptyParameterValue() {
|
||||
MediaType.parseMediaType("audio/*;attr=");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = InvalidMediaTypeException.class)
|
||||
public void parseMediaTypeIllegalParameterAttribute() {
|
||||
MediaType.parseMediaType("audio/*;attr<=value");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = InvalidMediaTypeException.class)
|
||||
public void parseMediaTypeIllegalParameterValue() {
|
||||
MediaType.parseMediaType("audio/*;attr=v>alue");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = InvalidMediaTypeException.class)
|
||||
public void parseMediaTypeIllegalQualityFactor() {
|
||||
MediaType.parseMediaType("audio/basic;q=1.1");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = InvalidMediaTypeException.class)
|
||||
public void parseMediaTypeIllegalCharset() {
|
||||
MediaType.parseMediaType("text/html; charset=foo-bar");
|
||||
}
|
||||
@@ -193,7 +193,7 @@ public class MediaTypeTests {
|
||||
assertEquals("'v>alue'", mediaType.getParameter("attr"));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = InvalidMediaTypeException.class)
|
||||
public void parseMediaTypeIllegalQuotedParameterValue() {
|
||||
MediaType.parseMediaType("audio/*;attr=\"");
|
||||
}
|
||||
|
||||
10
src/dist/changelog.txt
vendored
10
src/dist/changelog.txt
vendored
@@ -3,6 +3,16 @@ SPRING FRAMEWORK CHANGELOG
|
||||
http://www.springsource.org
|
||||
|
||||
|
||||
Changes in version 3.2.2 (2013-03-07)
|
||||
--------------------------------------
|
||||
|
||||
* ConfigurationClassPostProcessor consistently uses ClassLoader, not loading core JDK annotations via ASM (SPR-10249)
|
||||
* DefaultMessageListenerContainer invokes specified ExceptionListener for recovery exceptions as well (SPR-10230)
|
||||
* DefaultMessageListenerContainer logs recovery failures at error level and exposes "isRecovering()" method (SPR-10230)
|
||||
* MediaType throws dedicated InvalidMediaTypeException instead of generic IllegalArgumentException (SPR-10226)
|
||||
* consistent use of LinkedHashMaps and independent getAttributeNames Enumeration in Servlet/Portlet mocks (SPR-10224)
|
||||
|
||||
|
||||
Changes in version 3.2.1 (2013-01-24)
|
||||
--------------------------------------
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<section xml:id="new-in-3.2-webmvc-content-negotiation">
|
||||
<title>Content negotiation improvements</title>
|
||||
|
||||
<para>A <interfacename>ContentNeogtiationStrategy</interfacename> is now
|
||||
<para>A <interfacename>ContentNegotiationStrategy</interfacename> is now
|
||||
available for resolving the requested media types from an incoming
|
||||
request. The available implementations are based on the file extension,
|
||||
query parameter, the 'Accept' header, or a fixed content type.
|
||||
|
||||
Reference in New Issue
Block a user