Merge branch 'master' into websocket-stomp
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.
|
||||
@@ -412,8 +412,19 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
|
||||
* Returns the value of the {@code IfModifiedSince} header.
|
||||
* <p>The date is returned as the number of milliseconds since January 1, 1970 GMT. Returns -1 when the date is unknown.
|
||||
* @return the header value
|
||||
* @deprecated use {@link #getIfModifiedSince()}
|
||||
*/
|
||||
@Deprecated
|
||||
public long getIfNotModifiedSince() {
|
||||
return getIfModifiedSince();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the {@code If-Modified-Since} header.
|
||||
* <p>The date is returned as the number of milliseconds since January 1, 1970 GMT. Returns -1 when the date is unknown.
|
||||
* @return the header value
|
||||
*/
|
||||
public long getIfModifiedSince() {
|
||||
return getFirstDate(IF_MODIFIED_SINCE);
|
||||
}
|
||||
|
||||
|
||||
@@ -144,15 +144,15 @@ import java.util.concurrent.Callable;
|
||||
* Such command objects along with their validation results will be exposed
|
||||
* as model attributes, by default using the non-qualified command class name
|
||||
* in property notation (e.g. "orderAddress" for type "mypackage.OrderAddress").
|
||||
* Specify a parameter-level {@link ModelAttribute} annotation for declaring
|
||||
* a specific model attribute name.
|
||||
* Specify a parameter-level {@link ModelAttribute @ModelAttribute} annotation for
|
||||
* declaring a specific model attribute name.
|
||||
* <li>{@link org.springframework.validation.Errors} /
|
||||
* {@link org.springframework.validation.BindingResult} validation results
|
||||
* for a preceding command/form object (the immediate preceding argument).
|
||||
* <li>{@link org.springframework.web.bind.support.SessionStatus} status handle
|
||||
* for marking form processing as complete (triggering the cleanup of session
|
||||
* attributes that have been indicated by the {@link SessionAttributes} annotation
|
||||
* at the handler type level).
|
||||
* attributes that have been indicated by the {@link SessionAttributes @SessionAttributes}
|
||||
* annotation at the handler type level).
|
||||
* <li>{@link org.springframework.web.util.UriComponentsBuilder}
|
||||
* (Servlet-only, {@literal @MVC 3.1-only})
|
||||
* for preparing a URL relative to the current request's host, port, scheme,
|
||||
@@ -161,26 +161,26 @@ import java.util.concurrent.Callable;
|
||||
*
|
||||
* <p>The following return types are supported for handler methods:
|
||||
* <ul>
|
||||
* <li>A {@code ModelAndView} object (Servlet MVC or Portlet MVC),
|
||||
* <li>A {@link ModelAndView} object (Servlet MVC or Portlet MVC),
|
||||
* with the model implicitly enriched with command objects and the results
|
||||
* of {@link ModelAttribute} annotated reference data accessor methods.
|
||||
* of {@link ModelAttribute @ModelAttribute} annotated reference data accessor methods.
|
||||
* <li>A {@link org.springframework.ui.Model Model} object, with the view name
|
||||
* implicitly determined through a {@link org.springframework.web.servlet.RequestToViewNameTranslator}
|
||||
* and the model implicitly enriched with command objects and the results
|
||||
* of {@link ModelAttribute} annotated reference data accessor methods.
|
||||
* of {@link ModelAttribute @ModelAttribute} annotated reference data accessor methods.
|
||||
* <li>A {@link java.util.Map} object for exposing a model,
|
||||
* with the view name implicitly determined through a
|
||||
* {@link org.springframework.web.servlet.RequestToViewNameTranslator}
|
||||
* and the model implicitly enriched with command objects and the results
|
||||
* of {@link ModelAttribute} annotated reference data accessor methods.
|
||||
* of {@link ModelAttribute @ModelAttribute} annotated reference data accessor methods.
|
||||
* <li>A {@link org.springframework.web.servlet.View} object, with the
|
||||
* model implicitly determined through command objects and
|
||||
* {@link ModelAttribute} annotated reference data accessor methods.
|
||||
* {@link ModelAttribute @ModelAttribute} annotated reference data accessor methods.
|
||||
* The handler method may also programmatically enrich the model by
|
||||
* declaring a {@link org.springframework.ui.Model} argument (see above).
|
||||
* <li>A {@link String} value which is interpreted as view name,
|
||||
* with the model implicitly determined through command objects and
|
||||
* {@link ModelAttribute} annotated reference data accessor methods.
|
||||
* {@link ModelAttribute @ModelAttribute} annotated reference data accessor methods.
|
||||
* The handler method may also programmatically enrich the model by
|
||||
* declaring a {@link org.springframework.ui.ModelMap} argument
|
||||
* (see above).
|
||||
@@ -198,7 +198,7 @@ import java.util.concurrent.Callable;
|
||||
* <li>A {@link Callable} which is used by Spring MVC to obtain the return
|
||||
* value asynchronously in a separate thread transparently managed by Spring MVC
|
||||
* on behalf of the application.
|
||||
* <li>A {@code org.springframework.web.context.request.async.DeferredResult}
|
||||
* <li>A {@link org.springframework.web.context.request.async.DeferredResult}
|
||||
* which the application uses to produce a return value in a separate
|
||||
* thread of its own choosing, as an alternative to returning a Callable.
|
||||
* <li>{@code void} if the method handles the response itself (by
|
||||
@@ -211,10 +211,10 @@ import java.util.concurrent.Callable;
|
||||
* only applicable in a Servlet environment).
|
||||
* <li>Any other return type will be considered as single model attribute
|
||||
* to be exposed to the view, using the attribute name specified through
|
||||
* {@link ModelAttribute} at the method level (or the default attribute name
|
||||
* based on the return type's class name otherwise). The model will be
|
||||
* {@link ModelAttribute @ModelAttribute} at the method level (or the default attribute
|
||||
* name based on the return type's class name otherwise). The model will be
|
||||
* implicitly enriched with command objects and the results of
|
||||
* {@link ModelAttribute} annotated reference data accessor methods.
|
||||
* {@link ModelAttribute @ModelAttribute} annotated reference data accessor methods.
|
||||
* </ul>
|
||||
*
|
||||
* <p><b>NOTE:</b> {@code @RequestMapping} will only be processed if an
|
||||
|
||||
@@ -107,6 +107,22 @@ public class DeferredResult<T> {
|
||||
return ((this.result != RESULT_NONE) || this.expired);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if the DeferredResult has been set.
|
||||
*/
|
||||
public boolean hasResult() {
|
||||
return this.result != RESULT_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the result or {@code null} if the result wasn't set; since the result can
|
||||
* also be {@code null}, it is recommended to use {@link #hasResult()} first
|
||||
* to check if there is a result prior to calling this method.
|
||||
*/
|
||||
public Object getResult() {
|
||||
return hasResult() ? this.result : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured timeout value in milliseconds.
|
||||
*/
|
||||
|
||||
@@ -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,17 +97,11 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
|
||||
arg = resolveDefaultValue(namedValueInfo.defaultValue);
|
||||
}
|
||||
|
||||
boolean emptyArgValue = "".equals(arg);
|
||||
|
||||
if (binderFactory != null) {
|
||||
WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
|
||||
arg = binder.convertIfNecessary(arg, paramType, parameter);
|
||||
}
|
||||
|
||||
if (emptyArgValue && (arg == null)) {
|
||||
handleMissingValue(namedValueInfo.name, parameter);
|
||||
}
|
||||
|
||||
handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
|
||||
|
||||
return arg;
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
|
||||
package org.springframework.http.client;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
@@ -43,8 +40,10 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.tests.web.FreePortScanner;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public abstract class AbstractHttpRequestFactoryTestCase {
|
||||
|
||||
@@ -56,7 +55,7 @@ public abstract class AbstractHttpRequestFactoryTestCase {
|
||||
|
||||
@BeforeClass
|
||||
public static void startJettyServer() throws Exception {
|
||||
int port = FreePortScanner.getFreePort();
|
||||
int port = SocketUtils.findAvailableTcpPort();
|
||||
jettyServer = new Server(port);
|
||||
baseUrl = "http://localhost:" + port;
|
||||
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.tests.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.Random;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Utility class that finds free BSD ports for use in testing scenario's.
|
||||
*
|
||||
* @author Ben Hale
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public abstract class FreePortScanner {
|
||||
|
||||
private static final int MIN_SAFE_PORT = 1024;
|
||||
|
||||
private static final int MAX_PORT = 65535;
|
||||
|
||||
private static final Random random = new Random();
|
||||
|
||||
/**
|
||||
* Returns the number of a free port in the default range.
|
||||
*/
|
||||
public static int getFreePort() {
|
||||
return getFreePort(MIN_SAFE_PORT, MAX_PORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of a free port in the given range.
|
||||
*/
|
||||
public static int getFreePort(int minPort, int maxPort) {
|
||||
Assert.isTrue(minPort > 0, "'minPort' must be larger than 0");
|
||||
Assert.isTrue(maxPort > minPort, "'maxPort' must be larger than minPort");
|
||||
int portRange = maxPort - minPort;
|
||||
int candidatePort;
|
||||
int searchCounter = 0;
|
||||
do {
|
||||
if (++searchCounter > portRange) {
|
||||
throw new IllegalStateException(
|
||||
String.format("There were no ports available in the range %d to %d", minPort, maxPort));
|
||||
}
|
||||
candidatePort = getRandomPort(minPort, portRange);
|
||||
}
|
||||
while (!isPortAvailable(candidatePort));
|
||||
|
||||
return candidatePort;
|
||||
}
|
||||
|
||||
private static int getRandomPort(int minPort, int portRange) {
|
||||
return minPort + random.nextInt(portRange);
|
||||
}
|
||||
|
||||
private static boolean isPortAvailable(int port) {
|
||||
ServerSocket serverSocket;
|
||||
try {
|
||||
serverSocket = new ServerSocket();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Unable to create ServerSocket.", ex);
|
||||
}
|
||||
|
||||
try {
|
||||
InetSocketAddress sa = new InetSocketAddress(port);
|
||||
serverSocket.bind(sa);
|
||||
return true;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
serverSocket.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,14 +16,6 @@
|
||||
|
||||
package org.springframework.web.client;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
@@ -63,10 +55,12 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.tests.web.FreePortScanner;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/** @author Arjen Poutsma */
|
||||
public class RestTemplateIntegrationTests {
|
||||
@@ -83,7 +77,7 @@ public class RestTemplateIntegrationTests {
|
||||
|
||||
@BeforeClass
|
||||
public static void startJettyServer() throws Exception {
|
||||
int port = FreePortScanner.getFreePort();
|
||||
int port = SocketUtils.findAvailableTcpPort();
|
||||
jettyServer = new Server(port);
|
||||
baseUrl = "http://localhost:" + port;
|
||||
ServletContextHandler handler = new ServletContextHandler();
|
||||
@@ -243,6 +237,7 @@ public class RestTemplateIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void exchangeGet() throws Exception {
|
||||
HttpHeaders requestHeaders = new HttpHeaders();
|
||||
requestHeaders.set("MyHeader", "MyValue");
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.junit.Test;
|
||||
import org.springframework.web.context.request.async.DeferredResult.DeferredResultHandler;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* DeferredResult tests.
|
||||
@@ -69,6 +69,21 @@ public class DeferredResultTests {
|
||||
verify(handler).handleResult("hello");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasResult() {
|
||||
DeferredResultHandler handler = mock(DeferredResultHandler.class);
|
||||
|
||||
DeferredResult<String> result = new DeferredResult<String>();
|
||||
result.setResultHandler(handler);
|
||||
|
||||
assertFalse(result.hasResult());
|
||||
assertNull(result.getResult());
|
||||
|
||||
result.setResult("hello");
|
||||
|
||||
assertEquals("hello", result.getResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCompletion() throws Exception {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -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.
|
||||
@@ -49,6 +49,7 @@ import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
|
||||
/**
|
||||
* Test fixture with {@link org.springframework.web.method.annotation.RequestParamMethodArgumentResolver}.
|
||||
*
|
||||
@@ -70,6 +71,7 @@ public class RequestParamMethodArgumentResolverTests {
|
||||
private MethodParameter paramServlet30Part;
|
||||
private MethodParameter paramRequestPartAnnot;
|
||||
private MethodParameter paramRequired;
|
||||
private MethodParameter paramNotRequired;
|
||||
|
||||
private NativeWebRequest webRequest;
|
||||
|
||||
@@ -81,8 +83,10 @@ public class RequestParamMethodArgumentResolverTests {
|
||||
|
||||
ParameterNameDiscoverer paramNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
||||
|
||||
Method method = getClass().getMethod("params", String.class, String[].class, Map.class, MultipartFile.class,
|
||||
Map.class, String.class, MultipartFile.class, List.class, Part.class, MultipartFile.class, String.class);
|
||||
Method method = getClass().getMethod("params", String.class, String[].class,
|
||||
Map.class, MultipartFile.class, Map.class, String.class,
|
||||
MultipartFile.class, List.class, Part.class, MultipartFile.class,
|
||||
String.class, String.class);
|
||||
|
||||
paramNamedDefaultValueString = new MethodParameter(method, 0);
|
||||
paramNamedStringArray = new MethodParameter(method, 1);
|
||||
@@ -99,6 +103,7 @@ public class RequestParamMethodArgumentResolverTests {
|
||||
paramServlet30Part.initParameterNameDiscovery(paramNameDiscoverer);
|
||||
paramRequestPartAnnot = new MethodParameter(method, 9);
|
||||
paramRequired = new MethodParameter(method, 10);
|
||||
paramNotRequired = new MethodParameter(method, 11);
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
webRequest = new ServletWebRequest(request, new MockHttpServletResponse());
|
||||
@@ -243,9 +248,9 @@ public class RequestParamMethodArgumentResolverTests {
|
||||
fail("Expected exception");
|
||||
}
|
||||
|
||||
// SPR-10402
|
||||
// SPR-10578
|
||||
|
||||
@Test(expected = MissingServletRequestParameterException.class)
|
||||
@Test
|
||||
public void missingRequestParamEmptyValueConvertedToNull() throws Exception {
|
||||
|
||||
WebDataBinder binder = new WebRequestDataBinder(null);
|
||||
@@ -256,8 +261,25 @@ public class RequestParamMethodArgumentResolverTests {
|
||||
|
||||
this.request.addParameter("stringNotAnnot", "");
|
||||
|
||||
resolver.resolveArgument(paramStringNotAnnot, null, webRequest, binderFactory);
|
||||
fail("Expected exception");
|
||||
Object arg = resolver.resolveArgument(paramStringNotAnnot, null, webRequest, binderFactory);
|
||||
|
||||
assertNull(arg);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingRequestParamEmptyValueNotRequired() throws Exception {
|
||||
|
||||
WebDataBinder binder = new WebRequestDataBinder(null);
|
||||
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
|
||||
|
||||
WebDataBinderFactory binderFactory = mock(WebDataBinderFactory.class);
|
||||
given(binderFactory.createBinder(webRequest, null, "name")).willReturn(binder);
|
||||
|
||||
this.request.addParameter("name", "");
|
||||
|
||||
Object arg = resolver.resolveArgument(paramNotRequired, null, webRequest, binderFactory);
|
||||
|
||||
assertNull(arg);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -311,7 +333,8 @@ public class RequestParamMethodArgumentResolverTests {
|
||||
List<MultipartFile> multipartFileList,
|
||||
Part servlet30Part,
|
||||
@RequestPart MultipartFile requestPartAnnot,
|
||||
@RequestParam(value = "name") String paramRequired) {
|
||||
@RequestParam(value = "name") String paramRequired,
|
||||
@RequestParam(value = "name", required=false) String paramNotRequired) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user