Merge branch '3.1.x'

This is the first merge from 3.1.x => master after the Gradle build
system migration. Notice how files changed under the 3.1.x directory
structure (org.springframework.*) merge seamlessly into the new
directory structure (spring-*).

Certain files had changed under 3.1.x that have since been deleted with
the Gradle build migration, e.g. all pom.xml files had <license>
sections added. These files showed up as a conflict during the merge,
but the resolution is to simply re-remove them and commit as they are
no longer relevant under 3.2.x / master.

Also noteworthy is the .gitignore file. It has been updated under 3.1.x
to ignore files and directories specific to the new Gradle-based
structure. However, this causes conflicts when trying to merge against
master, given that master should *not* ignore this directories. The
resolution in this situation is to simply force the 'master' version of
the file, i.e. when prompted for merge resolution:

    anakata:~/Work/spring-framework/spring-framework[master|MERGING]
    $ git status -sb
    ## master...springsource/master [ahead 24]
    UU .gitignore

    anakata:~/Work/spring-framework/spring-framework[master|MERGING]
    $ git checkout master .gitignore

    anakata:~/Work/spring-framework/spring-framework[master|MERGING]
    $ git commit

It is helpful in situations like this one to enable git's "rerere"
feature beforehand, which records and remembers resolution strategies,
avoiding the need to repeat them in future merges:

    $ git config --global rerere.enabled 1

See:
    http://progit.org/2010/03/08/rerere.html
    http://gitfu.wordpress.com/2008/04/20/git-rerere-rereremember-what-you-did-last-time

Conflicts:
    .gitignore
    .springframework.*/pom.xml
This commit is contained in:
Chris Beams 2012-01-31 15:34:45 +01:00
commit 398cf997b3
9 changed files with 90 additions and 27 deletions

View File

