Merge branch '3.1.x'
This commit is contained in:
commit
3798626a90
|
|
@ -20,8 +20,8 @@ Instructions on
|
||||||
via Maven and other build systems are available via the project wiki.
|
via Maven and other build systems are available via the project wiki.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
See the current [Javadoc](http://static.springsource.org/spring/docs/current/javadoc-api)
|
See the current [Javadoc](http://static.springsource.org/spring-framework/docs/current/api)
|
||||||
and [Reference docs](http://static.springsource.org/spring/docs/current/spring-framework-reference).
|
and [Reference docs](http://static.springsource.org/spring-framework/docs/current/reference).
|
||||||
|
|
||||||
## Getting support
|
## Getting support
|
||||||
Check out the [Spring forums](http://forum.springsource.org) and the
|
Check out the [Spring forums](http://forum.springsource.org) and the
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ http://www.springsource.org
|
||||||
Changes in version 3.1.1 (2012-02-06)
|
Changes in version 3.1.1 (2012-02-06)
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
* official support for Hibernate 4.0 GA
|
* official support for Hibernate 4.0 GA (as released in the meantime)
|
||||||
* JBossNativeJdbcExtractor is compatible with JBoss AS 7 as well
|
* JBossNativeJdbcExtractor is compatible with JBoss AS 7 as well
|
||||||
* context:property-placeholder's "file-encoding" attribute value is being applied correctly
|
* context:property-placeholder's "file-encoding" attribute value is being applied correctly
|
||||||
* DataBinder correctly handles ParseException from Formatter for String->String case
|
* DataBinder correctly handles ParseException from Formatter for String->String case
|
||||||
|
|
@ -19,8 +19,14 @@ Changes in version 3.1.1 (2012-02-06)
|
||||||
* Hibernate 4 LocalSessionFactoryBean implements PersistenceExceptionTranslator interface as well
|
* Hibernate 4 LocalSessionFactoryBean implements PersistenceExceptionTranslator interface as well
|
||||||
* Hibernate 4 LocalSessionFactoryBean does not insist on a "dataSource" reference being set
|
* Hibernate 4 LocalSessionFactoryBean does not insist on a "dataSource" reference being set
|
||||||
* added "entityInterceptor" property to Hibernate 4 LocalSessionFactoryBean
|
* added "entityInterceptor" property to Hibernate 4 LocalSessionFactoryBean
|
||||||
|
* added "getConfiguration" accessor to Hibernate 4 LocalSessionFactoryBean
|
||||||
* corrected fix for QuartzJobBean to work with Quartz 2.0/2.1
|
* corrected fix for QuartzJobBean to work with Quartz 2.0/2.1
|
||||||
|
* JMS CachingConnectionFactory never caches consumers for temporary queues and topics
|
||||||
|
* JMS SimpleMessageListenerContainer silently falls back to lazy registration of consumers
|
||||||
|
* fix regresion in UriUtils
|
||||||
|
* 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
|
||||||
|
|
||||||
Changes in version 3.1 GA (2011-12-12)
|
Changes in version 3.1 GA (2011-12-12)
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -34,6 +34,8 @@ import javax.jms.MessageConsumer;
|
||||||
import javax.jms.MessageProducer;
|
import javax.jms.MessageProducer;
|
||||||
import javax.jms.QueueSession;
|
import javax.jms.QueueSession;
|
||||||
import javax.jms.Session;
|
import javax.jms.Session;
|
||||||
|
import javax.jms.TemporaryQueue;
|
||||||
|
import javax.jms.TemporaryTopic;
|
||||||
import javax.jms.Topic;
|
import javax.jms.Topic;
|
||||||
import javax.jms.TopicSession;
|
import javax.jms.TopicSession;
|
||||||
|
|
||||||
|
|
@ -323,16 +325,18 @@ public class CachingConnectionFactory extends SingleConnectionFactory {
|
||||||
// let raw JMS invocation throw an exception if Destination (i.e. args[0]) is null
|
// let raw JMS invocation throw an exception if Destination (i.e. args[0]) is null
|
||||||
if ((methodName.equals("createConsumer") || methodName.equals("createReceiver") ||
|
if ((methodName.equals("createConsumer") || methodName.equals("createReceiver") ||
|
||||||
methodName.equals("createSubscriber"))) {
|
methodName.equals("createSubscriber"))) {
|
||||||
if (args[0] != null) {
|
Destination dest = (Destination) args[0];
|
||||||
return getCachedConsumer((Destination) args[0],
|
if (dest != null && !(dest instanceof TemporaryQueue || dest instanceof TemporaryTopic)) {
|
||||||
|
return getCachedConsumer(dest,
|
||||||
(args.length > 1 ? (String) args[1] : null),
|
(args.length > 1 ? (String) args[1] : null),
|
||||||
(args.length > 2 && (Boolean) args[2]),
|
(args.length > 2 && (Boolean) args[2]),
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (methodName.equals("createDurableSubscriber")) {
|
else if (methodName.equals("createDurableSubscriber")) {
|
||||||
if (args[0] != null) {
|
Destination dest = (Destination) args[0];
|
||||||
return getCachedConsumer((Destination) args[0],
|
if (dest != null) {
|
||||||
|
return getCachedConsumer(dest,
|
||||||
(args.length > 2 ? (String) args[2] : null),
|
(args.length > 2 ? (String) args[2] : null),
|
||||||
(args.length > 3 && (Boolean) args[3]),
|
(args.length > 3 && (Boolean) args[3]),
|
||||||
(String) args[1]);
|
(String) args[1]);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -151,6 +151,7 @@ public abstract class AbstractJmsListeningContainer extends JmsDestinationAccess
|
||||||
/**
|
/**
|
||||||
* Delegates to {@link #validateConfiguration()} and {@link #initialize()}.
|
* Delegates to {@link #validateConfiguration()} and {@link #initialize()}.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void afterPropertiesSet() {
|
public void afterPropertiesSet() {
|
||||||
super.afterPropertiesSet();
|
super.afterPropertiesSet();
|
||||||
validateConfiguration();
|
validateConfiguration();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -410,6 +410,7 @@ public abstract class AbstractMessageListenerContainer extends AbstractJmsListen
|
||||||
return this.acceptMessagesWhileStopping;
|
return this.acceptMessagesWhileStopping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected void validateConfiguration() {
|
protected void validateConfiguration() {
|
||||||
if (this.destination == null) {
|
if (this.destination == null) {
|
||||||
throw new IllegalArgumentException("Property 'destination' or 'destinationName' is required");
|
throw new IllegalArgumentException("Property 'destination' or 'destinationName' is required");
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2010 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -75,8 +75,7 @@ import org.springframework.transaction.support.TransactionSynchronizationUtils;
|
||||||
* @see #receiveAndExecute
|
* @see #receiveAndExecute
|
||||||
* @see #setTransactionManager
|
* @see #setTransactionManager
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractPollingMessageListenerContainer extends AbstractMessageListenerContainer
|
public abstract class AbstractPollingMessageListenerContainer extends AbstractMessageListenerContainer {
|
||||||
implements BeanNameAware {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default receive timeout: 1000 ms = 1 second.
|
* The default receive timeout: 1000 ms = 1 second.
|
||||||
|
|
@ -100,6 +99,7 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
|
||||||
private volatile Boolean commitAfterNoMessageReceived;
|
private volatile Boolean commitAfterNoMessageReceived;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setSessionTransacted(boolean sessionTransacted) {
|
public void setSessionTransacted(boolean sessionTransacted) {
|
||||||
super.setSessionTransacted(sessionTransacted);
|
super.setSessionTransacted(sessionTransacted);
|
||||||
this.sessionTransactedCalled = true;
|
this.sessionTransactedCalled = true;
|
||||||
|
|
@ -188,6 +188,7 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
// Set sessionTransacted=true in case of a non-JTA transaction manager.
|
// Set sessionTransacted=true in case of a non-JTA transaction manager.
|
||||||
if (!this.sessionTransactedCalled &&
|
if (!this.sessionTransactedCalled &&
|
||||||
|
|
@ -374,6 +375,7 @@ public abstract class AbstractPollingMessageListenerContainer extends AbstractMe
|
||||||
* container's "sessionTransacted" flag being set to "true".
|
* container's "sessionTransacted" flag being set to "true".
|
||||||
* @see org.springframework.jms.connection.JmsResourceHolder
|
* @see org.springframework.jms.connection.JmsResourceHolder
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected boolean isSessionLocallyTransacted(Session session) {
|
protected boolean isSessionLocallyTransacted(Session session) {
|
||||||
if (!super.isSessionLocallyTransacted(session)) {
|
if (!super.isSessionLocallyTransacted(session)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -470,6 +470,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected void validateConfiguration() {
|
protected void validateConfiguration() {
|
||||||
super.validateConfiguration();
|
super.validateConfiguration();
|
||||||
synchronized (this.lifecycleMonitor) {
|
synchronized (this.lifecycleMonitor) {
|
||||||
|
|
@ -484,6 +485,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||||
// Implementation of AbstractMessageListenerContainer's template methods
|
// Implementation of AbstractMessageListenerContainer's template methods
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
// Adapt default cache level.
|
// Adapt default cache level.
|
||||||
if (this.cacheLevel == CACHE_AUTO) {
|
if (this.cacheLevel == CACHE_AUTO) {
|
||||||
|
|
@ -516,6 +518,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||||
* @see #scheduleNewInvoker
|
* @see #scheduleNewInvoker
|
||||||
* @see #setTaskExecutor
|
* @see #setTaskExecutor
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected void doInitialize() throws JMSException {
|
protected void doInitialize() throws JMSException {
|
||||||
synchronized (this.lifecycleMonitor) {
|
synchronized (this.lifecycleMonitor) {
|
||||||
for (int i = 0; i < this.concurrentConsumers; i++) {
|
for (int i = 0; i < this.concurrentConsumers; i++) {
|
||||||
|
|
@ -527,6 +530,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||||
/**
|
/**
|
||||||
* Destroy the registered JMS Sessions and associated MessageConsumers.
|
* Destroy the registered JMS Sessions and associated MessageConsumers.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected void doShutdown() throws JMSException {
|
protected void doShutdown() throws JMSException {
|
||||||
logger.debug("Waiting for shutdown of message listener invokers");
|
logger.debug("Waiting for shutdown of message listener invokers");
|
||||||
try {
|
try {
|
||||||
|
|
@ -549,6 +553,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||||
/**
|
/**
|
||||||
* Overridden to reset the stop callback, if any.
|
* Overridden to reset the stop callback, if any.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void start() throws JmsException {
|
public void start() throws JmsException {
|
||||||
synchronized (this.lifecycleMonitor) {
|
synchronized (this.lifecycleMonitor) {
|
||||||
this.stopCallback = null;
|
this.stopCallback = null;
|
||||||
|
|
@ -658,6 +663,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||||
* @see #setCacheLevel
|
* @see #setCacheLevel
|
||||||
* @see #CACHE_CONNECTION
|
* @see #CACHE_CONNECTION
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected final boolean sharedConnectionEnabled() {
|
protected final boolean sharedConnectionEnabled() {
|
||||||
return (getCacheLevel() >= CACHE_CONNECTION);
|
return (getCacheLevel() >= CACHE_CONNECTION);
|
||||||
}
|
}
|
||||||
|
|
@ -666,6 +672,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||||
* Re-executes the given task via this listener container's TaskExecutor.
|
* Re-executes the given task via this listener container's TaskExecutor.
|
||||||
* @see #setTaskExecutor
|
* @see #setTaskExecutor
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected void doRescheduleTask(Object task) {
|
protected void doRescheduleTask(Object task) {
|
||||||
this.taskExecutor.execute((Runnable) task);
|
this.taskExecutor.execute((Runnable) task);
|
||||||
}
|
}
|
||||||
|
|
@ -674,6 +681,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||||
* Tries scheduling a new invoker, since we know messages are coming in...
|
* Tries scheduling a new invoker, since we know messages are coming in...
|
||||||
* @see #scheduleNewInvokerIfAppropriate()
|
* @see #scheduleNewInvokerIfAppropriate()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected void messageReceived(Object invoker, Session session) {
|
protected void messageReceived(Object invoker, Session session) {
|
||||||
((AsyncMessageListenerInvoker) invoker).setIdle(false);
|
((AsyncMessageListenerInvoker) invoker).setIdle(false);
|
||||||
scheduleNewInvokerIfAppropriate();
|
scheduleNewInvokerIfAppropriate();
|
||||||
|
|
@ -682,6 +690,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||||
/**
|
/**
|
||||||
* Marks the affected invoker as idle.
|
* Marks the affected invoker as idle.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected void noMessageReceived(Object invoker, Session session) {
|
protected void noMessageReceived(Object invoker, Session session) {
|
||||||
((AsyncMessageListenerInvoker) invoker).setIdle(true);
|
((AsyncMessageListenerInvoker) invoker).setIdle(true);
|
||||||
}
|
}
|
||||||
|
|
@ -745,6 +754,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||||
* asynchronous invokers to establish the shared Connection on first access.
|
* asynchronous invokers to establish the shared Connection on first access.
|
||||||
* @see #refreshConnectionUntilSuccessful()
|
* @see #refreshConnectionUntilSuccessful()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected void establishSharedConnection() {
|
protected void establishSharedConnection() {
|
||||||
try {
|
try {
|
||||||
super.establishSharedConnection();
|
super.establishSharedConnection();
|
||||||
|
|
@ -760,6 +770,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||||
* <code>Connection.start()</code>, relying on listeners to perform
|
* <code>Connection.start()</code>, relying on listeners to perform
|
||||||
* appropriate recovery.
|
* appropriate recovery.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected void startSharedConnection() {
|
protected void startSharedConnection() {
|
||||||
try {
|
try {
|
||||||
super.startSharedConnection();
|
super.startSharedConnection();
|
||||||
|
|
@ -774,6 +785,7 @@ public class DefaultMessageListenerContainer extends AbstractPollingMessageListe
|
||||||
* <code>Connection.stop()</code>, relying on listeners to perform
|
* <code>Connection.stop()</code>, relying on listeners to perform
|
||||||
* appropriate recovery after a restart.
|
* appropriate recovery after a restart.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected void stopSharedConnection() {
|
protected void stopSharedConnection() {
|
||||||
try {
|
try {
|
||||||
super.stopSharedConnection();
|
super.stopSharedConnection();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2010 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -62,6 +62,8 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta
|
||||||
|
|
||||||
private boolean pubSubNoLocal = false;
|
private boolean pubSubNoLocal = false;
|
||||||
|
|
||||||
|
private boolean connectLazily = false;
|
||||||
|
|
||||||
private int concurrentConsumers = 1;
|
private int concurrentConsumers = 1;
|
||||||
|
|
||||||
private Executor taskExecutor;
|
private Executor taskExecutor;
|
||||||
|
|
@ -89,6 +91,20 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta
|
||||||
return this.pubSubNoLocal;
|
return this.pubSubNoLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify whether to connect lazily, i.e. whether to establish the JMS Connection
|
||||||
|
* and the corresponding Sessions and MessageConsumers as late as possible -
|
||||||
|
* in the start phase of this container.
|
||||||
|
* <p>Default is "false": connecting early, i.e. during the bean initialization phase.
|
||||||
|
* Set this flag to "true" in order to switch to lazy connecting if your target broker
|
||||||
|
* is likely to not have started up yet and you prefer to not even try a connection.
|
||||||
|
* @see #start()
|
||||||
|
* @see #initialize()
|
||||||
|
*/
|
||||||
|
public void setConnectLazily(boolean connectLazily) {
|
||||||
|
this.connectLazily = connectLazily;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify concurrency limits via a "lower-upper" String, e.g. "5-10", or a simple
|
* Specify concurrency limits via a "lower-upper" String, e.g. "5-10", or a simple
|
||||||
* upper limit String, e.g. "10".
|
* upper limit String, e.g. "10".
|
||||||
|
|
@ -159,6 +175,7 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta
|
||||||
this.taskExecutor = taskExecutor;
|
this.taskExecutor = taskExecutor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected void validateConfiguration() {
|
protected void validateConfiguration() {
|
||||||
super.validateConfiguration();
|
super.validateConfiguration();
|
||||||
if (isSubscriptionDurable() && this.concurrentConsumers != 1) {
|
if (isSubscriptionDurable() && this.concurrentConsumers != 1) {
|
||||||
|
|
@ -174,6 +191,7 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta
|
||||||
/**
|
/**
|
||||||
* Always use a shared JMS Connection.
|
* Always use a shared JMS Connection.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected final boolean sharedConnectionEnabled() {
|
protected final boolean sharedConnectionEnabled() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -183,15 +201,25 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta
|
||||||
* in the form of a JMS Session plus associated MessageConsumer.
|
* in the form of a JMS Session plus associated MessageConsumer.
|
||||||
* @see #createListenerConsumer
|
* @see #createListenerConsumer
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected void doInitialize() throws JMSException {
|
protected void doInitialize() throws JMSException {
|
||||||
|
if (!this.connectLazily) {
|
||||||
|
try {
|
||||||
establishSharedConnection();
|
establishSharedConnection();
|
||||||
|
}
|
||||||
|
catch (JMSException ex) {
|
||||||
|
logger.debug("Could not connect on initialization - registering message consumers lazily", ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
initializeConsumers();
|
initializeConsumers();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Re-initializes this container's JMS message consumers,
|
* Re-initializes this container's JMS message consumers,
|
||||||
* if not initialized already.
|
* if not initialized already.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected void doStart() throws JMSException {
|
protected void doStart() throws JMSException {
|
||||||
super.doStart();
|
super.doStart();
|
||||||
initializeConsumers();
|
initializeConsumers();
|
||||||
|
|
@ -200,6 +228,7 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta
|
||||||
/**
|
/**
|
||||||
* Registers this listener container as JMS ExceptionListener on the shared connection.
|
* Registers this listener container as JMS ExceptionListener on the shared connection.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected void prepareSharedConnection(Connection connection) throws JMSException {
|
protected void prepareSharedConnection(Connection connection) throws JMSException {
|
||||||
super.prepareSharedConnection(connection);
|
super.prepareSharedConnection(connection);
|
||||||
connection.setExceptionListener(this);
|
connection.setExceptionListener(this);
|
||||||
|
|
@ -320,6 +349,7 @@ public class SimpleMessageListenerContainer extends AbstractMessageListenerConta
|
||||||
/**
|
/**
|
||||||
* Destroy the registered JMS Sessions and associated MessageConsumers.
|
* Destroy the registered JMS Sessions and associated MessageConsumers.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected void doShutdown() throws JMSException {
|
protected void doShutdown() throws JMSException {
|
||||||
logger.debug("Closing JMS MessageConsumers");
|
logger.debug("Closing JMS MessageConsumers");
|
||||||
for (MessageConsumer consumer : this.consumers) {
|
for (MessageConsumer consumer : this.consumers) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2010 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -787,7 +787,7 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
||||||
configTimeTransactionManagerHolder.remove();
|
configTimeTransactionManagerHolder.remove();
|
||||||
}
|
}
|
||||||
if (this.cacheRegionFactory != null) {
|
if (this.cacheRegionFactory != null) {
|
||||||
configTimeCacheProviderHolder.remove();
|
configTimeRegionFactoryHolder.remove();
|
||||||
}
|
}
|
||||||
if (this.cacheProvider != null) {
|
if (this.cacheProvider != null) {
|
||||||
configTimeCacheProviderHolder.remove();
|
configTimeCacheProviderHolder.remove();
|
||||||
|
|
@ -862,7 +862,7 @@ public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implemen
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the Configuration object used to build the SessionFactory.
|
* Return the Configuration object used to build the SessionFactory.
|
||||||
* Allows access to configuration metadata stored there (rarely needed).
|
* Allows for access to configuration metadata stored there (rarely needed).
|
||||||
* @throws IllegalStateException if the Configuration object has not been initialized yet
|
* @throws IllegalStateException if the Configuration object has not been initialized yet
|
||||||
*/
|
*/
|
||||||
public final Configuration getConfiguration() {
|
public final Configuration getConfiguration() {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -23,6 +23,7 @@ import javax.sql.DataSource;
|
||||||
|
|
||||||
import org.hibernate.Interceptor;
|
import org.hibernate.Interceptor;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.cfg.NamingStrategy;
|
import org.hibernate.cfg.NamingStrategy;
|
||||||
|
|
||||||
import org.springframework.beans.factory.DisposableBean;
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
|
@ -37,16 +38,15 @@ import org.springframework.core.io.support.ResourcePatternResolver;
|
||||||
import org.springframework.core.io.support.ResourcePatternUtils;
|
import org.springframework.core.io.support.ResourcePatternUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link org.springframework.beans.factory.FactoryBean} that creates a
|
* {@link org.springframework.beans.factory.FactoryBean} that creates a Hibernate
|
||||||
* Hibernate {@link org.hibernate.SessionFactory}. This is the usual way to
|
* {@link org.hibernate.SessionFactory}. This is the usual way to set up a shared
|
||||||
* set up a shared Hibernate SessionFactory in a Spring application context;
|
* Hibernate SessionFactory in a Spring application context; the SessionFactory can
|
||||||
* the SessionFactory can then be passed to Hibernate-based DAOs via
|
* then be passed to Hibernate-based data access objects via dependency injection.
|
||||||
* dependency injection.
|
|
||||||
*
|
*
|
||||||
* <p><b>NOTE:</b> This variant of LocalSessionFactoryBean requires Hibernate 4.0
|
* <p><b>NOTE:</b> This variant of LocalSessionFactoryBean requires Hibernate 4.0 or higher.
|
||||||
* or higher. It is similar in role to the same-named class in the <code>orm.hibernate3</code>
|
* It is similar in role to the same-named class in the <code>orm.hibernate3</code> package.
|
||||||
* package. However, in practice, it is closer to <code>AnnotationSessionFactoryBean</code>
|
* However, in practice, it is closer to <code>AnnotationSessionFactoryBean</code> since
|
||||||
* since its core purpose is to bootstrap a <code>SessionFactory</code> from annotation scanning.
|
* its core purpose is to bootstrap a <code>SessionFactory</code> from annotation scanning.
|
||||||
*
|
*
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
|
|
@ -84,6 +84,8 @@ public class LocalSessionFactoryBean extends HibernateExceptionTranslator
|
||||||
|
|
||||||
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
|
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
|
||||||
|
|
||||||
|
private Configuration configuration;
|
||||||
|
|
||||||
private SessionFactory sessionFactory;
|
private SessionFactory sessionFactory;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -328,7 +330,36 @@ public class LocalSessionFactoryBean extends HibernateExceptionTranslator
|
||||||
sfb.scanPackages(this.packagesToScan);
|
sfb.scanPackages(this.packagesToScan);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sessionFactory = sfb.buildSessionFactory();
|
// Build SessionFactory instance.
|
||||||
|
this.configuration = sfb;
|
||||||
|
this.sessionFactory = buildSessionFactory(sfb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclasses can override this method to perform custom initialization
|
||||||
|
* of the SessionFactory instance, creating it via the given Configuration
|
||||||
|
* object that got prepared by this LocalSessionFactoryBean.
|
||||||
|
* <p>The default implementation invokes LocalSessionFactoryBuilder's buildSessionFactory.
|
||||||
|
* A custom implementation could prepare the instance in a specific way (e.g. applying
|
||||||
|
* a custom ServiceRegistry) or use a custom SessionFactoryImpl subclass.
|
||||||
|
* @param sfb LocalSessionFactoryBuilder prepared by this LocalSessionFactoryBean
|
||||||
|
* @return the SessionFactory instance
|
||||||
|
* @see LocalSessionFactoryBuilder#buildSessionFactory
|
||||||
|
*/
|
||||||
|
protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder sfb) {
|
||||||
|
return sfb.buildSessionFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the Hibernate Configuration object used to build the SessionFactory.
|
||||||
|
* Allows for access to configuration metadata stored there (rarely needed).
|
||||||
|
* @throws IllegalStateException if the Configuration object has not been initialized yet
|
||||||
|
*/
|
||||||
|
public final Configuration getConfiguration() {
|
||||||
|
if (this.configuration == null) {
|
||||||
|
throw new IllegalStateException("Configuration not initialized yet");
|
||||||
|
}
|
||||||
|
return this.configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* 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.oxm.jaxb;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.xml.bind.annotation.XmlEnum;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import javax.xml.bind.annotation.XmlSeeAlso;
|
||||||
|
import javax.xml.bind.annotation.XmlType;
|
||||||
|
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||||
|
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||||
|
import org.springframework.core.io.support.ResourcePatternUtils;
|
||||||
|
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReader;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||||
|
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||||
|
import org.springframework.core.type.filter.TypeFilter;
|
||||||
|
import org.springframework.oxm.UncategorizedMappingException;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class for {@link Jaxb2Marshaller} that scans given packages for classes marked with JAXB2 annotations.
|
||||||
|
*
|
||||||
|
* @author Arjen Poutsma
|
||||||
|
* @author David Harrigan
|
||||||
|
* @see #scanPackages()
|
||||||
|
*/
|
||||||
|
class ClassPathJaxb2TypeScanner {
|
||||||
|
|
||||||
|
private static final String RESOURCE_PATTERN = "/**/*.class";
|
||||||
|
|
||||||
|
private final TypeFilter[] jaxb2TypeFilters =
|
||||||
|
new TypeFilter[]{new AnnotationTypeFilter(XmlRootElement.class, false),
|
||||||
|
new AnnotationTypeFilter(XmlType.class, false), new AnnotationTypeFilter(XmlSeeAlso.class, false),
|
||||||
|
new AnnotationTypeFilter(XmlEnum.class, false)};
|
||||||
|
|
||||||
|
private final String[] packagesToScan;
|
||||||
|
|
||||||
|
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
|
||||||
|
|
||||||
|
private List<Class<?>> jaxb2Classes = new ArrayList<Class<?>>();
|
||||||
|
|
||||||
|
/** Constructs a new {@code ClassPathJaxb2TypeScanner} for the given packages. */
|
||||||
|
ClassPathJaxb2TypeScanner(String[] packagesToScan) {
|
||||||
|
Assert.notEmpty(packagesToScan, "'packagesToScan' must not be empty");
|
||||||
|
this.packagesToScan = packagesToScan;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setResourceLoader(ResourceLoader resourceLoader) {
|
||||||
|
if (resourceLoader != null) {
|
||||||
|
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the JAXB2 classes found in the specified packages. */
|
||||||
|
Class<?>[] getJaxb2Classes() {
|
||||||
|
return jaxb2Classes.toArray(new Class<?>[jaxb2Classes.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scans the packages for classes marked with JAXB2 annotations.
|
||||||
|
*
|
||||||
|
* @throws UncategorizedMappingException in case of errors
|
||||||
|
*/
|
||||||
|
void scanPackages() throws UncategorizedMappingException {
|
||||||
|
try {
|
||||||
|
for (String packageToScan : packagesToScan) {
|
||||||
|
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
|
||||||
|
ClassUtils.convertClassNameToResourcePath(packageToScan) + RESOURCE_PATTERN;
|
||||||
|
Resource[] resources = resourcePatternResolver.getResources(pattern);
|
||||||
|
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
|
||||||
|
for (Resource resource : resources) {
|
||||||
|
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
|
||||||
|
if (isJaxb2Class(metadataReader, metadataReaderFactory)) {
|
||||||
|
String className = metadataReader.getClassMetadata().getClassName();
|
||||||
|
Class<?> jaxb2AnnotatedClass = resourcePatternResolver.getClassLoader().loadClass(className);
|
||||||
|
jaxb2Classes.add(jaxb2AnnotatedClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new UncategorizedMappingException("Failed to scan classpath for unlisted classes", ex);
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException ex) {
|
||||||
|
throw new UncategorizedMappingException("Failed to load annotated classes from classpath", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isJaxb2Class(MetadataReader reader, MetadataReaderFactory factory) throws IOException {
|
||||||
|
for (TypeFilter filter : jaxb2TypeFilters) {
|
||||||
|
if (filter.match(reader, factory)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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,7 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.oxm.jaxb;
|
package org.springframework.oxm.jaxb;
|
||||||
|
|
||||||
import java.awt.Image;
|
import java.awt.*;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
@ -65,10 +65,20 @@ import javax.xml.transform.sax.SAXSource;
|
||||||
import javax.xml.validation.Schema;
|
import javax.xml.validation.Schema;
|
||||||
import javax.xml.validation.SchemaFactory;
|
import javax.xml.validation.SchemaFactory;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.w3c.dom.ls.LSResourceResolver;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import org.xml.sax.XMLReader;
|
||||||
|
import org.xml.sax.helpers.XMLReaderFactory;
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.context.ResourceLoaderAware;
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
import org.springframework.oxm.GenericMarshaller;
|
import org.springframework.oxm.GenericMarshaller;
|
||||||
import org.springframework.oxm.GenericUnmarshaller;
|
import org.springframework.oxm.GenericUnmarshaller;
|
||||||
import org.springframework.oxm.MarshallingFailureException;
|
import org.springframework.oxm.MarshallingFailureException;
|
||||||
|
|
@ -87,14 +97,6 @@ import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.util.xml.StaxUtils;
|
import org.springframework.util.xml.StaxUtils;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.w3c.dom.ls.LSResourceResolver;
|
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
import org.xml.sax.XMLReader;
|
|
||||||
import org.xml.sax.helpers.XMLReaderFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of the <code>Marshaller</code> interface for JAXB 2.0.
|
* Implementation of the <code>Marshaller</code> interface for JAXB 2.0.
|
||||||
*
|
*
|
||||||
|
|
@ -117,7 +119,7 @@ import org.xml.sax.helpers.XMLReaderFactory;
|
||||||
*/
|
*/
|
||||||
public class Jaxb2Marshaller
|
public class Jaxb2Marshaller
|
||||||
implements MimeMarshaller, MimeUnmarshaller, GenericMarshaller, GenericUnmarshaller, BeanClassLoaderAware,
|
implements MimeMarshaller, MimeUnmarshaller, GenericMarshaller, GenericUnmarshaller, BeanClassLoaderAware,
|
||||||
InitializingBean {
|
ResourceLoaderAware, InitializingBean {
|
||||||
|
|
||||||
private static final String CID = "cid:";
|
private static final String CID = "cid:";
|
||||||
|
|
||||||
|
|
@ -131,6 +133,8 @@ public class Jaxb2Marshaller
|
||||||
|
|
||||||
private Class<?>[] classesToBeBound;
|
private Class<?>[] classesToBeBound;
|
||||||
|
|
||||||
|
private String[] packagesToScan;
|
||||||
|
|
||||||
private Map<String, ?> jaxbContextProperties;
|
private Map<String, ?> jaxbContextProperties;
|
||||||
|
|
||||||
private Map<String, ?> marshallerProperties;
|
private Map<String, ?> marshallerProperties;
|
||||||
|
|
@ -153,6 +157,8 @@ public class Jaxb2Marshaller
|
||||||
|
|
||||||
private ClassLoader beanClassLoader;
|
private ClassLoader beanClassLoader;
|
||||||
|
|
||||||
|
private ResourceLoader resourceLoader;
|
||||||
|
|
||||||
private JAXBContext jaxbContext;
|
private JAXBContext jaxbContext;
|
||||||
|
|
||||||
private Schema schema;
|
private Schema schema;
|
||||||
|
|
@ -175,6 +181,8 @@ public class Jaxb2Marshaller
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a JAXB context path.
|
* Set a JAXB context path.
|
||||||
|
* <p>Setting this property, {@link #setClassesToBeBound "classesToBeBound"}, or
|
||||||
|
* {@link #setPackagesToScan "packagesToScan"} is required.
|
||||||
*/
|
*/
|
||||||
public void setContextPath(String contextPath) {
|
public void setContextPath(String contextPath) {
|
||||||
Assert.hasText(contextPath, "'contextPath' must not be null");
|
Assert.hasText(contextPath, "'contextPath' must not be null");
|
||||||
|
|
@ -190,7 +198,8 @@ public class Jaxb2Marshaller
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the list of Java classes to be recognized by a newly created JAXBContext.
|
* Set the list of Java classes to be recognized by a newly created JAXBContext.
|
||||||
* Setting this property or {@link #setContextPath "contextPath"} is required.
|
* <p>Setting this property, {@link #setContextPath "contextPath"}, or
|
||||||
|
* {@link #setPackagesToScan "packagesToScan"} is required.
|
||||||
*/
|
*/
|
||||||
public void setClassesToBeBound(Class<?>... classesToBeBound) {
|
public void setClassesToBeBound(Class<?>... classesToBeBound) {
|
||||||
Assert.notEmpty(classesToBeBound, "'classesToBeBound' must not be empty");
|
Assert.notEmpty(classesToBeBound, "'classesToBeBound' must not be empty");
|
||||||
|
|
@ -204,6 +213,23 @@ public class Jaxb2Marshaller
|
||||||
return this.classesToBeBound;
|
return this.classesToBeBound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the packages to search using Spring-based scanning for classes with JAXB2 annotations in the classpath.
|
||||||
|
* <p>Setting this property, {@link #setContextPath "contextPath"}, or
|
||||||
|
* {@link #setClassesToBeBound "classesToBeBound"} is required. This is analogous to Spring's component-scan feature
|
||||||
|
* ({@link org.springframework.context.annotation.ClassPathBeanDefinitionScanner}).
|
||||||
|
*/
|
||||||
|
public void setPackagesToScan(String[] packagesToScan) {
|
||||||
|
this.packagesToScan = packagesToScan;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the packages to search for JAXB2 annotations.
|
||||||
|
*/
|
||||||
|
public String[] getPackagesToScan() {
|
||||||
|
return packagesToScan;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the <code>JAXBContext</code> properties. These implementation-specific
|
* Set the <code>JAXBContext</code> properties. These implementation-specific
|
||||||
* properties will be set on the underlying <code>JAXBContext</code>.
|
* properties will be set on the underlying <code>JAXBContext</code>.
|
||||||
|
|
@ -291,6 +317,7 @@ public class Jaxb2Marshaller
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the resource resolver, as used to load the schema resources.
|
* Sets the resource resolver, as used to load the schema resources.
|
||||||
|
*
|
||||||
* @see SchemaFactory#setResourceResolver(org.w3c.dom.ls.LSResourceResolver)
|
* @see SchemaFactory#setResourceResolver(org.w3c.dom.ls.LSResourceResolver)
|
||||||
* @see #setSchema(Resource)
|
* @see #setSchema(Resource)
|
||||||
* @see #setSchemas(Resource[])
|
* @see #setSchemas(Resource[])
|
||||||
|
|
@ -336,13 +363,23 @@ public class Jaxb2Marshaller
|
||||||
this.beanClassLoader = classLoader;
|
this.beanClassLoader = classLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||||
|
this.resourceLoader = resourceLoader;
|
||||||
|
}
|
||||||
|
|
||||||
public final void afterPropertiesSet() throws Exception {
|
public final void afterPropertiesSet() throws Exception {
|
||||||
if (StringUtils.hasLength(getContextPath()) && !ObjectUtils.isEmpty(getClassesToBeBound())) {
|
boolean hasContextPath = StringUtils.hasLength(getContextPath());
|
||||||
throw new IllegalArgumentException("Specify either 'contextPath' or 'classesToBeBound property'; not both");
|
boolean hasClassesToBeBound = !ObjectUtils.isEmpty(getClassesToBeBound());
|
||||||
|
boolean hasPackagesToScan = !ObjectUtils.isEmpty(getPackagesToScan());
|
||||||
|
|
||||||
|
if (hasContextPath && (hasClassesToBeBound || hasPackagesToScan) ||
|
||||||
|
(hasClassesToBeBound && hasPackagesToScan)) {
|
||||||
|
throw new IllegalArgumentException("Specify either 'contextPath', 'classesToBeBound', " +
|
||||||
|
"or 'packagesToScan'");
|
||||||
}
|
}
|
||||||
else if (!StringUtils.hasLength(getContextPath()) && ObjectUtils.isEmpty(getClassesToBeBound())) {
|
if (!hasContextPath && !hasClassesToBeBound && !hasPackagesToScan) {
|
||||||
throw new IllegalArgumentException("Setting either 'contextPath' or 'classesToBeBound' is required");
|
throw new IllegalArgumentException(
|
||||||
|
"Setting either 'contextPath', 'classesToBeBound', " + "or 'packagesToScan' is required");
|
||||||
}
|
}
|
||||||
if (!this.lazyInit) {
|
if (!this.lazyInit) {
|
||||||
getJaxbContext();
|
getJaxbContext();
|
||||||
|
|
@ -361,6 +398,9 @@ public class Jaxb2Marshaller
|
||||||
else if (!ObjectUtils.isEmpty(getClassesToBeBound())) {
|
else if (!ObjectUtils.isEmpty(getClassesToBeBound())) {
|
||||||
this.jaxbContext = createJaxbContextFromClasses();
|
this.jaxbContext = createJaxbContextFromClasses();
|
||||||
}
|
}
|
||||||
|
else if (!ObjectUtils.isEmpty(getPackagesToScan())) {
|
||||||
|
this.jaxbContext = createJaxbContextFromPackages();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (JAXBException ex) {
|
catch (JAXBException ex) {
|
||||||
throw convertJaxbException(ex);
|
throw convertJaxbException(ex);
|
||||||
|
|
@ -404,6 +444,26 @@ public class Jaxb2Marshaller
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JAXBContext createJaxbContextFromPackages() throws JAXBException {
|
||||||
|
if (logger.isInfoEnabled()) {
|
||||||
|
logger.info("Creating JAXBContext by scanning packages [" +
|
||||||
|
StringUtils.arrayToCommaDelimitedString(getPackagesToScan()) + "]");
|
||||||
|
}
|
||||||
|
ClassPathJaxb2TypeScanner scanner = new ClassPathJaxb2TypeScanner(getPackagesToScan());
|
||||||
|
scanner.setResourceLoader(this.resourceLoader);
|
||||||
|
scanner.scanPackages();
|
||||||
|
Class<?>[] jaxb2Classes = scanner.getJaxb2Classes();
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Found JAXB2 classes: [" + StringUtils.arrayToCommaDelimitedString(jaxb2Classes) + "]");
|
||||||
|
}
|
||||||
|
if (this.jaxbContextProperties != null) {
|
||||||
|
return JAXBContext.newInstance(jaxb2Classes, this.jaxbContextProperties);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return JAXBContext.newInstance(jaxb2Classes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Schema loadSchema(Resource[] resources, String schemaLanguage) throws IOException, SAXException {
|
private Schema loadSchema(Resource[] resources, String schemaLanguage) throws IOException, SAXException {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Setting validation schema to " + StringUtils.arrayToCommaDelimitedString(this.schemaResources));
|
logger.debug("Setting validation schema to " + StringUtils.arrayToCommaDelimitedString(this.schemaResources));
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -279,6 +279,13 @@ public class Jaxb2MarshallerTests extends AbstractMarshallerTests {
|
||||||
assertTrue("No XML written", writer.toString().length() > 0);
|
assertTrue("No XML written", writer.toString().length() > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void supportsPackagesToScan() throws Exception {
|
||||||
|
marshaller = new Jaxb2Marshaller();
|
||||||
|
marshaller.setPackagesToScan(new String[] {CONTEXT_PATH});
|
||||||
|
marshaller.afterPropertiesSet();
|
||||||
|
}
|
||||||
|
|
||||||
@XmlRootElement
|
@XmlRootElement
|
||||||
public static class DummyRootElement {
|
public static class DummyRootElement {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ Import-Template:
|
||||||
org.exolab.castor.*;version="[1.2.0, 2.0.0)";resolution:=optional,
|
org.exolab.castor.*;version="[1.2.0, 2.0.0)";resolution:=optional,
|
||||||
org.jibx.runtime.*;version="[1.1.5, 2.0.0)";resolution:=optional,
|
org.jibx.runtime.*;version="[1.1.5, 2.0.0)";resolution:=optional,
|
||||||
org.springframework.beans.*;version=${spring.osgi.range},
|
org.springframework.beans.*;version=${spring.osgi.range},
|
||||||
|
org.springframework.context.*;version=${spring.osgi.range},
|
||||||
org.springframework.core.*;version=${spring.osgi.range},
|
org.springframework.core.*;version=${spring.osgi.range},
|
||||||
org.springframework.util.*;version=${spring.osgi.range},
|
org.springframework.util.*;version=${spring.osgi.range},
|
||||||
org.w3c.dom.*;version="0",
|
org.w3c.dom.*;version="0",
|
||||||
|
|
|
||||||
|
|
@ -815,7 +815,7 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.flashMapManager.requestStarted(request);
|
this.flashMapManager.requestStarted(request, response);
|
||||||
|
|
||||||
// Make framework objects available to handlers and view objects.
|
// Make framework objects available to handlers and view objects.
|
||||||
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
|
request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
|
||||||
|
|
@ -827,7 +827,7 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||||
doDispatch(request, response);
|
doDispatch(request, response);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
this.flashMapManager.requestCompleted(request);
|
this.flashMapManager.requestCompleted(request, response);
|
||||||
|
|
||||||
// Restore the original attribute snapshot, in case of an include.
|
// Restore the original attribute snapshot, in case of an include.
|
||||||
if (attributesSnapshot != null) {
|
if (attributesSnapshot != null) {
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,8 @@ public final class FlashMap extends HashMap<String, Object> implements Comparabl
|
||||||
/**
|
/**
|
||||||
* Create a new instance with an id uniquely identifying the creator of
|
* Create a new instance with an id uniquely identifying the creator of
|
||||||
* this FlashMap.
|
* this FlashMap.
|
||||||
|
* @param createdBy identifies the FlashMapManager instance that created
|
||||||
|
* and will manage this FlashMap instance (e.g. via a hashCode)
|
||||||
*/
|
*/
|
||||||
public FlashMap(int createdBy) {
|
public FlashMap(int createdBy) {
|
||||||
this.createdBy = createdBy;
|
this.createdBy = createdBy;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.web.servlet;
|
package org.springframework.web.servlet;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A strategy interface for storing, retrieving, and managing {@code FlashMap}
|
* A strategy interface for storing, retrieving, and managing {@code FlashMap}
|
||||||
|
|
@ -64,8 +65,9 @@ public interface FlashMapManager {
|
||||||
* <li>Clean expired FlashMap instances.
|
* <li>Clean expired FlashMap instances.
|
||||||
* </ol>
|
* </ol>
|
||||||
* @param request the current request
|
* @param request the current request
|
||||||
|
* @param response the current response
|
||||||
*/
|
*/
|
||||||
void requestStarted(HttpServletRequest request);
|
void requestStarted(HttpServletRequest request, HttpServletResponse response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the expiration period of the "output" FlashMap save it in the
|
* Start the expiration period of the "output" FlashMap save it in the
|
||||||
|
|
@ -73,7 +75,8 @@ public interface FlashMapManager {
|
||||||
* <p>The "output" FlashMap should not be saved if it is empty or if it was
|
* <p>The "output" FlashMap should not be saved if it is empty or if it was
|
||||||
* not created by the current FlashMapManager instance.
|
* not created by the current FlashMapManager instance.
|
||||||
* @param request the current request
|
* @param request the current request
|
||||||
|
* @param response the current response
|
||||||
*/
|
*/
|
||||||
void requestCompleted(HttpServletRequest request);
|
void requestCompleted(HttpServletRequest request, HttpServletResponse response);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,14 @@ import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for {@link org.springframework.web.servlet.HandlerExceptionResolver HandlerExceptionResolver}
|
* Abstract base class for
|
||||||
* implementations that support handling exceptions from {@link HandlerMethod}s rather than handlers.
|
* {@link org.springframework.web.servlet.HandlerExceptionResolver HandlerExceptionResolver}
|
||||||
|
* implementations that support handling exceptions from handlers of type {@link HandlerMethod}.
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
public class AbstractHandlerMethodExceptionResolver extends AbstractHandlerExceptionResolver {
|
public abstract class AbstractHandlerMethodExceptionResolver extends AbstractHandlerExceptionResolver {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the handler is a {@link HandlerMethod} instance and performs the check against the bean
|
* Checks if the handler is a {@link HandlerMethod} instance and performs the check against the bean
|
||||||
|
|
@ -52,10 +53,10 @@ public class AbstractHandlerMethodExceptionResolver extends AbstractHandlerExcep
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final ModelAndView doResolveException(HttpServletRequest request,
|
protected final ModelAndView doResolveException(
|
||||||
HttpServletResponse response,
|
HttpServletRequest request, HttpServletResponse response,
|
||||||
Object handler,
|
Object handler, Exception ex) {
|
||||||
Exception ex) {
|
|
||||||
return doResolveHandlerMethodException(request, response, (HandlerMethod) handler, ex);
|
return doResolveHandlerMethodException(request, response, (HandlerMethod) handler, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,11 +74,8 @@ public class AbstractHandlerMethodExceptionResolver extends AbstractHandlerExcep
|
||||||
* @param ex the exception that got thrown during handler execution
|
* @param ex the exception that got thrown during handler execution
|
||||||
* @return a corresponding ModelAndView to forward to, or <code>null</code> for default processing
|
* @return a corresponding ModelAndView to forward to, or <code>null</code> for default processing
|
||||||
*/
|
*/
|
||||||
protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request,
|
protected abstract ModelAndView doResolveHandlerMethodException(
|
||||||
HttpServletResponse response,
|
HttpServletRequest request, HttpServletResponse response,
|
||||||
HandlerMethod handlerMethod,
|
HandlerMethod handlerMethod, Exception ex);
|
||||||
Exception ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
import org.springframework.web.servlet.support.RequestContextUtils;
|
||||||
import org.springframework.web.util.UrlPathHelper;
|
import org.springframework.web.util.UrlPathHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -86,7 +87,8 @@ public abstract class AbstractUrlViewController extends AbstractController {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the URL path to use for lookup and delegates to
|
* Retrieves the URL path to use for lookup and delegates to
|
||||||
* {@link #getViewNameForRequest}.
|
* {@link #getViewNameForRequest}. Also adds the content of
|
||||||
|
* {@link RequestContextUtils#getInputFlashMap} to the model.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
|
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
|
@ -95,7 +97,7 @@ public abstract class AbstractUrlViewController extends AbstractController {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Returning view name '" + viewName + "' for lookup path [" + lookupPath + "]");
|
logger.debug("Returning view name '" + viewName + "' for lookup path [" + lookupPath + "]");
|
||||||
}
|
}
|
||||||
return new ModelAndView(viewName);
|
return new ModelAndView(viewName, RequestContextUtils.getInputFlashMap(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
import org.springframework.web.servlet.support.RequestContextUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Trivial controller that always returns a named view. The view
|
* <p>Trivial controller that always returns a named view. The view
|
||||||
|
|
@ -87,12 +88,13 @@ public class ParameterizableViewController extends AbstractController {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a ModelAndView object with the specified view name.
|
* Return a ModelAndView object with the specified view name.
|
||||||
|
* The content of {@link RequestContextUtils#getInputFlashMap} is also added to the model.
|
||||||
* @see #getViewName()
|
* @see #getViewName()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
|
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
return new ModelAndView(getViewName());
|
return new ModelAndView(getViewName(), RequestContextUtils.getInputFlashMap(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li>Sort 'Accept' header media types by quality value via
|
* <li>Sort 'Accept' header media types by quality value via
|
||||||
* {@link MediaType#sortByQualityValue(List)} and iterate the list.
|
* {@link MediaType#sortByQualityValue(List)} and iterate the list.
|
||||||
* <li>Get the lowest index of matching media types from each "produces"
|
* <li>Get the first index of matching media types in each "produces"
|
||||||
* condition first matching with {@link MediaType#equals(Object)} and
|
* condition first matching with {@link MediaType#equals(Object)} and
|
||||||
* then with {@link MediaType#includes(MediaType)}.
|
* then with {@link MediaType#includes(MediaType)}.
|
||||||
* <li>If a lower index is found, the condition at that index wins.
|
* <li>If a lower index is found, the condition at that index wins.
|
||||||
|
|
@ -220,7 +220,9 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
|
||||||
|
|
||||||
private int indexOfEqualMediaType(MediaType mediaType) {
|
private int indexOfEqualMediaType(MediaType mediaType) {
|
||||||
for (int i = 0; i < getExpressionsToCompare().size(); i++) {
|
for (int i = 0; i < getExpressionsToCompare().size(); i++) {
|
||||||
if (mediaType.equals(getExpressionsToCompare().get(i).getMediaType())) {
|
MediaType currentMediaType = getExpressionsToCompare().get(i).getMediaType();
|
||||||
|
if (mediaType.getType().equalsIgnoreCase(currentMediaType.getType()) &&
|
||||||
|
mediaType.getSubtype().equalsIgnoreCase(currentMediaType.getSubtype())) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -66,10 +66,9 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
|
||||||
return HttpEntity.class.equals(parameterType) || ResponseEntity.class.equals(parameterType);
|
return HttpEntity.class.equals(parameterType) || ResponseEntity.class.equals(parameterType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object resolveArgument(MethodParameter parameter,
|
public Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest,
|
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory)
|
|
||||||
throws IOException, HttpMediaTypeNotSupportedException {
|
throws IOException, HttpMediaTypeNotSupportedException {
|
||||||
|
|
||||||
HttpInputMessage inputMessage = createInputMessage(webRequest);
|
HttpInputMessage inputMessage = createInputMessage(webRequest);
|
||||||
|
|
@ -100,10 +99,10 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
|
||||||
+ "in method " + parameter.getMethod() + "is not parameterized");
|
+ "in method " + parameter.getMethod() + "is not parameterized");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleReturnValue(Object returnValue,
|
public void handleReturnValue(
|
||||||
MethodParameter returnType,
|
Object returnValue, MethodParameter returnType,
|
||||||
ModelAndViewContainer mavContainer,
|
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
|
||||||
NativeWebRequest webRequest) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
mavContainer.setRequestHandled(true);
|
mavContainer.setRequestHandled(true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,10 +46,11 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn
|
||||||
return ModelAndView.class.isAssignableFrom(returnType.getParameterType());
|
return ModelAndView.class.isAssignableFrom(returnType.getParameterType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleReturnValue(Object returnValue,
|
public void handleReturnValue(
|
||||||
MethodParameter returnType,
|
Object returnValue, MethodParameter returnType,
|
||||||
ModelAndViewContainer mavContainer,
|
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
|
||||||
NativeWebRequest webRequest) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
if (returnValue == null) {
|
if (returnValue == null) {
|
||||||
mavContainer.setRequestHandled(true);
|
mavContainer.setRequestHandled(true);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -71,10 +71,10 @@ public class ModelAndViewResolverMethodReturnValueHandler implements HandlerMeth
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleReturnValue(Object returnValue,
|
public void handleReturnValue(
|
||||||
MethodParameter returnType,
|
Object returnValue, MethodParameter returnType,
|
||||||
ModelAndViewContainer mavContainer,
|
ModelAndViewContainer mavContainer, NativeWebRequest request)
|
||||||
NativeWebRequest request) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
if (this.mavResolvers != null) {
|
if (this.mavResolvers != null) {
|
||||||
for (ModelAndViewResolver mavResolver : this.mavResolvers) {
|
for (ModelAndViewResolver mavResolver : this.mavResolvers) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -46,10 +46,11 @@ public class RedirectAttributesMethodArgumentResolver implements HandlerMethodAr
|
||||||
return RedirectAttributes.class.isAssignableFrom(parameter.getParameterType());
|
return RedirectAttributes.class.isAssignableFrom(parameter.getParameterType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object resolveArgument(MethodParameter parameter,
|
public Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest,
|
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
DataBinder dataBinder = binderFactory.createBinder(webRequest, null, null);
|
DataBinder dataBinder = binderFactory.createBinder(webRequest, null, null);
|
||||||
ModelMap redirectAttributes = new RedirectAttributesModelMap(dataBinder);
|
ModelMap redirectAttributes = new RedirectAttributesModelMap(dataBinder);
|
||||||
mavContainer.setRedirectModel(redirectAttributes);
|
mavContainer.setRedirectModel(redirectAttributes);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -89,9 +89,9 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
|
||||||
* @param mavContainer the {@link ModelAndViewContainer} for the current request
|
* @param mavContainer the {@link ModelAndViewContainer} for the current request
|
||||||
* @param providedArgs argument values to try to use without the need for view resolution
|
* @param providedArgs argument values to try to use without the need for view resolution
|
||||||
*/
|
*/
|
||||||
public final void invokeAndHandle(NativeWebRequest request,
|
public final void invokeAndHandle(
|
||||||
ModelAndViewContainer mavContainer,
|
NativeWebRequest request, ModelAndViewContainer mavContainer,
|
||||||
Object...providedArgs) throws Exception {
|
Object... providedArgs) throws Exception {
|
||||||
|
|
||||||
Object returnValue = invokeForRequest(request, mavContainer, providedArgs);
|
Object returnValue = invokeForRequest(request, mavContainer, providedArgs);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -67,10 +67,10 @@ public class ServletRequestMethodArgumentResolver implements HandlerMethodArgume
|
||||||
Reader.class.isAssignableFrom(paramType);
|
Reader.class.isAssignableFrom(paramType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object resolveArgument(MethodParameter parameter,
|
public Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest,
|
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory) throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
Class<?> paramType = parameter.getParameterType();
|
Class<?> paramType = parameter.getParameterType();
|
||||||
if (WebRequest.class.isAssignableFrom(paramType)) {
|
if (WebRequest.class.isAssignableFrom(paramType)) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -57,10 +57,10 @@ public class ServletResponseMethodArgumentResolver implements HandlerMethodArgum
|
||||||
* to the response. If subsequently the underlying method returns
|
* to the response. If subsequently the underlying method returns
|
||||||
* {@code null}, the request is considered directly handled.
|
* {@code null}, the request is considered directly handled.
|
||||||
*/
|
*/
|
||||||
public Object resolveArgument(MethodParameter parameter,
|
public Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest,
|
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory) throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
mavContainer.setRequestHandled(true);
|
mavContainer.setRequestHandled(true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -41,10 +41,10 @@ public class UriComponentsBuilderMethodArgumentResolver implements HandlerMethod
|
||||||
return UriComponentsBuilder.class.isAssignableFrom(parameter.getParameterType());
|
return UriComponentsBuilder.class.isAssignableFrom(parameter.getParameterType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object resolveArgument(MethodParameter parameter,
|
public Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest,
|
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
|
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
|
||||||
return ServletUriComponentsBuilder.fromServletMapping(request);
|
return ServletUriComponentsBuilder.fromServletMapping(request);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -44,10 +44,11 @@ public class ViewMethodReturnValueHandler implements HandlerMethodReturnValueHan
|
||||||
return View.class.isAssignableFrom(returnType.getParameterType());
|
return View.class.isAssignableFrom(returnType.getParameterType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleReturnValue(Object returnValue,
|
public void handleReturnValue(
|
||||||
MethodParameter returnType,
|
Object returnValue, MethodParameter returnType,
|
||||||
ModelAndViewContainer mavContainer,
|
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
|
||||||
NativeWebRequest webRequest) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
if (returnValue == null) {
|
if (returnValue == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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,10 +45,11 @@ public class ViewNameMethodReturnValueHandler implements HandlerMethodReturnValu
|
||||||
return (void.class.equals(paramType) || String.class.equals(paramType));
|
return (void.class.equals(paramType) || String.class.equals(paramType));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleReturnValue(Object returnValue,
|
public void handleReturnValue(
|
||||||
MethodParameter returnType,
|
Object returnValue, MethodParameter returnType,
|
||||||
ModelAndViewContainer mavContainer,
|
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
|
||||||
NativeWebRequest webRequest) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
if (returnValue == null) {
|
if (returnValue == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,12 @@ import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
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.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
@ -47,24 +49,46 @@ public class DefaultFlashMapManager implements FlashMapManager {
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(DefaultFlashMapManager.class);
|
private static final Log logger = LogFactory.getLog(DefaultFlashMapManager.class);
|
||||||
|
|
||||||
private int flashTimeout = 180;
|
private int flashMapTimeout = 180;
|
||||||
|
|
||||||
private final UrlPathHelper urlPathHelper = new UrlPathHelper();
|
private UrlPathHelper urlPathHelper = new UrlPathHelper();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the amount of time in seconds after a {@link FlashMap} is saved
|
* Set the amount of time in seconds after a {@link FlashMap} is saved
|
||||||
* (at request completion) and before it expires.
|
* (at request completion) and before it expires.
|
||||||
* <p>The default value is 180 seconds.
|
* <p>The default value is 180 seconds.
|
||||||
*/
|
*/
|
||||||
public void setFlashMapTimeout(int flashTimeout) {
|
public void setFlashMapTimeout(int flashMapTimeout) {
|
||||||
this.flashTimeout = flashTimeout;
|
this.flashMapTimeout = flashMapTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the amount of time in seconds before a FlashMap expires.
|
||||||
|
*/
|
||||||
|
public int getFlashMapTimeout() {
|
||||||
|
return flashMapTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the UrlPathHelper to use to obtain the request URI.
|
||||||
|
*/
|
||||||
|
public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
|
||||||
|
Assert.notNull(urlPathHelper, "UrlPathHelper must not be null");
|
||||||
|
this.urlPathHelper = urlPathHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the UrlPathHelper implementation for the request URI.
|
||||||
|
*/
|
||||||
|
public UrlPathHelper getUrlPathHelper() {
|
||||||
|
return urlPathHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* <p>An HTTP session is never created by this method.
|
* <p>An HTTP session is never created by this method.
|
||||||
*/
|
*/
|
||||||
public void requestStarted(HttpServletRequest request) {
|
public final void requestStarted(HttpServletRequest request, HttpServletResponse response) {
|
||||||
if (request.getAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE) != null) {
|
if (request.getAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE) != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -164,9 +188,9 @@ public class DefaultFlashMapManager implements FlashMapManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterate all flash maps and remove expired ones.
|
* Check and remove expired FlashMaps instances.
|
||||||
*/
|
*/
|
||||||
private void removeExpiredFlashMaps(HttpServletRequest request) {
|
protected void removeExpiredFlashMaps(HttpServletRequest request) {
|
||||||
List<FlashMap> allMaps = retrieveFlashMaps(request, false);
|
List<FlashMap> allMaps = retrieveFlashMaps(request, false);
|
||||||
if (CollectionUtils.isEmpty(allMaps)) {
|
if (CollectionUtils.isEmpty(allMaps)) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -189,7 +213,7 @@ public class DefaultFlashMapManager implements FlashMapManager {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* <p>An HTTP session is never created if the "output" FlashMap is empty.
|
* <p>An HTTP session is never created if the "output" FlashMap is empty.
|
||||||
*/
|
*/
|
||||||
public void requestCompleted(HttpServletRequest request) {
|
public void requestCompleted(HttpServletRequest request, HttpServletResponse response) {
|
||||||
FlashMap flashMap = (FlashMap) request.getAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE);
|
FlashMap flashMap = (FlashMap) request.getAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE);
|
||||||
if (flashMap == null) {
|
if (flashMap == null) {
|
||||||
throw new IllegalStateException("requestCompleted called but \"output\" FlashMap was never created");
|
throw new IllegalStateException("requestCompleted called but \"output\" FlashMap was never created");
|
||||||
|
|
@ -198,22 +222,33 @@ public class DefaultFlashMapManager implements FlashMapManager {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Saving FlashMap=" + flashMap);
|
logger.debug("Saving FlashMap=" + flashMap);
|
||||||
}
|
}
|
||||||
onSaveFlashMap(flashMap, request);
|
onSaveFlashMap(flashMap, request, response);
|
||||||
retrieveFlashMaps(request, true).add(flashMap);
|
saveFlashMap(flashMap, request, response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a FlashMap before it is stored in the HTTP Session.
|
* Update a FlashMap before it is stored in the underlying storage.
|
||||||
* <p>The default implementation starts the expiration period and ensures the
|
* <p>The default implementation starts the expiration period and ensures the
|
||||||
* target request path is decoded and normalized if it is relative.
|
* target request path is decoded and normalized if it is relative.
|
||||||
* @param flashMap the flash map to be saved
|
* @param flashMap the flash map to be saved
|
||||||
* @param request the current request
|
* @param request the current request
|
||||||
|
* @param response the current response
|
||||||
*/
|
*/
|
||||||
protected void onSaveFlashMap(FlashMap flashMap, HttpServletRequest request) {
|
protected void onSaveFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response) {
|
||||||
String targetPath = flashMap.getTargetRequestPath();
|
String targetPath = flashMap.getTargetRequestPath();
|
||||||
flashMap.setTargetRequestPath(decodeAndNormalizePath(targetPath, request));
|
flashMap.setTargetRequestPath(decodeAndNormalizePath(targetPath, request));
|
||||||
flashMap.startExpirationPeriod(this.flashTimeout);
|
flashMap.startExpirationPeriod(this.flashMapTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the FlashMap in the underlying storage.
|
||||||
|
* @param flashMap the FlashMap to save
|
||||||
|
* @param request the current request
|
||||||
|
* @param response the current response
|
||||||
|
*/
|
||||||
|
protected void saveFlashMap(FlashMap flashMap, HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
retrieveFlashMaps(request, true).add(flashMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String decodeAndNormalizePath(String path, HttpServletRequest request) {
|
private String decodeAndNormalizePath(String path, HttpServletRequest request) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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.web.servlet.mvc;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.web.servlet.FlashMapManager;
|
||||||
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test fixture with a ParameterizableViewController.
|
||||||
|
*
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
* @since 3.1.1
|
||||||
|
*/
|
||||||
|
public class ParameterizableViewControllerTests {
|
||||||
|
|
||||||
|
private ParameterizableViewController controller;
|
||||||
|
|
||||||
|
private MockHttpServletRequest request;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
this.controller = new ParameterizableViewController();
|
||||||
|
this.request = new MockHttpServletRequest("GET", "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handleRequestWithViewName() throws Exception {
|
||||||
|
String viewName = "testView";
|
||||||
|
this.controller.setViewName(viewName);
|
||||||
|
ModelAndView mav = this.controller.handleRequest(this.request, new MockHttpServletResponse());
|
||||||
|
assertEquals(viewName, mav.getViewName());
|
||||||
|
assertTrue(mav.getModel().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handleRequestWithoutViewName() throws Exception {
|
||||||
|
ModelAndView mav = this.controller.handleRequest(this.request, new MockHttpServletResponse());
|
||||||
|
assertNull(mav.getViewName());
|
||||||
|
assertTrue(mav.getModel().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void handleRequestWithFlashAttributes() throws Exception {
|
||||||
|
this.request.setAttribute(FlashMapManager.INPUT_FLASH_MAP_ATTRIBUTE, new ModelMap("name", "value"));
|
||||||
|
ModelAndView mav = this.controller.handleRequest(this.request, new MockHttpServletResponse());
|
||||||
|
assertEquals(1, mav.getModel().size());
|
||||||
|
assertEquals("value", mav.getModel().get("name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -20,8 +20,10 @@ import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
import org.springframework.util.AntPathMatcher;
|
import org.springframework.util.AntPathMatcher;
|
||||||
import org.springframework.util.PathMatcher;
|
import org.springframework.util.PathMatcher;
|
||||||
|
import org.springframework.web.servlet.FlashMapManager;
|
||||||
import org.springframework.web.servlet.HandlerMapping;
|
import org.springframework.web.servlet.HandlerMapping;
|
||||||
import org.springframework.web.servlet.ModelAndView;
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
|
|
@ -150,6 +152,17 @@ public class UrlFilenameViewControllerTests extends TestCase {
|
||||||
assertTrue(mv.getModel().isEmpty());
|
assertTrue(mv.getModel().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testWithFlashAttributes() throws Exception {
|
||||||
|
UrlFilenameViewController ctrl = new UrlFilenameViewController();
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/index");
|
||||||
|
request.setAttribute(FlashMapManager.INPUT_FLASH_MAP_ATTRIBUTE, new ModelMap("name", "value"));
|
||||||
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
|
ModelAndView mv = ctrl.handleRequest(request, response);
|
||||||
|
assertEquals("index", mv.getViewName());
|
||||||
|
assertEquals(1, mv.getModel().size());
|
||||||
|
assertEquals("value", mv.getModel().get("name"));
|
||||||
|
}
|
||||||
|
|
||||||
private void exposePathInMapping(MockHttpServletRequest request, String mapping) {
|
private void exposePathInMapping(MockHttpServletRequest request, String mapping) {
|
||||||
String pathInMapping = this.pathMatcher.extractPathWithinPattern(mapping, request.getRequestURI());
|
String pathInMapping = this.pathMatcher.extractPathWithinPattern(mapping, request.getRequestURI());
|
||||||
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathInMapping);
|
request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathInMapping);
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,20 @@ public class ProducesRequestConditionTests {
|
||||||
assertTrue(condition2.compareTo(condition1, request) > 0);
|
assertTrue(condition2.compareTo(condition1, request) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SPR-9021
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void compareToMediaTypeAllWithParameter() {
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
request.addHeader("Accept", "*/*;q=0.9");
|
||||||
|
|
||||||
|
ProducesRequestCondition condition1 = new ProducesRequestCondition();
|
||||||
|
ProducesRequestCondition condition2 = new ProducesRequestCondition("application/json");
|
||||||
|
|
||||||
|
assertTrue(condition1.compareTo(condition2, request) < 0);
|
||||||
|
assertTrue(condition2.compareTo(condition1, request) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void compareToEqualMatch() {
|
public void compareToEqualMatch() {
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
import org.springframework.web.servlet.FlashMap;
|
import org.springframework.web.servlet.FlashMap;
|
||||||
import org.springframework.web.util.WebUtils;
|
import org.springframework.web.util.WebUtils;
|
||||||
|
|
||||||
|
|
@ -46,15 +47,18 @@ public class DefaultFlashMapManagerTests {
|
||||||
|
|
||||||
private MockHttpServletRequest request;
|
private MockHttpServletRequest request;
|
||||||
|
|
||||||
|
private MockHttpServletResponse response;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
this.flashMapManager = new DefaultFlashMapManager();
|
this.flashMapManager = new DefaultFlashMapManager();
|
||||||
this.request = new MockHttpServletRequest();
|
this.request = new MockHttpServletRequest();
|
||||||
|
this.response = new MockHttpServletResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void requestStarted() {
|
public void requestStarted() {
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
|
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);
|
||||||
|
|
||||||
assertNotNull("Current FlashMap not found", flashMap);
|
assertNotNull("Current FlashMap not found", flashMap);
|
||||||
|
|
@ -64,7 +68,7 @@ public class DefaultFlashMapManagerTests {
|
||||||
public void requestStartedAlready() {
|
public void requestStartedAlready() {
|
||||||
FlashMap flashMap = new FlashMap();
|
FlashMap flashMap = new FlashMap();
|
||||||
this.request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, flashMap);
|
this.request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, flashMap);
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
|
|
||||||
assertSame(flashMap, RequestContextUtils.getOutputFlashMap(request));
|
assertSame(flashMap, RequestContextUtils.getOutputFlashMap(request));
|
||||||
}
|
}
|
||||||
|
|
@ -79,7 +83,7 @@ public class DefaultFlashMapManagerTests {
|
||||||
allMaps.add(flashMap);
|
allMaps.add(flashMap);
|
||||||
|
|
||||||
this.request.setRequestURI("/path");
|
this.request.setRequestURI("/path");
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
|
|
||||||
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
||||||
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
||||||
|
|
@ -98,7 +102,7 @@ public class DefaultFlashMapManagerTests {
|
||||||
|
|
||||||
this.request.setAttribute(WebUtils.FORWARD_REQUEST_URI_ATTRIBUTE, "/accounts");
|
this.request.setAttribute(WebUtils.FORWARD_REQUEST_URI_ATTRIBUTE, "/accounts");
|
||||||
this.request.setRequestURI("/mvc/accounts");
|
this.request.setRequestURI("/mvc/accounts");
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
|
|
||||||
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
||||||
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
||||||
|
|
@ -114,7 +118,7 @@ public class DefaultFlashMapManagerTests {
|
||||||
allMaps.add(flashMap);
|
allMaps.add(flashMap);
|
||||||
|
|
||||||
this.request.setRequestURI("/path/");
|
this.request.setRequestURI("/path/");
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
|
|
||||||
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
||||||
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
||||||
|
|
@ -130,21 +134,21 @@ public class DefaultFlashMapManagerTests {
|
||||||
allMaps.add(flashMap);
|
allMaps.add(flashMap);
|
||||||
|
|
||||||
this.request.setParameter("number", (String) null);
|
this.request.setParameter("number", (String) null);
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
|
|
||||||
assertNull(RequestContextUtils.getInputFlashMap(this.request));
|
assertNull(RequestContextUtils.getInputFlashMap(this.request));
|
||||||
assertEquals("FlashMap should not have been removed", 1, getFlashMaps().size());
|
assertEquals("FlashMap should not have been removed", 1, getFlashMaps().size());
|
||||||
|
|
||||||
clearFlashMapRequestAttributes();
|
clearFlashMapRequestAttributes();
|
||||||
this.request.setParameter("number", "two");
|
this.request.setParameter("number", "two");
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
|
|
||||||
assertNull(RequestContextUtils.getInputFlashMap(this.request));
|
assertNull(RequestContextUtils.getInputFlashMap(this.request));
|
||||||
assertEquals("FlashMap should not have been removed", 1, getFlashMaps().size());
|
assertEquals("FlashMap should not have been removed", 1, getFlashMaps().size());
|
||||||
|
|
||||||
clearFlashMapRequestAttributes();
|
clearFlashMapRequestAttributes();
|
||||||
this.request.setParameter("number", "one");
|
this.request.setParameter("number", "one");
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
|
|
||||||
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
||||||
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
||||||
|
|
@ -163,14 +167,14 @@ public class DefaultFlashMapManagerTests {
|
||||||
allMaps.add(flashMap);
|
allMaps.add(flashMap);
|
||||||
|
|
||||||
this.request.setParameter("id", "1");
|
this.request.setParameter("id", "1");
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
|
|
||||||
assertNull(RequestContextUtils.getInputFlashMap(this.request));
|
assertNull(RequestContextUtils.getInputFlashMap(this.request));
|
||||||
assertEquals("FlashMap should not have been removed", 1, getFlashMaps().size());
|
assertEquals("FlashMap should not have been removed", 1, getFlashMaps().size());
|
||||||
|
|
||||||
clearFlashMapRequestAttributes();
|
clearFlashMapRequestAttributes();
|
||||||
this.request.addParameter("id", "2");
|
this.request.addParameter("id", "2");
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
|
|
||||||
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
assertEquals(flashMap, RequestContextUtils.getInputFlashMap(this.request));
|
||||||
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
assertEquals("Input FlashMap should have been removed", 0, getFlashMaps().size());
|
||||||
|
|
@ -196,7 +200,7 @@ public class DefaultFlashMapManagerTests {
|
||||||
Collections.shuffle(allMaps);
|
Collections.shuffle(allMaps);
|
||||||
|
|
||||||
this.request.setRequestURI("/one/two");
|
this.request.setRequestURI("/one/two");
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
|
|
||||||
assertEquals(flashMapTwo, request.getAttribute(INPUT_FLASH_MAP_ATTRIBUTE));
|
assertEquals(flashMapTwo, request.getAttribute(INPUT_FLASH_MAP_ATTRIBUTE));
|
||||||
}
|
}
|
||||||
|
|
@ -210,15 +214,15 @@ public class DefaultFlashMapManagerTests {
|
||||||
flashMap.startExpirationPeriod(0);
|
flashMap.startExpirationPeriod(0);
|
||||||
}
|
}
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
|
|
||||||
assertEquals(0, allMaps.size());
|
assertEquals(0, allMaps.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void saveFlashMapWithoutAttributes() throws InterruptedException {
|
public void saveFlashMapWithoutAttributes() throws InterruptedException {
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
this.flashMapManager.requestCompleted(this.request);
|
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||||
|
|
||||||
assertNull(getFlashMaps());
|
assertNull(getFlashMaps());
|
||||||
}
|
}
|
||||||
|
|
@ -227,19 +231,19 @@ public class DefaultFlashMapManagerTests {
|
||||||
public void saveFlashMapNotCreatedByThisManager() throws InterruptedException {
|
public void saveFlashMapNotCreatedByThisManager() throws InterruptedException {
|
||||||
FlashMap flashMap = new FlashMap();
|
FlashMap flashMap = new FlashMap();
|
||||||
this.request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, flashMap);
|
this.request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, flashMap);
|
||||||
this.flashMapManager.requestCompleted(this.request);
|
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||||
|
|
||||||
assertNull(getFlashMaps());
|
assertNull(getFlashMaps());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void saveFlashMapWithAttributes() throws InterruptedException {
|
public void saveFlashMapWithAttributes() throws InterruptedException {
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(this.request);
|
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(this.request);
|
||||||
flashMap.put("name", "value");
|
flashMap.put("name", "value");
|
||||||
|
|
||||||
this.flashMapManager.setFlashMapTimeout(0);
|
this.flashMapManager.setFlashMapTimeout(0);
|
||||||
this.flashMapManager.requestCompleted(this.request);
|
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||||
|
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
|
|
||||||
|
|
@ -252,49 +256,49 @@ public class DefaultFlashMapManagerTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void decodeTargetPath() throws InterruptedException {
|
public void decodeTargetPath() throws InterruptedException {
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(this.request);
|
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(this.request);
|
||||||
flashMap.put("key", "value");
|
flashMap.put("key", "value");
|
||||||
|
|
||||||
flashMap.setTargetRequestPath("/once%20upon%20a%20time");
|
flashMap.setTargetRequestPath("/once%20upon%20a%20time");
|
||||||
this.flashMapManager.requestCompleted(this.request);
|
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||||
|
|
||||||
assertEquals("/once upon a time", flashMap.getTargetRequestPath());
|
assertEquals("/once upon a time", flashMap.getTargetRequestPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void normalizeTargetPath() throws InterruptedException {
|
public void normalizeTargetPath() throws InterruptedException {
|
||||||
this.flashMapManager.requestStarted(this.request);
|
this.flashMapManager.requestStarted(this.request, this.response);
|
||||||
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(this.request);
|
FlashMap flashMap = RequestContextUtils.getOutputFlashMap(this.request);
|
||||||
flashMap.put("key", "value");
|
flashMap.put("key", "value");
|
||||||
|
|
||||||
flashMap.setTargetRequestPath(".");
|
flashMap.setTargetRequestPath(".");
|
||||||
this.request.setRequestURI("/once/upon/a/time");
|
this.request.setRequestURI("/once/upon/a/time");
|
||||||
this.flashMapManager.requestCompleted(this.request);
|
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||||
|
|
||||||
assertEquals("/once/upon/a", flashMap.getTargetRequestPath());
|
assertEquals("/once/upon/a", flashMap.getTargetRequestPath());
|
||||||
|
|
||||||
flashMap.setTargetRequestPath("./");
|
flashMap.setTargetRequestPath("./");
|
||||||
this.request.setRequestURI("/once/upon/a/time");
|
this.request.setRequestURI("/once/upon/a/time");
|
||||||
this.flashMapManager.requestCompleted(this.request);
|
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||||
|
|
||||||
assertEquals("/once/upon/a/", flashMap.getTargetRequestPath());
|
assertEquals("/once/upon/a/", flashMap.getTargetRequestPath());
|
||||||
|
|
||||||
flashMap.setTargetRequestPath("..");
|
flashMap.setTargetRequestPath("..");
|
||||||
this.request.setRequestURI("/once/upon/a/time");
|
this.request.setRequestURI("/once/upon/a/time");
|
||||||
this.flashMapManager.requestCompleted(this.request);
|
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||||
|
|
||||||
assertEquals("/once/upon", flashMap.getTargetRequestPath());
|
assertEquals("/once/upon", flashMap.getTargetRequestPath());
|
||||||
|
|
||||||
flashMap.setTargetRequestPath("../");
|
flashMap.setTargetRequestPath("../");
|
||||||
this.request.setRequestURI("/once/upon/a/time");
|
this.request.setRequestURI("/once/upon/a/time");
|
||||||
this.flashMapManager.requestCompleted(this.request);
|
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||||
|
|
||||||
assertEquals("/once/upon/", flashMap.getTargetRequestPath());
|
assertEquals("/once/upon/", flashMap.getTargetRequestPath());
|
||||||
|
|
||||||
flashMap.setTargetRequestPath("../../only");
|
flashMap.setTargetRequestPath("../../only");
|
||||||
this.request.setRequestURI("/once/upon/a/time");
|
this.request.setRequestURI("/once/upon/a/time");
|
||||||
this.flashMapManager.requestCompleted(this.request);
|
this.flashMapManager.requestCompleted(this.request, this.response);
|
||||||
|
|
||||||
assertEquals("/once/only", flashMap.getTargetRequestPath());
|
assertEquals("/once/only", flashMap.getTargetRequestPath());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2010 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -24,6 +24,7 @@ package org.springframework.http;
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @see HttpStatus.Series
|
* @see HttpStatus.Series
|
||||||
* @see <a href="http://www.iana.org/assignments/http-status-codes">HTTP Status Code Registry</a>
|
* @see <a href="http://www.iana.org/assignments/http-status-codes">HTTP Status Code Registry</a>
|
||||||
|
* @see <a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes">List of HTTP status codes - Wikipedia</a>
|
||||||
*/
|
*/
|
||||||
public enum HttpStatus {
|
public enum HttpStatus {
|
||||||
|
|
||||||
|
|
@ -44,6 +45,12 @@ public enum HttpStatus {
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2518#section-10.1">WebDAV</a>
|
* @see <a href="http://tools.ietf.org/html/rfc2518#section-10.1">WebDAV</a>
|
||||||
*/
|
*/
|
||||||
PROCESSING(102, "Processing"),
|
PROCESSING(102, "Processing"),
|
||||||
|
/**
|
||||||
|
* {@code 103 Checkpoint}.
|
||||||
|
* @see <a href="http://code.google.com/p/gears/wiki/ResumableHttpRequestsProposal">A proposal for supporting
|
||||||
|
* resumable POST/PUT HTTP requests in HTTP/1.0</a>
|
||||||
|
*/
|
||||||
|
CHECKPOINT(103, "Checkpoint"),
|
||||||
|
|
||||||
// 2xx Success
|
// 2xx Success
|
||||||
|
|
||||||
|
|
@ -140,6 +147,12 @@ public enum HttpStatus {
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.3.8">HTTP/1.1</a>
|
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.3.8">HTTP/1.1</a>
|
||||||
*/
|
*/
|
||||||
TEMPORARY_REDIRECT(307, "Temporary Redirect"),
|
TEMPORARY_REDIRECT(307, "Temporary Redirect"),
|
||||||
|
/**
|
||||||
|
* {@code 308 Resume Incomplete}.
|
||||||
|
* @see <a href="http://code.google.com/p/gears/wiki/ResumableHttpRequestsProposal">A proposal for supporting
|
||||||
|
* resumable POST/PUT HTTP requests in HTTP/1.0</a>
|
||||||
|
*/
|
||||||
|
RESUME_INCOMPLETE(308, "Resume Incomplete"),
|
||||||
|
|
||||||
// --- 4xx Client Error ---
|
// --- 4xx Client Error ---
|
||||||
|
|
||||||
|
|
@ -187,7 +200,7 @@ public enum HttpStatus {
|
||||||
* {@code 408 Request Timeout}.
|
* {@code 408 Request Timeout}.
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.4.9">HTTP/1.1</a>
|
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.4.9">HTTP/1.1</a>
|
||||||
*/
|
*/
|
||||||
REQUEST_TIMEOUT(408, "Request Time-out"),
|
REQUEST_TIMEOUT(408, "Request Timeout"),
|
||||||
/**
|
/**
|
||||||
* {@code 409 Conflict}.
|
* {@code 409 Conflict}.
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.4.10">HTTP/1.1</a>
|
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.4.10">HTTP/1.1</a>
|
||||||
|
|
@ -217,7 +230,7 @@ public enum HttpStatus {
|
||||||
* {@code 414 Request-URI Too Long}.
|
* {@code 414 Request-URI Too Long}.
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.4.15">HTTP/1.1</a>
|
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.4.15">HTTP/1.1</a>
|
||||||
*/
|
*/
|
||||||
REQUEST_URI_TOO_LONG(414, "Request-URI Too Large"),
|
REQUEST_URI_TOO_LONG(414, "Request-URI Too Long"),
|
||||||
/**
|
/**
|
||||||
* {@code 415 Unsupported Media Type}.
|
* {@code 415 Unsupported Media Type}.
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.4.16">HTTP/1.1</a>
|
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.4.16">HTTP/1.1</a>
|
||||||
|
|
@ -233,6 +246,11 @@ public enum HttpStatus {
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.4.18">HTTP/1.1</a>
|
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.4.18">HTTP/1.1</a>
|
||||||
*/
|
*/
|
||||||
EXPECTATION_FAILED(417, "Expectation Failed"),
|
EXPECTATION_FAILED(417, "Expectation Failed"),
|
||||||
|
/**
|
||||||
|
* {@code 418 I'm a teapot}.
|
||||||
|
* @see <a href="http://tools.ietf.org/html/rfc2324#section-2.3.2">HTCPCP/1.0</a>
|
||||||
|
*/
|
||||||
|
I_AM_A_TEAPOT(418, "I'm a teapot"),
|
||||||
/**
|
/**
|
||||||
* {@code 419 Insufficient Space on Resource}.
|
* {@code 419 Insufficient Space on Resource}.
|
||||||
* @see <a href="http://tools.ietf.org/html/draft-ietf-webdav-protocol-05#section-10.4">WebDAV Draft</a>
|
* @see <a href="http://tools.ietf.org/html/draft-ietf-webdav-protocol-05#section-10.4">WebDAV Draft</a>
|
||||||
|
|
@ -268,6 +286,24 @@ public enum HttpStatus {
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2817#section-6">Upgrading to TLS Within HTTP/1.1</a>
|
* @see <a href="http://tools.ietf.org/html/rfc2817#section-6">Upgrading to TLS Within HTTP/1.1</a>
|
||||||
*/
|
*/
|
||||||
UPGRADE_REQUIRED(426, "Upgrade Required"),
|
UPGRADE_REQUIRED(426, "Upgrade Required"),
|
||||||
|
/**
|
||||||
|
* {@code 428 Precondition Required}.
|
||||||
|
* @see <a href="http://tools.ietf.org/html/draft-nottingham-http-new-status-02#section-3">Additional HTTP Status
|
||||||
|
* Codes</a>
|
||||||
|
*/
|
||||||
|
PRECONDITION_REQUIRED(428, "Precondition Required"),
|
||||||
|
/**
|
||||||
|
* {@code 429 Too Many Requests}.
|
||||||
|
* @see <a href="http://tools.ietf.org/html/draft-nottingham-http-new-status-02#section-4">Additional HTTP Status
|
||||||
|
* Codes</a>
|
||||||
|
*/
|
||||||
|
TOO_MANY_REQUESTS(429, "Too Many Requests"),
|
||||||
|
/**
|
||||||
|
* {@code 431 Request Header Fields Too Large}.
|
||||||
|
* @see <a href="http://tools.ietf.org/html/draft-nottingham-http-new-status-02#section-5">Additional HTTP Status
|
||||||
|
* Codes</a>
|
||||||
|
*/
|
||||||
|
REQUEST_HEADER_FIELDS_TOO_LARGE(431, "Request Header Fields Too Large"),
|
||||||
|
|
||||||
// --- 5xx Server Error ---
|
// --- 5xx Server Error ---
|
||||||
|
|
||||||
|
|
@ -295,7 +331,7 @@ public enum HttpStatus {
|
||||||
* {@code 504 Gateway Timeout}.
|
* {@code 504 Gateway Timeout}.
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.5.5">HTTP/1.1</a>
|
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.5.5">HTTP/1.1</a>
|
||||||
*/
|
*/
|
||||||
GATEWAY_TIMEOUT(504, "Gateway Time-out"),
|
GATEWAY_TIMEOUT(504, "Gateway Timeout"),
|
||||||
/**
|
/**
|
||||||
* {@code 505 HTTP Version Not Supported}.
|
* {@code 505 HTTP Version Not Supported}.
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.5.6">HTTP/1.1</a>
|
* @see <a href="http://tools.ietf.org/html/rfc2616#section-10.5.6">HTTP/1.1</a>
|
||||||
|
|
@ -316,11 +352,22 @@ public enum HttpStatus {
|
||||||
* @see <a href="http://tools.ietf.org/html/draft-ietf-webdav-bind-27#section-7.2">WebDAV Binding Extensions</a>
|
* @see <a href="http://tools.ietf.org/html/draft-ietf-webdav-bind-27#section-7.2">WebDAV Binding Extensions</a>
|
||||||
*/
|
*/
|
||||||
LOOP_DETECTED(508, "Loop Detected"),
|
LOOP_DETECTED(508, "Loop Detected"),
|
||||||
|
/**
|
||||||
|
* {@code 509 Bandwidth Limit Exceeded}
|
||||||
|
*/
|
||||||
|
BANDWIDTH_LIMIT_EXCEEDED(509, "Bandwidth Limit Exceeded"),
|
||||||
/**
|
/**
|
||||||
* {@code 510 Not Extended}
|
* {@code 510 Not Extended}
|
||||||
* @see <a href="http://tools.ietf.org/html/rfc2774#section-7">HTTP Extension Framework</a>
|
* @see <a href="http://tools.ietf.org/html/rfc2774#section-7">HTTP Extension Framework</a>
|
||||||
*/
|
*/
|
||||||
NOT_EXTENDED(510, "Not Extended");
|
NOT_EXTENDED(510, "Not Extended"),
|
||||||
|
/**
|
||||||
|
* {@code 511 Network Authentication Required}.
|
||||||
|
* @see <a href="http://tools.ietf.org/html/draft-nottingham-http-new-status-02#section-6">Additional HTTP Status
|
||||||
|
* Codes</a>
|
||||||
|
*/
|
||||||
|
NETWORK_AUTHENTICATION_REQUIRED(511, "Network Authentication Required");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private final int value;
|
private final int value;
|
||||||
|
|
|
||||||
|
|
@ -331,7 +331,7 @@ public class MediaType implements Comparable<MediaType> {
|
||||||
String attribute = entry.getKey();
|
String attribute = entry.getKey();
|
||||||
String value = entry.getValue();
|
String value = entry.getValue();
|
||||||
checkParameters(attribute, value);
|
checkParameters(attribute, value);
|
||||||
m.put(attribute, unquote(value));
|
m.put(attribute, value);
|
||||||
}
|
}
|
||||||
this.parameters = Collections.unmodifiableMap(m);
|
this.parameters = Collections.unmodifiableMap(m);
|
||||||
}
|
}
|
||||||
|
|
@ -428,7 +428,7 @@ public class MediaType implements Comparable<MediaType> {
|
||||||
*/
|
*/
|
||||||
public Charset getCharSet() {
|
public Charset getCharSet() {
|
||||||
String charSet = getParameter(PARAM_CHARSET);
|
String charSet = getParameter(PARAM_CHARSET);
|
||||||
return (charSet != null ? Charset.forName(charSet) : null);
|
return (charSet != null ? Charset.forName(unquote(charSet)) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -438,7 +438,7 @@ public class MediaType implements Comparable<MediaType> {
|
||||||
*/
|
*/
|
||||||
public double getQualityValue() {
|
public double getQualityValue() {
|
||||||
String qualityFactory = getParameter(PARAM_QUALITY_FACTOR);
|
String qualityFactory = getParameter(PARAM_QUALITY_FACTOR);
|
||||||
return (qualityFactory != null ? Double.parseDouble(qualityFactory) : 1D);
|
return (qualityFactory != null ? Double.parseDouble(unquote(qualityFactory)) : 1D);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* 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.http.client;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract base for {@link ClientHttpResponse}.
|
||||||
|
*
|
||||||
|
* @author Arjen Poutsma
|
||||||
|
* @since 3.1.1
|
||||||
|
*/
|
||||||
|
public abstract class AbstractClientHttpResponse implements ClientHttpResponse {
|
||||||
|
|
||||||
|
public HttpStatus getStatusCode() throws IOException {
|
||||||
|
return HttpStatus.valueOf(getRawStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -47,6 +47,10 @@ final class BufferingClientHttpResponseWrapper implements ClientHttpResponse {
|
||||||
return this.response.getStatusCode();
|
return this.response.getStatusCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getRawStatusCode() throws IOException {
|
||||||
|
return this.response.getRawStatusCode();
|
||||||
|
}
|
||||||
|
|
||||||
public String getStatusText() throws IOException {
|
public String getStatusText() throws IOException {
|
||||||
return this.response.getStatusText();
|
return this.response.getStatusText();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2009 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -39,6 +39,13 @@ public interface ClientHttpResponse extends HttpInputMessage {
|
||||||
*/
|
*/
|
||||||
HttpStatus getStatusCode() throws IOException;
|
HttpStatus getStatusCode() throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the HTTP status code of the response as integer
|
||||||
|
* @return the HTTP status as an integer
|
||||||
|
* @throws IOException in case of I/O errors
|
||||||
|
*/
|
||||||
|
int getRawStatusCode() throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the HTTP status text of the response.
|
* Return the HTTP status text of the response.
|
||||||
* @return the HTTP status text
|
* @return the HTTP status text
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -23,7 +23,6 @@ import org.apache.commons.httpclient.Header;
|
||||||
import org.apache.commons.httpclient.HttpMethod;
|
import org.apache.commons.httpclient.HttpMethod;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link org.springframework.http.client.ClientHttpResponse} implementation that uses
|
* {@link org.springframework.http.client.ClientHttpResponse} implementation that uses
|
||||||
|
|
@ -37,7 +36,7 @@ import org.springframework.http.HttpStatus;
|
||||||
* @deprecated In favor of {@link HttpComponentsClientHttpResponse}
|
* @deprecated In favor of {@link HttpComponentsClientHttpResponse}
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
final class CommonsClientHttpResponse implements ClientHttpResponse {
|
final class CommonsClientHttpResponse extends AbstractClientHttpResponse {
|
||||||
|
|
||||||
private final HttpMethod httpMethod;
|
private final HttpMethod httpMethod;
|
||||||
|
|
||||||
|
|
@ -49,8 +48,8 @@ final class CommonsClientHttpResponse implements ClientHttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public HttpStatus getStatusCode() {
|
public int getRawStatusCode() {
|
||||||
return HttpStatus.valueOf(this.httpMethod.getStatusCode());
|
return this.httpMethod.getStatusCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStatusText() {
|
public String getStatusText() {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -25,7 +25,6 @@ import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link org.springframework.http.client.ClientHttpResponse} implementation that uses
|
* {@link org.springframework.http.client.ClientHttpResponse} implementation that uses
|
||||||
|
|
@ -38,20 +37,20 @@ import org.springframework.http.HttpStatus;
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
* @see HttpComponentsClientHttpRequest#execute()
|
* @see HttpComponentsClientHttpRequest#execute()
|
||||||
*/
|
*/
|
||||||
final class HttpComponentsClientHttpResponse implements ClientHttpResponse {
|
final class HttpComponentsClientHttpResponse extends AbstractClientHttpResponse {
|
||||||
|
|
||||||
private final HttpResponse httpResponse;
|
private final HttpResponse httpResponse;
|
||||||
|
|
||||||
private HttpHeaders headers;
|
private HttpHeaders headers;
|
||||||
|
|
||||||
|
|
||||||
public HttpComponentsClientHttpResponse(HttpResponse httpResponse) {
|
HttpComponentsClientHttpResponse(HttpResponse httpResponse) {
|
||||||
this.httpResponse = httpResponse;
|
this.httpResponse = httpResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public HttpStatus getStatusCode() throws IOException {
|
public int getRawStatusCode() throws IOException {
|
||||||
return HttpStatus.valueOf(this.httpResponse.getStatusLine().getStatusCode());
|
return this.httpResponse.getStatusLine().getStatusCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStatusText() throws IOException {
|
public String getStatusText() throws IOException {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -21,7 +21,6 @@ import java.io.InputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -32,7 +31,7 @@ import org.springframework.util.StringUtils;
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
final class SimpleClientHttpResponse implements ClientHttpResponse {
|
final class SimpleClientHttpResponse extends AbstractClientHttpResponse {
|
||||||
|
|
||||||
private final HttpURLConnection connection;
|
private final HttpURLConnection connection;
|
||||||
|
|
||||||
|
|
@ -44,8 +43,8 @@ final class SimpleClientHttpResponse implements ClientHttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public HttpStatus getStatusCode() throws IOException {
|
public int getRawStatusCode() throws IOException {
|
||||||
return HttpStatus.valueOf(this.connection.getResponseCode());
|
return this.connection.getResponseCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStatusText() throws IOException {
|
public String getStatusText() throws IOException {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2010 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -407,8 +407,14 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
|
||||||
*/
|
*/
|
||||||
protected Object getPortStub(Service service, QName portQName) {
|
protected Object getPortStub(Service service, QName portQName) {
|
||||||
if (this.webServiceFeatures != null) {
|
if (this.webServiceFeatures != null) {
|
||||||
|
try {
|
||||||
return new FeaturePortProvider().getPortStub(service, portQName, this.webServiceFeatures);
|
return new FeaturePortProvider().getPortStub(service, portQName, this.webServiceFeatures);
|
||||||
}
|
}
|
||||||
|
catch (LinkageError ex) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Specifying the 'webServiceFeatures' property requires JAX-WS 2.1 or higher at runtime", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
return (portQName != null ? service.getPort(portQName, getServiceInterface()) :
|
return (portQName != null ? service.getPort(portQName, getServiceInterface()) :
|
||||||
service.getPort(getServiceInterface()));
|
service.getPort(getServiceInterface()));
|
||||||
|
|
@ -527,6 +533,7 @@ public class JaxWsPortClientInterceptor extends LocalJaxWsServiceFactory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inner class in order to avoid a hard-coded JAX-WS 2.1 dependency.
|
* Inner class in order to avoid a hard-coded JAX-WS 2.1 dependency.
|
||||||
* JAX-WS 2.0, as used in Java EE 5, didn't have WebServiceFeatures yet...
|
* JAX-WS 2.0, as used in Java EE 5, didn't have WebServiceFeatures yet...
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -71,10 +71,11 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
|
||||||
this.expressionContext = (beanFactory != null) ? new BeanExpressionContext(beanFactory, new RequestScope()) : null;
|
this.expressionContext = (beanFactory != null) ? new BeanExpressionContext(beanFactory, new RequestScope()) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Object resolveArgument(MethodParameter parameter,
|
public final Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest,
|
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
Class<?> paramType = parameter.getParameterType();
|
Class<?> paramType = parameter.getParameterType();
|
||||||
|
|
||||||
NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
|
NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -91,10 +91,11 @@ public abstract class AbstractWebArgumentResolverAdapter implements HandlerMetho
|
||||||
* @exception IllegalStateException if the resolved value is not assignable
|
* @exception IllegalStateException if the resolved value is not assignable
|
||||||
* to the method parameter.
|
* to the method parameter.
|
||||||
*/
|
*/
|
||||||
public Object resolveArgument(MethodParameter parameter,
|
public Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest,
|
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
Class<?> paramType = parameter.getParameterType();
|
Class<?> paramType = parameter.getParameterType();
|
||||||
Object result = this.adaptee.resolveArgument(parameter, webRequest);
|
Object result = this.adaptee.resolveArgument(parameter, webRequest);
|
||||||
if (result == WebArgumentResolver.UNRESOLVED || !ClassUtils.isAssignableValue(paramType, result)) {
|
if (result == WebArgumentResolver.UNRESOLVED || !ClassUtils.isAssignableValue(paramType, result)) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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,10 +45,11 @@ public class ErrorsMethodArgumentResolver implements HandlerMethodArgumentResolv
|
||||||
return Errors.class.isAssignableFrom(paramType);
|
return Errors.class.isAssignableFrom(paramType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object resolveArgument(MethodParameter parameter,
|
public Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest,
|
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
ModelMap model = mavContainer.getModel();
|
ModelMap model = mavContainer.getModel();
|
||||||
if (model.size() > 0) {
|
if (model.size() > 0) {
|
||||||
int lastIndex = model.size()-1;
|
int lastIndex = model.size()-1;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -42,10 +42,11 @@ public class MapMethodProcessor implements HandlerMethodArgumentResolver, Handle
|
||||||
return Map.class.isAssignableFrom(parameter.getParameterType());
|
return Map.class.isAssignableFrom(parameter.getParameterType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object resolveArgument(MethodParameter parameter,
|
public Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest,
|
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
return mavContainer.getModel();
|
return mavContainer.getModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,10 +55,11 @@ public class MapMethodProcessor implements HandlerMethodArgumentResolver, Handle
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public void handleReturnValue(Object returnValue,
|
public void handleReturnValue(
|
||||||
MethodParameter returnType,
|
Object returnValue, MethodParameter returnType,
|
||||||
ModelAndViewContainer mavContainer,
|
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
|
||||||
NativeWebRequest webRequest) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
if (returnValue == null) {
|
if (returnValue == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -93,10 +93,11 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
|
||||||
* and the next method parameter is not of type {@link Errors}.
|
* and the next method parameter is not of type {@link Errors}.
|
||||||
* @throws Exception if WebDataBinder initialization fails.
|
* @throws Exception if WebDataBinder initialization fails.
|
||||||
*/
|
*/
|
||||||
public final Object resolveArgument(MethodParameter parameter,
|
public final Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest request,
|
NativeWebRequest request, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
String name = ModelFactory.getNameForParameter(parameter);
|
String name = ModelFactory.getNameForParameter(parameter);
|
||||||
Object target = (mavContainer.containsAttribute(name)) ?
|
Object target = (mavContainer.containsAttribute(name)) ?
|
||||||
mavContainer.getModel().get(name) : createAttribute(name, parameter, binderFactory, request);
|
mavContainer.getModel().get(name) : createAttribute(name, parameter, binderFactory, request);
|
||||||
|
|
@ -190,10 +191,11 @@ public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResol
|
||||||
/**
|
/**
|
||||||
* Add non-null return values to the {@link ModelAndViewContainer}.
|
* Add non-null return values to the {@link ModelAndViewContainer}.
|
||||||
*/
|
*/
|
||||||
public void handleReturnValue(Object returnValue,
|
public void handleReturnValue(
|
||||||
MethodParameter returnType,
|
Object returnValue, MethodParameter returnType,
|
||||||
ModelAndViewContainer mavContainer,
|
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
|
||||||
NativeWebRequest webRequest) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
if (returnValue != null) {
|
if (returnValue != null) {
|
||||||
String name = ModelFactory.getNameForReturnValue(returnValue, returnType);
|
String name = ModelFactory.getNameForReturnValue(returnValue, returnType);
|
||||||
mavContainer.addAttribute(name, returnValue);
|
mavContainer.addAttribute(name, returnValue);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -41,10 +41,11 @@ public class ModelMethodProcessor implements HandlerMethodArgumentResolver, Hand
|
||||||
return Model.class.isAssignableFrom(parameter.getParameterType());
|
return Model.class.isAssignableFrom(parameter.getParameterType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object resolveArgument(MethodParameter parameter,
|
public Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest,
|
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
return mavContainer.getModel();
|
return mavContainer.getModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,10 +53,11 @@ public class ModelMethodProcessor implements HandlerMethodArgumentResolver, Hand
|
||||||
return Model.class.isAssignableFrom(returnType.getParameterType());
|
return Model.class.isAssignableFrom(returnType.getParameterType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleReturnValue(Object returnValue,
|
public void handleReturnValue(
|
||||||
MethodParameter returnType,
|
Object returnValue, MethodParameter returnType,
|
||||||
ModelAndViewContainer mavContainer,
|
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
|
||||||
NativeWebRequest webRequest) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
if (returnValue == null) {
|
if (returnValue == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -50,10 +50,11 @@ public class RequestHeaderMapMethodArgumentResolver implements HandlerMethodArgu
|
||||||
&& Map.class.isAssignableFrom(parameter.getParameterType());
|
&& Map.class.isAssignableFrom(parameter.getParameterType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object resolveArgument(MethodParameter parameter,
|
public Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest,
|
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
Class<?> paramType = parameter.getParameterType();
|
Class<?> paramType = parameter.getParameterType();
|
||||||
|
|
||||||
if (MultiValueMap.class.isAssignableFrom(paramType)) {
|
if (MultiValueMap.class.isAssignableFrom(paramType)) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -55,10 +55,11 @@ public class RequestParamMapMethodArgumentResolver implements HandlerMethodArgum
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object resolveArgument(MethodParameter parameter,
|
public Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest,
|
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
Class<?> paramType = parameter.getParameterType();
|
Class<?> paramType = parameter.getParameterType();
|
||||||
|
|
||||||
Map<String, String[]> parameterMap = webRequest.getParameterMap();
|
Map<String, String[]> parameterMap = webRequest.getParameterMap();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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,10 +36,11 @@ public class SessionStatusMethodArgumentResolver implements HandlerMethodArgumen
|
||||||
return SessionStatus.class.equals(parameter.getParameterType());
|
return SessionStatus.class.equals(parameter.getParameterType());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object resolveArgument(MethodParameter parameter,
|
public Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest,
|
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
return mavContainer.getSessionStatus();
|
return mavContainer.getSessionStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -65,10 +65,11 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu
|
||||||
* Iterate over registered {@link HandlerMethodArgumentResolver}s and invoke the one that supports it.
|
* Iterate over registered {@link HandlerMethodArgumentResolver}s and invoke the one that supports it.
|
||||||
* @exception IllegalStateException if no suitable {@link HandlerMethodArgumentResolver} is found.
|
* @exception IllegalStateException if no suitable {@link HandlerMethodArgumentResolver} is found.
|
||||||
*/
|
*/
|
||||||
public Object resolveArgument(MethodParameter parameter,
|
public Object resolveArgument(
|
||||||
ModelAndViewContainer mavContainer,
|
MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||||
NativeWebRequest webRequest,
|
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
|
||||||
WebDataBinderFactory binderFactory) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
|
HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
|
||||||
Assert.notNull(resolver, "Unknown parameter type [" + parameter.getParameterType().getName() + "]");
|
Assert.notNull(resolver, "Unknown parameter type [" + parameter.getParameterType().getName() + "]");
|
||||||
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
|
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -64,10 +64,11 @@ public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodRe
|
||||||
* Iterate over registered {@link HandlerMethodReturnValueHandler}s and invoke the one that supports it.
|
* Iterate over registered {@link HandlerMethodReturnValueHandler}s and invoke the one that supports it.
|
||||||
* @exception IllegalStateException if no suitable {@link HandlerMethodReturnValueHandler} is found.
|
* @exception IllegalStateException if no suitable {@link HandlerMethodReturnValueHandler} is found.
|
||||||
*/
|
*/
|
||||||
public void handleReturnValue(Object returnValue,
|
public void handleReturnValue(
|
||||||
MethodParameter returnType,
|
Object returnValue, MethodParameter returnType,
|
||||||
ModelAndViewContainer mavContainer,
|
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
|
||||||
NativeWebRequest webRequest) throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType);
|
HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType);
|
||||||
Assert.notNull(handler, "Unknown return value type [" + returnType.getParameterType().getName() + "]");
|
Assert.notNull(handler, "Unknown return value type [" + returnType.getParameterType().getName() + "]");
|
||||||
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
|
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -135,9 +135,10 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||||
/**
|
/**
|
||||||
* Get the method argument values for the current request.
|
* Get the method argument values for the current request.
|
||||||
*/
|
*/
|
||||||
private Object[] getMethodArgumentValues(NativeWebRequest request,
|
private Object[] getMethodArgumentValues(
|
||||||
ModelAndViewContainer mavContainer,
|
NativeWebRequest request, ModelAndViewContainer mavContainer,
|
||||||
Object... providedArgs) throws Exception {
|
Object... providedArgs) throws Exception {
|
||||||
|
|
||||||
MethodParameter[] parameters = getMethodParameters();
|
MethodParameter[] parameters = getMethodParameters();
|
||||||
Object[] args = new Object[parameters.length];
|
Object[] args = new Object[parameters.length];
|
||||||
for (int i = 0; i < parameters.length; i++) {
|
for (int i = 0; i < parameters.length; i++) {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ package org.springframework.web.util;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
|
@ -38,21 +40,68 @@ import org.springframework.util.Assert;
|
||||||
*/
|
*/
|
||||||
public abstract class UriUtils {
|
public abstract class UriUtils {
|
||||||
|
|
||||||
|
private static final String SCHEME_PATTERN = "([^:/?#]+):";
|
||||||
|
|
||||||
|
private static final String HTTP_PATTERN = "(http|https):";
|
||||||
|
|
||||||
|
private static final String USERINFO_PATTERN = "([^@/]*)";
|
||||||
|
|
||||||
|
private static final String HOST_PATTERN = "([^/?#:]*)";
|
||||||
|
|
||||||
|
private static final String PORT_PATTERN = "(\\d*)";
|
||||||
|
|
||||||
|
private static final String PATH_PATTERN = "([^?#]*)";
|
||||||
|
|
||||||
|
private static final String QUERY_PATTERN = "([^#]*)";
|
||||||
|
|
||||||
|
private static final String LAST_PATTERN = "(.*)";
|
||||||
|
|
||||||
|
// Regex patterns that matches URIs. See RFC 3986, appendix B
|
||||||
|
private static final Pattern URI_PATTERN = Pattern.compile(
|
||||||
|
"^(" + SCHEME_PATTERN + ")?" + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN +
|
||||||
|
")?" + ")?" + PATH_PATTERN + "(\\?" + QUERY_PATTERN + ")?" + "(#" + LAST_PATTERN + ")?");
|
||||||
|
|
||||||
|
private static final Pattern HTTP_URL_PATTERN = Pattern.compile(
|
||||||
|
"^" + HTTP_PATTERN + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN + ")?" + ")?" +
|
||||||
|
PATH_PATTERN + "(\\?" + LAST_PATTERN + ")?");
|
||||||
// encoding
|
// encoding
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes the given source URI into an encoded String. All various URI components are
|
* Encodes the given source URI into an encoded String. All various URI components are
|
||||||
* encoded according to their respective valid character sets.
|
* encoded according to their respective valid character sets.
|
||||||
|
* <p><strong>Note</strong> that this method does not attempt to encode "=" and "&"
|
||||||
|
* characters in query parameter names and query parameter values because they cannot
|
||||||
|
* be parsed in a reliable way. Instead use:
|
||||||
|
* <pre>
|
||||||
|
* UriComponents uriComponents = UriComponentsBuilder.fromUri("/path?name={value}").buildAndExpand("a=b");
|
||||||
|
* String encodedUri = uriComponents.encode().toUriString();
|
||||||
|
* </pre>
|
||||||
* @param uri the URI to be encoded
|
* @param uri the URI to be encoded
|
||||||
* @param encoding the character encoding to encode to
|
* @param encoding the character encoding to encode to
|
||||||
* @return the encoded URI
|
* @return the encoded URI
|
||||||
* @throws IllegalArgumentException when the given uri parameter is not a valid URI
|
* @throws IllegalArgumentException when the given uri parameter is not a valid URI
|
||||||
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
|
||||||
|
* @deprecated in favor of {@link UriComponentsBuilder}; see note about query param encoding
|
||||||
*/
|
*/
|
||||||
public static String encodeUri(String uri, String encoding) throws UnsupportedEncodingException {
|
public static String encodeUri(String uri, String encoding) throws UnsupportedEncodingException {
|
||||||
UriComponents uriComponents = UriComponentsBuilder.fromUriString(uri).build();
|
Assert.notNull(uri, "'uri' must not be null");
|
||||||
UriComponents encoded = uriComponents.encode(encoding);
|
Assert.hasLength(encoding, "'encoding' must not be empty");
|
||||||
return encoded.toUriString();
|
Matcher m = URI_PATTERN.matcher(uri);
|
||||||
|
if (m.matches()) {
|
||||||
|
String scheme = m.group(2);
|
||||||
|
String authority = m.group(3);
|
||||||
|
String userinfo = m.group(5);
|
||||||
|
String host = m.group(6);
|
||||||
|
String port = m.group(8);
|
||||||
|
String path = m.group(9);
|
||||||
|
String query = m.group(11);
|
||||||
|
String fragment = m.group(13);
|
||||||
|
|
||||||
|
return encodeUriComponents(scheme, authority, userinfo, host, port, path, query, fragment, encoding);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException("[" + uri + "] is not a valid URI");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -60,16 +109,38 @@ public abstract class UriUtils {
|
||||||
* encoded according to their respective valid character sets.
|
* encoded according to their respective valid character sets.
|
||||||
* <p><strong>Note</strong> that this method does not support fragments ({@code #}),
|
* <p><strong>Note</strong> that this method does not support fragments ({@code #}),
|
||||||
* as these are not supposed to be sent to the server, but retained by the client.
|
* as these are not supposed to be sent to the server, but retained by the client.
|
||||||
|
* <p><strong>Note</strong> that this method does not attempt to encode "=" and "&"
|
||||||
|
* characters in query parameter names and query parameter values because they cannot
|
||||||
|
* be parsed in a reliable way. Instead use:
|
||||||
|
* <pre>
|
||||||
|
* UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl("/path?name={value}").buildAndExpand("a=b");
|
||||||
|
* String encodedUri = uriComponents.encode().toUriString();
|
||||||
|
* </pre>
|
||||||
* @param httpUrl the HTTP URL to be encoded
|
* @param httpUrl the HTTP URL to be encoded
|
||||||
* @param encoding the character encoding to encode to
|
* @param encoding the character encoding to encode to
|
||||||
* @return the encoded URL
|
* @return the encoded URL
|
||||||
* @throws IllegalArgumentException when the given uri parameter is not a valid URI
|
* @throws IllegalArgumentException when the given uri parameter is not a valid URI
|
||||||
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
|
||||||
|
* @deprecated in favor of {@link UriComponentsBuilder}; see note about query param encoding
|
||||||
*/
|
*/
|
||||||
public static String encodeHttpUrl(String httpUrl, String encoding) throws UnsupportedEncodingException {
|
public static String encodeHttpUrl(String httpUrl, String encoding) throws UnsupportedEncodingException {
|
||||||
UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(httpUrl).build();
|
Assert.notNull(httpUrl, "'httpUrl' must not be null");
|
||||||
UriComponents encoded = uriComponents.encode(encoding);
|
Assert.hasLength(encoding, "'encoding' must not be empty");
|
||||||
return encoded.toUriString();
|
Matcher m = HTTP_URL_PATTERN.matcher(httpUrl);
|
||||||
|
if (m.matches()) {
|
||||||
|
String scheme = m.group(1);
|
||||||
|
String authority = m.group(2);
|
||||||
|
String userinfo = m.group(4);
|
||||||
|
String host = m.group(5);
|
||||||
|
String portString = m.group(7);
|
||||||
|
String path = m.group(8);
|
||||||
|
String query = m.group(10);
|
||||||
|
|
||||||
|
return encodeUriComponents(scheme, authority, userinfo, host, portString, path, query, null, encoding);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalArgumentException("[" + httpUrl + "] is not a valid HTTP URL");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -87,20 +158,48 @@ public abstract class UriUtils {
|
||||||
* @return the encoded URI
|
* @return the encoded URI
|
||||||
* @throws IllegalArgumentException when the given uri parameter is not a valid URI
|
* @throws IllegalArgumentException when the given uri parameter is not a valid URI
|
||||||
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
|
* @throws UnsupportedEncodingException when the given encoding parameter is not supported
|
||||||
|
* @deprecated in favor of {@link UriComponentsBuilder}
|
||||||
*/
|
*/
|
||||||
public static String encodeUriComponents(String scheme, String authority, String userInfo,
|
public static String encodeUriComponents(String scheme, String authority, String userInfo,
|
||||||
String host, String port, String path, String query, String fragment, String encoding)
|
String host, String port, String path, String query, String fragment, String encoding)
|
||||||
throws UnsupportedEncodingException {
|
throws UnsupportedEncodingException {
|
||||||
|
|
||||||
int portAsInt = (port != null ? Integer.parseInt(port) : -1);
|
Assert.hasLength(encoding, "'encoding' must not be empty");
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
|
if (scheme != null) {
|
||||||
builder.scheme(scheme).userInfo(userInfo).host(host).port(portAsInt);
|
sb.append(encodeScheme(scheme, encoding));
|
||||||
builder.path(path).query(query).fragment(fragment);
|
sb.append(':');
|
||||||
|
}
|
||||||
|
|
||||||
UriComponents encoded = builder.build().encode(encoding);
|
if (authority != null) {
|
||||||
|
sb.append("//");
|
||||||
|
if (userInfo != null) {
|
||||||
|
sb.append(encodeUserInfo(userInfo, encoding));
|
||||||
|
sb.append('@');
|
||||||
|
}
|
||||||
|
if (host != null) {
|
||||||
|
sb.append(encodeHost(host, encoding));
|
||||||
|
}
|
||||||
|
if (port != null) {
|
||||||
|
sb.append(':');
|
||||||
|
sb.append(encodePort(port, encoding));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return encoded.toUriString();
|
sb.append(encodePath(path, encoding));
|
||||||
|
|
||||||
|
if (query != null) {
|
||||||
|
sb.append('?');
|
||||||
|
sb.append(encodeQuery(query, encoding));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fragment != null) {
|
||||||
|
sb.append('#');
|
||||||
|
sb.append(encodeFragment(fragment, encoding));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2010 the original author or authors.
|
* Copyright 2002-2012 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,38 +16,110 @@
|
||||||
|
|
||||||
package org.springframework.http;
|
package org.springframework.http;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/** @author Arjen Poutsma */
|
/** @author Arjen Poutsma */
|
||||||
public class HttpStatusTests {
|
public class HttpStatusTests {
|
||||||
|
|
||||||
private int[] registryValues =
|
private Map<Integer, String> statusCodes = new LinkedHashMap<Integer, String>();
|
||||||
new int[]{100, 101, 102, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305,
|
|
||||||
307, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 422,
|
|
||||||
423, 424, 426, 500, 501, 502, 503, 504, 505, 506, 507, 508, 510,};
|
|
||||||
|
|
||||||
private String[] registryDescriptions =
|
@Before
|
||||||
new String[]{"CONTINUE", "SWITCHING_PROTOCOLS", "PROCESSING", "OK", "CREATED", "ACCEPTED",
|
public void createStatusCodes() {
|
||||||
"NON_AUTHORITATIVE_INFORMATION", "NO_CONTENT", "RESET_CONTENT", "PARTIAL_CONTENT", "MULTI_STATUS",
|
statusCodes.put(100, "CONTINUE");
|
||||||
"ALREADY_REPORTED", "IM_USED", "MULTIPLE_CHOICES", "MOVED_PERMANENTLY", "FOUND", "SEE_OTHER",
|
statusCodes.put(101, "SWITCHING_PROTOCOLS");
|
||||||
"NOT_MODIFIED", "USE_PROXY", "TEMPORARY_REDIRECT", "BAD_REQUEST", "UNAUTHORIZED",
|
statusCodes.put(102, "PROCESSING");
|
||||||
"PAYMENT_REQUIRED", "FORBIDDEN", "NOT_FOUND", "METHOD_NOT_ALLOWED", "NOT_ACCEPTABLE",
|
statusCodes.put(103, "CHECKPOINT");
|
||||||
"PROXY_AUTHENTICATION_REQUIRED", "REQUEST_TIMEOUT", "CONFLICT", "GONE", "LENGTH_REQUIRED",
|
|
||||||
"PRECONDITION_FAILED", "REQUEST_ENTITY_TOO_LARGE", "REQUEST_URI_TOO_LONG", "UNSUPPORTED_MEDIA_TYPE",
|
statusCodes.put(200, "OK");
|
||||||
"REQUESTED_RANGE_NOT_SATISFIABLE", "EXPECTATION_FAILED", "UNPROCESSABLE_ENTITY", "LOCKED",
|
statusCodes.put(201, "CREATED");
|
||||||
"FAILED_DEPENDENCY", "UPGRADE_REQUIRED", "INTERNAL_SERVER_ERROR", "NOT_IMPLEMENTED", "BAD_GATEWAY",
|
statusCodes.put(202, "ACCEPTED");
|
||||||
"SERVICE_UNAVAILABLE", "GATEWAY_TIMEOUT", "HTTP_VERSION_NOT_SUPPORTED", "VARIANT_ALSO_NEGOTIATES",
|
statusCodes.put(203, "NON_AUTHORITATIVE_INFORMATION");
|
||||||
"INSUFFICIENT_STORAGE", "LOOP_DETECTED", "NOT_EXTENDED",};
|
statusCodes.put(204, "NO_CONTENT");
|
||||||
|
statusCodes.put(205, "RESET_CONTENT");
|
||||||
|
statusCodes.put(206, "PARTIAL_CONTENT");
|
||||||
|
statusCodes.put(207, "MULTI_STATUS");
|
||||||
|
statusCodes.put(208, "ALREADY_REPORTED");
|
||||||
|
statusCodes.put(226, "IM_USED");
|
||||||
|
|
||||||
|
statusCodes.put(300, "MULTIPLE_CHOICES");
|
||||||
|
statusCodes.put(301, "MOVED_PERMANENTLY");
|
||||||
|
statusCodes.put(302, "FOUND");
|
||||||
|
statusCodes.put(303, "SEE_OTHER");
|
||||||
|
statusCodes.put(304, "NOT_MODIFIED");
|
||||||
|
statusCodes.put(305, "USE_PROXY");
|
||||||
|
statusCodes.put(307, "TEMPORARY_REDIRECT");
|
||||||
|
statusCodes.put(308, "RESUME_INCOMPLETE");
|
||||||
|
|
||||||
|
statusCodes.put(400, "BAD_REQUEST");
|
||||||
|
statusCodes.put(401, "UNAUTHORIZED");
|
||||||
|
statusCodes.put(402, "PAYMENT_REQUIRED");
|
||||||
|
statusCodes.put(403, "FORBIDDEN");
|
||||||
|
statusCodes.put(404, "NOT_FOUND");
|
||||||
|
statusCodes.put(405, "METHOD_NOT_ALLOWED");
|
||||||
|
statusCodes.put(406, "NOT_ACCEPTABLE");
|
||||||
|
statusCodes.put(407, "PROXY_AUTHENTICATION_REQUIRED");
|
||||||
|
statusCodes.put(408, "REQUEST_TIMEOUT");
|
||||||
|
statusCodes.put(409, "CONFLICT");
|
||||||
|
statusCodes.put(410, "GONE");
|
||||||
|
statusCodes.put(411, "LENGTH_REQUIRED");
|
||||||
|
statusCodes.put(412, "PRECONDITION_FAILED");
|
||||||
|
statusCodes.put(413, "REQUEST_ENTITY_TOO_LARGE");
|
||||||
|
statusCodes.put(414, "REQUEST_URI_TOO_LONG");
|
||||||
|
statusCodes.put(415, "UNSUPPORTED_MEDIA_TYPE");
|
||||||
|
statusCodes.put(416, "REQUESTED_RANGE_NOT_SATISFIABLE");
|
||||||
|
statusCodes.put(417, "EXPECTATION_FAILED");
|
||||||
|
statusCodes.put(418, "I_AM_A_TEAPOT");
|
||||||
|
statusCodes.put(419, "INSUFFICIENT_SPACE_ON_RESOURCE");
|
||||||
|
statusCodes.put(420, "METHOD_FAILURE");
|
||||||
|
statusCodes.put(421, "DESTINATION_LOCKED");
|
||||||
|
statusCodes.put(422, "UNPROCESSABLE_ENTITY");
|
||||||
|
statusCodes.put(423, "LOCKED");
|
||||||
|
statusCodes.put(424, "FAILED_DEPENDENCY");
|
||||||
|
statusCodes.put(426, "UPGRADE_REQUIRED");
|
||||||
|
statusCodes.put(428, "PRECONDITION_REQUIRED");
|
||||||
|
statusCodes.put(429, "TOO_MANY_REQUESTS");
|
||||||
|
statusCodes.put(431, "REQUEST_HEADER_FIELDS_TOO_LARGE");
|
||||||
|
|
||||||
|
statusCodes.put(500, "INTERNAL_SERVER_ERROR");
|
||||||
|
statusCodes.put(501, "NOT_IMPLEMENTED");
|
||||||
|
statusCodes.put(502, "BAD_GATEWAY");
|
||||||
|
statusCodes.put(503, "SERVICE_UNAVAILABLE");
|
||||||
|
statusCodes.put(504, "GATEWAY_TIMEOUT");
|
||||||
|
statusCodes.put(505, "HTTP_VERSION_NOT_SUPPORTED");
|
||||||
|
statusCodes.put(506, "VARIANT_ALSO_NEGOTIATES");
|
||||||
|
statusCodes.put(507, "INSUFFICIENT_STORAGE");
|
||||||
|
statusCodes.put(508, "LOOP_DETECTED");
|
||||||
|
statusCodes.put(509, "BANDWIDTH_LIMIT_EXCEEDED");
|
||||||
|
statusCodes.put(510, "NOT_EXTENDED");
|
||||||
|
statusCodes.put(511, "NETWORK_AUTHENTICATION_REQUIRED");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void registryValues() {
|
public void fromMapToEnum() {
|
||||||
for (int i = 0; i < registryValues.length; i++) {
|
for (Map.Entry<Integer, String> entry : statusCodes.entrySet()) {
|
||||||
HttpStatus status = HttpStatus.valueOf(registryValues[i]);
|
int value = entry.getKey();
|
||||||
assertEquals("Invalid value", registryValues[i], status.value());
|
HttpStatus status = HttpStatus.valueOf(value);
|
||||||
assertEquals("Invalid descripion", registryDescriptions[i], status.name());
|
assertEquals("Invalid value", value, status.value());
|
||||||
|
assertEquals("Invalid name for [" + value + "]", entry.getValue(), status.name());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
@Test
|
||||||
|
public void fromEnumToMap() {
|
||||||
|
|
||||||
|
for (HttpStatus status : HttpStatus.values()) {
|
||||||
|
int value = status.value();
|
||||||
|
if (value == 302) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
assertTrue("Map has no value for [" + value + "]", statusCodes.containsKey(value));
|
||||||
|
assertEquals("Invalid name for [" + value + "]", statusCodes.get(value), status.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -173,9 +173,12 @@ public class MediaTypeTests {
|
||||||
MediaType.parseMediaType("text/html; charset=foo-bar");
|
MediaType.parseMediaType("text/html; charset=foo-bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SPR-8917
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void parseMediaTypeQuotedParameterValue() {
|
public void parseMediaTypeQuotedParameterValue() {
|
||||||
MediaType.parseMediaType("audio/*;attr=\"v>alue\"");
|
MediaType mediaType = MediaType.parseMediaType("audio/*;attr=\"v>alue\"");
|
||||||
|
assertEquals("\"v>alue\"", mediaType.getParameter("attr"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 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.
|
||||||
|
|
@ -291,6 +291,10 @@ public class InterceptingClientHttpRequestFactoryTests {
|
||||||
return statusCode;
|
return statusCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getRawStatusCode() throws IOException {
|
||||||
|
return statusCode.value();
|
||||||
|
}
|
||||||
|
|
||||||
public String getStatusText() throws IOException {
|
public String getStatusText() throws IOException {
|
||||||
return statusText;
|
return statusText;
|
||||||
}
|
}
|
||||||
|
|
@ -300,7 +304,7 @@ public class InterceptingClientHttpRequestFactoryTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getBody() throws IOException {
|
public InputStream getBody() throws IOException {
|
||||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,9 @@ public class UriUtilsTests {
|
||||||
assertEquals("Invalid encoded URI", "http://example.com/query=foo@bar",
|
assertEquals("Invalid encoded URI", "http://example.com/query=foo@bar",
|
||||||
UriUtils.encodeUri("http://example.com/query=foo@bar", ENC));
|
UriUtils.encodeUri("http://example.com/query=foo@bar", ENC));
|
||||||
|
|
||||||
|
// SPR-8974
|
||||||
|
assertEquals("http://example.org?format=json&url=http://another.com?foo=bar",
|
||||||
|
UriUtils.encodeUri("http://example.org?format=json&url=http://another.com?foo=bar", ENC));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue