Polishing

(cherry picked from commit 2675ce7)
This commit is contained in:
Juergen Hoeller 2014-11-22 18:05:35 +01:00
parent 8854c33bf7
commit 5f58cd3b79
7 changed files with 84 additions and 74 deletions

View File

@ -54,6 +54,7 @@ import org.springframework.core.io.DescriptiveResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource; import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.ResourcePatternUtils; import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.util.ObjectUtils;
/** /**
* A Groovy-based reader for Spring bean definitions: like a Groovy builder, * A Groovy-based reader for Spring bean definitions: like a Groovy builder,
@ -269,10 +270,9 @@ public class GroovyBeanDefinitionReader extends AbstractBeanDefinitionReader imp
try { try {
Closure callable = null; Closure callable = null;
Collection constructorArgs = null; Collection constructorArgs = null;
if (args != null && args.length > 0) { if (!ObjectUtils.isEmpty(args)) {
int index = args.length; int index = args.length;
Object lastArg = args[index-1]; Object lastArg = args[index-1];
if (lastArg instanceof Closure) { if (lastArg instanceof Closure) {
callable = (Closure) lastArg; callable = (Closure) lastArg;
index--; index--;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -45,6 +45,7 @@ public abstract class FreeMarkerTemplateUtils {
*/ */
public static String processTemplateIntoString(Template template, Object model) public static String processTemplateIntoString(Template template, Object model)
throws IOException, TemplateException { throws IOException, TemplateException {
StringWriter result = new StringWriter(); StringWriter result = new StringWriter();
template.process(model, result); template.process(model, result);
return result.toString(); return result.toString();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -63,6 +63,7 @@ public class SpringTemplateLoader implements TemplateLoader {
} }
} }
@Override @Override
public Object findTemplateSource(String name) throws IOException { public Object findTemplateSource(String name) throws IOException {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
@ -86,7 +87,6 @@ public class SpringTemplateLoader implements TemplateLoader {
} }
} }
@Override @Override
public long getLastModified(Object templateSource) { public long getLastModified(Object templateSource) {
Resource resource = (Resource) templateSource; Resource resource = (Resource) templateSource;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,14 +16,15 @@
package org.springframework.context.annotation; package org.springframework.context.annotation;
import static org.junit.Assert.assertNotNull;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import static org.junit.Assert.*;
/** /**
* Test case cornering the bug initially raised with SPR-8762, in which a * Test case cornering the bug initially raised with SPR-8762, in which a
* NullPointerException would be raised if a FactoryBean-returning @Bean method also * NullPointerException would be raised if a FactoryBean-returning @Bean method also
@ -33,47 +34,55 @@ import org.springframework.context.ApplicationContext;
* @since 3.1 * @since 3.1
*/ */
public class ConfigurationWithFactoryBeanAndParametersTests { public class ConfigurationWithFactoryBeanAndParametersTests {
@Test @Test
public void test() { public void test() {
ApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class, Bar.class); ApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class, Bar.class);
assertNotNull(ctx.getBean(Bar.class).foo); assertNotNull(ctx.getBean(Bar.class).foo);
} }
}
@Configuration
class Config {
@Bean
public FactoryBean<Foo> fb(@Value("42") String answer) {
return new FooFactoryBean();
}
}
class Foo { @Configuration
} static class Config {
class Bar { @Bean
Foo foo; public FactoryBean<Foo> fb(@Value("42") String answer) {
return new FooFactoryBean();
@Autowired }
public Bar(Foo foo) {
this.foo = foo;
}
}
class FooFactoryBean implements FactoryBean<Foo> {
@Override
public Foo getObject() {
return new Foo();
} }
@Override
public Class<Foo> getObjectType() { static class Foo {
return Foo.class;
} }
@Override
public boolean isSingleton() { static class Bar {
return true;
Foo foo;
@Autowired
public Bar(Foo foo) {
this.foo = foo;
}
} }
static class FooFactoryBean implements FactoryBean<Foo> {
@Override
public Foo getObject() {
return new Foo();
}
@Override
public Class<Foo> getObjectType() {
return Foo.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,16 +16,19 @@
package org.springframework.context.groovy; package org.springframework.context.groovy;
import junit.framework.TestCase; import org.junit.Test;
import org.springframework.context.support.GenericGroovyApplicationContext; import org.springframework.context.support.GenericGroovyApplicationContext;
import static org.junit.Assert.*;
/** /**
* @author Jeff Brown * @author Jeff Brown
* @author Juergen Hoeller * @author Juergen Hoeller
*/ */
public class GroovyApplicationContextTests extends TestCase { public class GroovyApplicationContextTests {
@Test
public void testLoadingConfigFile() { public void testLoadingConfigFile() {
GenericGroovyApplicationContext ctx = new GenericGroovyApplicationContext( GenericGroovyApplicationContext ctx = new GenericGroovyApplicationContext(
"org/springframework/context/groovy/applicationContext.groovy"); "org/springframework/context/groovy/applicationContext.groovy");
@ -35,6 +38,7 @@ public class GroovyApplicationContextTests extends TestCase {
assertEquals("Grails", framework); assertEquals("Grails", framework);
} }
@Test
public void testLoadingMultipleConfigFiles() { public void testLoadingMultipleConfigFiles() {
GenericGroovyApplicationContext ctx = new GenericGroovyApplicationContext( GenericGroovyApplicationContext ctx = new GenericGroovyApplicationContext(
"org/springframework/context/groovy/applicationContext2.groovy", "org/springframework/context/groovy/applicationContext2.groovy",
@ -49,6 +53,7 @@ public class GroovyApplicationContextTests extends TestCase {
assertEquals("SpringSource", company); assertEquals("SpringSource", company);
} }
@Test
public void testLoadingMultipleConfigFilesWithRelativeClass() { public void testLoadingMultipleConfigFilesWithRelativeClass() {
GenericGroovyApplicationContext ctx = new GenericGroovyApplicationContext(); GenericGroovyApplicationContext ctx = new GenericGroovyApplicationContext();
ctx.load(GroovyApplicationContextTests.class, "applicationContext2.groovy", "applicationContext.groovy"); ctx.load(GroovyApplicationContextTests.class, "applicationContext2.groovy", "applicationContext.groovy");

View File

@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
@ -16,32 +16,33 @@
package org.springframework.messaging.simp.user; package org.springframework.messaging.simp.user;
import java.security.Principal;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.messaging.Message; import org.springframework.messaging.Message;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor; import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessageType; import org.springframework.messaging.simp.SimpMessageType;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.security.Principal;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/** /**
* A default implementation of {@link UserDestinationResolver} that relies * A default implementation of {@link UserDestinationResolver} that relies
* on the {@link org.springframework.messaging.simp.user.UserSessionRegistry} * on the {@link org.springframework.messaging.simp.user.UserSessionRegistry}
* provided to the constructor to find the sessionIds associated with a user * provided to the constructor to find the sessionIds associated with a user
* and then uses the sessionId to make the target destination unique. * and then uses the sessionId to make the target destination unique.
* <p> *
* When a user attempts to subscribe to "/user/queue/position-updates", the * <p>When a user attempts to subscribe to "/user/queue/position-updates", the
* "/user" prefix is removed and a unique suffix added, resulting in something * "/user" prefix is removed and a unique suffix added, resulting in something
* like "/queue/position-updates-useri9oqdfzo" where the suffix is based on the * like "/queue/position-updates-useri9oqdfzo" where the suffix is based on the
* user's session and ensures it does not collide with any other users attempting * user's session and ensures it does not collide with any other users attempting
* to subscribe to "/user/queue/position-updates". * to subscribe to "/user/queue/position-updates".
* <p> *
* When a message is sent to a user with a destination such as * <p>When a message is sent to a user with a destination such as
* "/user/{username}/queue/position-updates", the "/user/{username}" prefix is * "/user/{username}/queue/position-updates", the "/user/{username}" prefix is
* removed and the suffix added, resulting in something like * removed and the suffix added, resulting in something like
* "/queue/position-updates-useri9oqdfzo". * "/queue/position-updates-useri9oqdfzo".
@ -69,6 +70,7 @@ public class DefaultUserDestinationResolver implements UserDestinationResolver {
this.userSessionRegistry = userSessionRegistry; this.userSessionRegistry = userSessionRegistry;
} }
/** /**
* The prefix used to identify user destinations. Any destinations that do not * The prefix used to identify user destinations. Any destinations that do not
* start with the given prefix are not be resolved. * start with the given prefix are not be resolved.
@ -99,35 +101,30 @@ public class DefaultUserDestinationResolver implements UserDestinationResolver {
@Override @Override
public UserDestinationResult resolveDestination(Message<?> message) { public UserDestinationResult resolveDestination(Message<?> message) {
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(message); SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(message);
DestinationInfo info = parseUserDestination(headers); DestinationInfo info = parseUserDestination(headers);
if (info == null) { if (info == null) {
return null; return null;
} }
Set<String> targetDestinations = new HashSet<String>(); Set<String> targetDestinations = new HashSet<String>();
for (String sessionId : info.getSessionIds()) { for (String sessionId : info.getSessionIds()) {
targetDestinations.add(getTargetDestination( targetDestinations.add(getTargetDestination(
headers.getDestination(), info.getDestinationWithoutPrefix(), sessionId, info.getUser())); headers.getDestination(), info.getDestinationWithoutPrefix(), sessionId, info.getUser()));
} }
return new UserDestinationResult(headers.getDestination(), return new UserDestinationResult(headers.getDestination(),
targetDestinations, info.getSubscribeDestination(), info.getUser()); targetDestinations, info.getSubscribeDestination(), info.getUser());
} }
private DestinationInfo parseUserDestination(SimpMessageHeaderAccessor headers) { private DestinationInfo parseUserDestination(SimpMessageHeaderAccessor headers) {
String destination = headers.getDestination(); String destination = headers.getDestination();
Principal principal = headers.getUser();
SimpMessageType messageType = headers.getMessageType();
String destinationWithoutPrefix; String destinationWithoutPrefix;
String subscribeDestination; String subscribeDestination;
String user; String user;
Set<String> sessionIds; Set<String> sessionIds;
Principal principal = headers.getUser();
SimpMessageType messageType = headers.getMessageType();
if (SimpMessageType.SUBSCRIBE.equals(messageType) || SimpMessageType.UNSUBSCRIBE.equals(messageType)) { if (SimpMessageType.SUBSCRIBE.equals(messageType) || SimpMessageType.UNSUBSCRIBE.equals(messageType)) {
if (!checkDestination(destination, this.destinationPrefix)) { if (!checkDestination(destination, this.destinationPrefix)) {
return null; return null;
@ -185,7 +182,6 @@ public class DefaultUserDestinationResolver implements UserDestinationResolver {
/** /**
* Return the target destination to use. Provided as input are the original source * Return the target destination to use. Provided as input are the original source
* destination, as well as the same destination with the target prefix removed. * destination, as well as the same destination with the target prefix removed.
*
* @param sourceDestination the source destination from the input message * @param sourceDestination the source destination from the input message
* @param sourceDestinationWithoutPrefix the source destination with the target prefix removed * @param sourceDestinationWithoutPrefix the source destination with the target prefix removed
* @param sessionId an active user session id * @param sessionId an active user session id
@ -209,8 +205,7 @@ public class DefaultUserDestinationResolver implements UserDestinationResolver {
private final Set<String> sessionIds; private final Set<String> sessionIds;
public DestinationInfo(String destinationWithoutPrefix, String subscribeDestination, String user,
private DestinationInfo(String destinationWithoutPrefix, String subscribeDestination, String user,
Set<String> sessionIds) { Set<String> sessionIds) {
this.user = user; this.user = user;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -36,11 +36,13 @@ public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator i
private int order = Ordered.LOWEST_PRECEDENCE; private int order = Ordered.LOWEST_PRECEDENCE;
public AbstractHandlerMethodAdapter() { public AbstractHandlerMethodAdapter() {
// no restriction of HTTP methods by default // no restriction of HTTP methods by default
super(false); super(false);
} }
/** /**
* Specify the order value for this HandlerAdapter bean. * Specify the order value for this HandlerAdapter bean.
* <p>Default value is {@code Integer.MAX_VALUE}, meaning that it's non-ordered. * <p>Default value is {@code Integer.MAX_VALUE}, meaning that it's non-ordered.
@ -55,51 +57,49 @@ public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator i
return this.order; return this.order;
} }
/** /**
* {@inheritDoc} <p>This implementation expects the handler to be an {@link HandlerMethod}. * This implementation expects the handler to be an {@link HandlerMethod}.
*
* @param handler the handler instance to check * @param handler the handler instance to check
* @return whether or not this adapter can adapt the given handler * @return whether or not this adapter can adapt the given handler
*/ */
@Override @Override
public final boolean supports(Object handler) { public final boolean supports(Object handler) {
return handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler); return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
} }
/** /**
* Given a handler method, return whether or not this adapter can support it. * Given a handler method, return whether or not this adapter can support it.
*
* @param handlerMethod the handler method to check * @param handlerMethod the handler method to check
* @return whether or not this adapter can adapt the given method * @return whether or not this adapter can adapt the given method
*/ */
protected abstract boolean supportsInternal(HandlerMethod handlerMethod); protected abstract boolean supportsInternal(HandlerMethod handlerMethod);
/** /**
* {@inheritDoc} <p>This implementation expects the handler to be an {@link HandlerMethod}. * This implementation expects the handler to be an {@link HandlerMethod}.
*/ */
@Override @Override
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception { throws Exception {
return handleInternal(request, response, (HandlerMethod) handler); return handleInternal(request, response, (HandlerMethod) handler);
} }
/** /**
* Use the given handler method to handle the request. * Use the given handler method to handle the request.
*
* @param request current HTTP request * @param request current HTTP request
* @param response current HTTP response * @param response current HTTP response
* @param handlerMethod handler method to use. This object must have previously been passed to the * @param handlerMethod handler method to use. This object must have previously been passed to the
* {@link #supportsInternal(HandlerMethod)} this interface, which must have returned {@code true}. * {@link #supportsInternal(HandlerMethod)} this interface, which must have returned {@code true}.
* @return ModelAndView object with the name of the view and the required model data, or {@code null} if * @return ModelAndView object with the name of the view and the required model data,
* the request has been handled directly * or {@code null} if the request has been handled directly
* @throws Exception in case of errors * @throws Exception in case of errors
*/ */
protected abstract ModelAndView handleInternal(HttpServletRequest request, protected abstract ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;
HandlerMethod handlerMethod) throws Exception;
/** /**
* {@inheritDoc} <p>This implementation expects the handler to be an {@link HandlerMethod}. * This implementation expects the handler to be an {@link HandlerMethod}.
*/ */
@Override @Override
public final long getLastModified(HttpServletRequest request, Object handler) { public final long getLastModified(HttpServletRequest request, Object handler) {
@ -108,10 +108,10 @@ public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator i
/** /**
* Same contract as for {@link javax.servlet.http.HttpServlet#getLastModified(HttpServletRequest)}. * Same contract as for {@link javax.servlet.http.HttpServlet#getLastModified(HttpServletRequest)}.
*
* @param request current HTTP request * @param request current HTTP request
* @param handlerMethod handler method to use * @param handlerMethod handler method to use
* @return the lastModified value for the given handler * @return the lastModified value for the given handler
*/ */
protected abstract long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod); protected abstract long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod);
} }