@ -133,7 +133,7 @@ public class MethodInvokingJobDetailFactoryBean extends ArgumentConvertingMethod
* fashion. The behavior when one does not want concurrent jobs to be
* executed is realized through adding the {@link StatefulJob} interface.
* More information on stateful versus stateless jobs can be found
* <a href="http://www.opensymphony.com/quartz/tutorial.html#jobsMore">here</a>.
* <a href="http://www.quartz-scheduler.org/documentation/quartz-2.1.x/tutorials/tutorial-lesson-03">here</a>.
* <p>The default setting is to run jobs concurrently.
*/
public void setConcurrent(boolean concurrent) {

View File

@ -2,7 +2,7 @@
/**
*
* Support classes for the open source scheduler
* <a href="http://www.opensymphony.com/quartz">Quartz</a>,
* <a href="http://quartz-scheduler.org">Quartz</a>,
* allowing to set up Quartz Schedulers, JobDetails and
* Triggers as beans in a Spring context. Also provides
* convenience classes for implementing Quartz Jobs.

View File

@ -51,52 +51,52 @@ public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
}
@Override
protected final void addInterceptors(InterceptorRegistry registry) {
protected void addInterceptors(InterceptorRegistry registry) {
configurers.addInterceptors(registry);
}
@Override
protected final void addViewControllers(ViewControllerRegistry registry) {
protected void addViewControllers(ViewControllerRegistry registry) {
configurers.addViewControllers(registry);
}
@Override
protected final void addResourceHandlers(ResourceHandlerRegistry registry) {
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
configurers.addResourceHandlers(registry);
}
@Override
protected final void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurers.configureDefaultServletHandling(configurer);
}
@Override
protected final void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
configurers.addArgumentResolvers(argumentResolvers);
}
@Override
protected final void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
protected void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
configurers.addReturnValueHandlers(returnValueHandlers);
}
@Override
protected final void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
configurers.configureMessageConverters(converters);
}
@Override
protected final void addFormatters(FormatterRegistry registry) {
protected void addFormatters(FormatterRegistry registry) {
configurers.addFormatters(registry);
}
@Override
protected final Validator getValidator() {
protected Validator getValidator() {
return configurers.getValidator();
}
@Override
protected final void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
protected void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
configurers.configureHandlerExceptionResolvers(exceptionResolvers);
}

View File

@ -18,12 +18,14 @@ package org.springframework.web.servlet.handler;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ -237,18 +239,16 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
* @see #handleNoMatch(Set, String, HttpServletRequest)
*/
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
List<T> mappings = urlMap.get(lookupPath);
if (mappings == null) {
mappings = new ArrayList<T>(handlerMethods.keySet());
}
List<Match> matches = new ArrayList<Match>();
for (T mapping : mappings) {
T match = getMatchingMapping(mapping, request);
if (match != null) {
matches.add(new Match(match, handlerMethods.get(mapping)));
}
List<T> directPathMatches = this.urlMap.get(lookupPath);
if (directPathMatches != null) {
addMatchingMappings(directPathMatches, matches, request);
}
if (matches.isEmpty()) {
// No choice but to go through all mappings
addMatchingMappings(this.handlerMethods.keySet(), matches, request);
}
if (!matches.isEmpty()) {
@ -279,6 +279,15 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
}
}
private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {
for (T mapping : mappings) {
T match = getMatchingMapping(mapping, request);
if (match != null) {
matches.add(new Match(match, handlerMethods.get(mapping)));
}
}
}
/**
* Check if a mapping matches the current request and return a (potentially
* new) mapping with conditions relevant to the current request.

View File

@ -106,6 +106,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView {
private HttpStatus statusCode;
private boolean expandUriTemplateVariables = true;
/**
* Constructor for use as a bean.
@ -225,6 +226,18 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView {
this.statusCode = statusCode;
}
/**
* Whether to treat the redirect URL as a URI template.
* Set this flag to <code>false</code> if the redirect URL contains open
* and close curly braces "{", "}" and you don't want them interpreted
* as URI variables.
* <p>Defaults to <code>true</code>.
* @param expandUriTemplateVariables
*/
public void setExpandUriTemplateVariables(boolean expandUriTemplateVariables) {
this.expandUriTemplateVariables = expandUriTemplateVariables;
}
/**
* Returns "true" indicating this view performs a redirect.
*/
@ -288,7 +301,7 @@ public class RedirectView extends AbstractUrlBasedView implements SmartView {
enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
}
if (StringUtils.hasText(targetUrl)) {
if (this.expandUriTemplateVariables && StringUtils.hasText(targetUrl)) {
Map<String, String> variables = getCurrentRequestUriVariables(request);
targetUrl = replaceUriTemplateVariables(targetUrl.toString(), model, variables, enc);
}

View File

@ -1182,6 +1182,19 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
assertEquals("myParam-42", response.getContentAsString());
}
// SPR-9062
@Test
public void ambiguousPathAndRequestMethod() throws Exception {
initServletWithControllers(AmbiguousPathAndRequestMethodController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/bug/EXISTING");
MockHttpServletResponse response = new MockHttpServletResponse();
getServlet().service(request, response);
assertEquals(200, response.getStatus());
assertEquals("Pattern", response.getContentAsString());
}
@Test
public void bridgeMethods() throws Exception {
initServletWithControllers(TestControllerImpl.class);
@ -2549,6 +2562,20 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
}
}
@Controller
static class AmbiguousPathAndRequestMethodController {
@RequestMapping(value = "/bug/EXISTING", method = RequestMethod.POST)
public void directMatch(Writer writer) throws IOException {
writer.write("Direct");
}
@RequestMapping(value = "/bug/{type}", method = RequestMethod.GET)
public void patternMatch(Writer writer) throws IOException {
writer.write("Pattern");
}
}
@Controller
@RequestMapping("/test*")
public static class BindingCookieValueController {

View File

@ -121,5 +121,17 @@ public class RedirectViewUriTemplateTests {
assertEquals("", this.response.getRedirectedUrl());
}
// SPR-9016
@Test
public void dontApplyUriVariables() throws Exception {
String url = "/test#{'one','abc'}";
RedirectView redirectView = new RedirectView(url, true);
redirectView.setExpandUriTemplateVariables(false);
redirectView.renderMergedOutputModel(new ModelMap(), this.request, this.response);
assertEquals(url, this.response.getRedirectedUrl());
}
}

View File

@ -27,6 +27,8 @@ Changes in version 3.1.1 (2012-02-06)
* allow adding flash attributes in methods with a ModelAndView return value
* preserve quotes in MediaType parameters
* make flash attributes available in the model of ParameterizableViewController and UrlFilenameViewController
* add property to RedirectView to disable expanding URI variables in redirect URL
* fix request mapping bug involving direct vs pattern path matches with HTTP methods
Changes in version 3.1 GA (2011-12-12)
--------------------------------------

View File

@ -21,7 +21,7 @@
<para>Spring also features integration classes for supporting scheduling
with the <classname>Timer</classname>, part of the JDK since 1.3, and the
Quartz Scheduler (<ulink
url="http://www.opensymphony.com/quartz/"></ulink>). Both of those
url="http://quartz-scheduler.org"></ulink>). Both of those
schedulers are set up using a <interfacename>FactoryBean</interfacename>
with optional references to <classname>Timer</classname> or
<classname>Trigger</classname> instances, respectively. Furthermore, a
@ -641,13 +641,13 @@ public class SampleBeanInititalizer {
</section>
<section id="scheduling-quartz">
<title>Using the OpenSymphony Quartz Scheduler</title>
<title>Using the Quartz Scheduler</title>
<para>Quartz uses <classname>Trigger</classname>,
<classname>Job</classname> and <classname>JobDetail</classname> objects to
realize scheduling of all kinds of jobs. For the basic concepts behind
Quartz, have a look at <ulink
url="http://www.opensymphony.com/quartz"></ulink>. For convenience
url="http://quartz-scheduler.org"></ulink>. For convenience
purposes, Spring offers a couple of classes that simplify the usage of
Quartz within Spring-based applications.</para>