Browse Source
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@1666 50f2f4bb-b051-0410-bef5-90022cba6387pull/1/head
64 changed files with 63 additions and 7372 deletions
@ -1,52 +1,52 @@ |
|||||||
<?xml version="1.0" encoding="UTF-8"?> |
<?xml version="1.0" encoding="UTF-8"?> |
||||||
<classpath> |
<classpath> |
||||||
<classpathentry kind="src" path="src/main/java"/> |
<classpathentry kind="src" path="src/main/java"/> |
||||||
<classpathentry kind="src" path="src/main/resources"/> |
<classpathentry kind="src" path="src/main/resources"/> |
||||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/> |
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/> |
||||||
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/> |
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/> |
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> |
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> |
||||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.aop"/> |
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.aop"/> |
||||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.beans"/> |
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.beans"/> |
||||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.context"/> |
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.context"/> |
||||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.context.support"/> |
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.context.support"/> |
||||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.core"/> |
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.core"/> |
||||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.orm"/> |
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.jdbc"/> |
||||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.oxm"/> |
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.orm"/> |
||||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.web"/> |
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.oxm"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/com.lowagie.text/com.springsource.com.lowagie.text/2.0.8/com.springsource.com.lowagie.text-2.0.8.jar" sourcepath="/IVY_CACHE/com.lowagie.text/com.springsource.com.lowagie.text/2.0.8/com.springsource.com.lowagie.text-sources-2.0.8.jar"/> |
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.transaction"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/com.sun.syndication/com.springsource.com.sun.syndication/1.0.0/com.springsource.com.sun.syndication-1.0.0.jar" sourcepath="/IVY_CACHE/com.sun.syndication/com.springsource.com.sun.syndication/1.0.0/com.springsource.com.sun.syndication-sources-1.0.0.jar"/> |
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.web"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/javax.activation/com.springsource.javax.activation/1.1.0/com.springsource.javax.activation-1.1.0.jar" sourcepath="/IVY_CACHE/javax.activation/com.springsource.javax.activation/1.1.0/com.springsource.javax.activation-sources-1.1.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/com.lowagie.text/com.springsource.com.lowagie.text/2.0.8/com.springsource.com.lowagie.text-2.0.8.jar" sourcepath="/IVY_CACHE/com.lowagie.text/com.springsource.com.lowagie.text/2.0.8/com.springsource.com.lowagie.text-sources-2.0.8.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-1.0.0.jar" sourcepath="/IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-sources-1.0.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/com.sun.syndication/com.springsource.com.sun.syndication/1.0.0/com.springsource.com.sun.syndication-1.0.0.jar" sourcepath="/IVY_CACHE/com.sun.syndication/com.springsource.com.sun.syndication/1.0.0/com.springsource.com.sun.syndication-sources-1.0.0.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/javax.servlet/com.springsource.javax.servlet.jsp.jstl/1.1.2/com.springsource.javax.servlet.jsp.jstl-1.1.2.jar" sourcepath="/IVY_CACHE/javax.servlet/com.springsource.javax.servlet.jsp.jstl/1.1.2/com.springsource.javax.servlet.jsp.jstl-sources-1.1.2.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/javax.activation/com.springsource.javax.activation/1.1.0/com.springsource.javax.activation-1.1.0.jar" sourcepath="/IVY_CACHE/javax.activation/com.springsource.javax.activation/1.1.0/com.springsource.javax.activation-sources-1.1.0.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/javax.servlet/com.springsource.javax.servlet.jsp/2.1.0/com.springsource.javax.servlet.jsp-2.1.0.jar" sourcepath="/IVY_CACHE/javax.servlet/com.springsource.javax.servlet.jsp/2.1.0/com.springsource.javax.servlet.jsp-sources-2.1.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-1.0.0.jar" sourcepath="/IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-sources-1.0.0.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/javax.servlet/com.springsource.javax.servlet/2.5.0/com.springsource.javax.servlet-2.5.0.jar" sourcepath="/IVY_CACHE/javax.servlet/com.springsource.javax.servlet/2.5.0/com.springsource.javax.servlet-sources-2.5.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/javax.servlet/com.springsource.javax.servlet.jsp.jstl/1.1.2/com.springsource.javax.servlet.jsp.jstl-1.1.2.jar" sourcepath="/IVY_CACHE/javax.servlet/com.springsource.javax.servlet.jsp.jstl/1.1.2/com.springsource.javax.servlet.jsp.jstl-sources-1.1.2.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/net.sourceforge.jasperreports/com.springsource.net.sf.jasperreports/2.0.5/com.springsource.net.sf.jasperreports-2.0.5.jar" sourcepath="/IVY_CACHE/net.sourceforge.jasperreports/com.springsource.net.sf.jasperreports/2.0.5/com.springsource.net.sf.jasperreports-sources-2.0.5.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/javax.servlet/com.springsource.javax.servlet.jsp/2.1.0/com.springsource.javax.servlet.jsp-2.1.0.jar" sourcepath="/IVY_CACHE/javax.servlet/com.springsource.javax.servlet.jsp/2.1.0/com.springsource.javax.servlet.jsp-sources-2.1.0.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/net.sourceforge.jexcelapi/com.springsource.jxl/2.6.6/com.springsource.jxl-2.6.6.jar" sourcepath="/IVY_CACHE/net.sourceforge.jexcelapi/com.springsource.jxl/2.6.6/com.springsource.jxl-sources-2.6.6.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/javax.servlet/com.springsource.javax.servlet/2.5.0/com.springsource.javax.servlet-2.5.0.jar" sourcepath="/IVY_CACHE/javax.servlet/com.springsource.javax.servlet/2.5.0/com.springsource.javax.servlet-sources-2.5.0.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar" sourcepath="/IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-sources-1.0.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/net.sourceforge.jasperreports/com.springsource.net.sf.jasperreports/2.0.5/com.springsource.net.sf.jasperreports-2.0.5.jar" sourcepath="/IVY_CACHE/net.sourceforge.jasperreports/com.springsource.net.sf.jasperreports/2.0.5/com.springsource.net.sf.jasperreports-sources-2.0.5.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.fileupload/1.2.0/com.springsource.org.apache.commons.fileupload-1.2.0.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.fileupload/1.2.0/com.springsource.org.apache.commons.fileupload-sources-1.2.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/net.sourceforge.jexcelapi/com.springsource.jxl/2.6.6/com.springsource.jxl-2.6.6.jar" sourcepath="/IVY_CACHE/net.sourceforge.jexcelapi/com.springsource.jxl/2.6.6/com.springsource.jxl-sources-2.6.6.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.lang/2.1.0/com.springsource.org.apache.commons.lang-2.1.0.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.lang/2.1.0/com.springsource.org.apache.commons.lang-sources-2.1.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-1.0.0.jar" sourcepath="/IVY_CACHE/org.aopalliance/com.springsource.org.aopalliance/1.0.0/com.springsource.org.aopalliance-sources-1.0.0.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.fileupload/1.2.0/com.springsource.org.apache.commons.fileupload-1.2.0.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.fileupload/1.2.0/com.springsource.org.apache.commons.fileupload-sources-1.2.0.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.poi/com.springsource.org.apache.poi/3.0.2.FINAL/com.springsource.org.apache.poi-3.0.2.FINAL.jar" sourcepath="/IVY_CACHE/org.apache.poi/com.springsource.org.apache.poi/3.0.2.FINAL/com.springsource.org.apache.poi-sources-3.0.2.FINAL.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.lang/2.1.0/com.springsource.org.apache.commons.lang-2.1.0.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.lang/2.1.0/com.springsource.org.apache.commons.lang-sources-2.1.0.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.taglibs/com.springsource.org.apache.taglibs.standard/1.1.2/com.springsource.org.apache.taglibs.standard-1.1.2.jar" sourcepath="/IVY_CACHE/org.apache.taglibs/com.springsource.org.apache.taglibs.standard/1.1.2/com.springsource.org.apache.taglibs.standard-sources-1.1.2.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-1.1.1.jar" sourcepath="/IVY_CACHE/org.apache.commons/com.springsource.org.apache.commons.logging/1.1.1/com.springsource.org.apache.commons.logging-sources-1.1.1.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.velocity/com.springsource.org.apache.velocity.tools.view/1.4.0/com.springsource.org.apache.velocity.tools.view-1.4.0.jar" sourcepath="/IVY_CACHE/org.apache.velocity/com.springsource.org.apache.velocity.tools.view/1.4.0/com.springsource.org.apache.velocity.tools.view-sources-1.4.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.apache.poi/com.springsource.org.apache.poi/3.0.2.FINAL/com.springsource.org.apache.poi-3.0.2.FINAL.jar" sourcepath="/IVY_CACHE/org.apache.poi/com.springsource.org.apache.poi/3.0.2.FINAL/com.springsource.org.apache.poi-sources-3.0.2.FINAL.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.velocity/com.springsource.org.apache.velocity/1.5.0/com.springsource.org.apache.velocity-1.5.0.jar" sourcepath="/IVY_CACHE/org.apache.velocity/com.springsource.org.apache.velocity/1.5.0/com.springsource.org.apache.velocity-sources-1.5.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.apache.taglibs/com.springsource.org.apache.taglibs.standard/1.1.2/com.springsource.org.apache.taglibs.standard-1.1.2.jar" sourcepath="/IVY_CACHE/org.apache.taglibs/com.springsource.org.apache.taglibs.standard/1.1.2/com.springsource.org.apache.taglibs.standard-sources-1.1.2.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.codehaus.jackson/com.springsource.org.codehaus.jackson.mapper/1.0.0/com.springsource.org.codehaus.jackson.mapper-1.0.0.jar" sourcepath="/IVY_CACHE/org.codehaus.jackson/com.springsource.org.codehaus.jackson.mapper/1.0.0/com.springsource.org.codehaus.jackson.mapper-sources-1.0.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.apache.velocity/com.springsource.org.apache.velocity.tools.view/1.4.0/com.springsource.org.apache.velocity.tools.view-1.4.0.jar" sourcepath="/IVY_CACHE/org.apache.velocity/com.springsource.org.apache.velocity.tools.view/1.4.0/com.springsource.org.apache.velocity.tools.view-sources-1.4.0.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.codehaus.jackson/com.springsource.org.codehaus.jackson/1.0.0/com.springsource.org.codehaus.jackson-1.0.0.jar" sourcepath="/IVY_CACHE/org.codehaus.jackson/com.springsource.org.codehaus.jackson/1.0.0/com.springsource.org.codehaus.jackson-sources-1.0.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.apache.velocity/com.springsource.org.apache.velocity/1.5.0/com.springsource.org.apache.velocity-1.5.0.jar" sourcepath="/IVY_CACHE/org.apache.velocity/com.springsource.org.apache.velocity/1.5.0/com.springsource.org.apache.velocity-sources-1.5.0.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.custommonkey.xmlunit/com.springsource.org.custommonkey.xmlunit/1.2.0/com.springsource.org.custommonkey.xmlunit-1.2.0.jar" sourcepath="/IVY_CACHE/org.custommonkey.xmlunit/com.springsource.org.custommonkey.xmlunit/1.2.0/com.springsource.org.custommonkey.xmlunit-sources-1.2.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.codehaus.jackson/com.springsource.org.codehaus.jackson.mapper/1.0.0/com.springsource.org.codehaus.jackson.mapper-1.0.0.jar" sourcepath="/IVY_CACHE/org.codehaus.jackson/com.springsource.org.codehaus.jackson.mapper/1.0.0/com.springsource.org.codehaus.jackson.mapper-sources-1.0.0.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.dom4j/com.springsource.org.dom4j/1.6.1/com.springsource.org.dom4j-1.6.1.jar" sourcepath="/IVY_CACHE/org.dom4j/com.springsource.org.dom4j/1.6.1/com.springsource.org.dom4j-sources-1.6.1.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.codehaus.jackson/com.springsource.org.codehaus.jackson/1.0.0/com.springsource.org.codehaus.jackson-1.0.0.jar" sourcepath="/IVY_CACHE/org.codehaus.jackson/com.springsource.org.codehaus.jackson/1.0.0/com.springsource.org.codehaus.jackson-sources-1.0.0.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-2.5.1.jar" sourcepath="/IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-sources-2.5.1.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.custommonkey.xmlunit/com.springsource.org.custommonkey.xmlunit/1.2.0/com.springsource.org.custommonkey.xmlunit-1.2.0.jar" sourcepath="/IVY_CACHE/org.custommonkey.xmlunit/com.springsource.org.custommonkey.xmlunit/1.2.0/com.springsource.org.custommonkey.xmlunit-sources-1.2.0.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.freemarker/com.springsource.freemarker/2.3.15/com.springsource.freemarker-2.3.15.jar" sourcepath="/IVY_CACHE/org.freemarker/com.springsource.freemarker/2.3.15/com.springsource.freemarker-sources-2.3.15.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.dom4j/com.springsource.org.dom4j/1.6.1/com.springsource.org.dom4j-1.6.1.jar" sourcepath="/IVY_CACHE/org.dom4j/com.springsource.org.dom4j/1.6.1/com.springsource.org.dom4j-sources-1.6.1.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.jaxen/com.springsource.org.jaxen/1.1.1/com.springsource.org.jaxen-1.1.1.jar" sourcepath="/IVY_CACHE/org.jaxen/com.springsource.org.jaxen/1.1.1/com.springsource.org.jaxen-sources-1.1.1.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-2.5.1.jar" sourcepath="/IVY_CACHE/org.easymock/com.springsource.org.easymock/2.5.1/com.springsource.org.easymock-sources-2.5.1.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.jdom/com.springsource.org.jdom/1.0.0/com.springsource.org.jdom-1.0.0.jar" sourcepath="/IVY_CACHE/org.jdom/com.springsource.org.jdom/1.0.0/com.springsource.org.jdom-1.0.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.freemarker/com.springsource.freemarker/2.3.15/com.springsource.freemarker-2.3.15.jar" sourcepath="/IVY_CACHE/org.freemarker/com.springsource.freemarker/2.3.15/com.springsource.freemarker-sources-2.3.15.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.6.0/com.springsource.org.junit-4.6.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.6.0/com.springsource.org.junit-sources-4.6.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.jaxen/com.springsource.org.jaxen/1.1.1/com.springsource.org.jaxen-1.1.1.jar" sourcepath="/IVY_CACHE/org.jaxen/com.springsource.org.jaxen/1.1.1/com.springsource.org.jaxen-sources-1.1.1.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.mozilla.javascript/com.springsource.org.mozilla.javascript/1.7.0.R2/com.springsource.org.mozilla.javascript-1.7.0.R2.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.jdom/com.springsource.org.jdom/1.0.0/com.springsource.org.jdom-1.0.0.jar" sourcepath="/IVY_CACHE/org.jdom/com.springsource.org.jdom/1.0.0/com.springsource.org.jdom-1.0.0.jar"/> |
||||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.transaction"/> |
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.org.junit/4.6.0/com.springsource.org.junit-4.6.0.jar" sourcepath="/IVY_CACHE/org.junit/com.springsource.org.junit/4.6.0/com.springsource.org.junit-sources-4.6.0.jar"/> |
||||||
<classpathentry combineaccessrules="false" kind="src" path="/org.springframework.jdbc"/> |
<classpathentry kind="var" path="IVY_CACHE/org.mozilla.javascript/com.springsource.org.mozilla.javascript/1.7.0.R2/com.springsource.org.mozilla.javascript-1.7.0.R2.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.hibernate/com.springsource.org.hibernate/3.3.1.GA/com.springsource.org.hibernate-3.3.1.GA.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.hibernate/com.springsource.org.hibernate/3.3.1.GA/com.springsource.org.hibernate-3.3.1.GA.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/javax.transaction/com.springsource.javax.transaction/1.1.0/com.springsource.javax.transaction-1.1.0.jar" sourcepath="/IVY_CACHE/javax.transaction/com.springsource.javax.transaction/1.1.0/com.springsource.javax.transaction-sources-1.1.0.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/javax.transaction/com.springsource.javax.transaction/1.1.0/com.springsource.javax.transaction-1.1.0.jar" sourcepath="/IVY_CACHE/javax.transaction/com.springsource.javax.transaction/1.1.0/com.springsource.javax.transaction-sources-1.1.0.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.tiles/com.springsource.org.apache.tiles/2.1.2.osgi/com.springsource.org.apache.tiles-2.1.2.osgi.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.apache.tiles/com.springsource.org.apache.tiles/2.1.2.osgi/com.springsource.org.apache.tiles-2.1.2.osgi.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.tiles/com.springsource.org.apache.tiles.core/2.1.2.osgi/com.springsource.org.apache.tiles.core-2.1.2.osgi.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.apache.tiles/com.springsource.org.apache.tiles.core/2.1.2.osgi/com.springsource.org.apache.tiles.core-2.1.2.osgi.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.tiles/com.springsource.org.apache.tiles.jsp/2.1.2/com.springsource.org.apache.tiles.jsp-2.1.2.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.apache.tiles/com.springsource.org.apache.tiles.jsp/2.1.2/com.springsource.org.apache.tiles.jsp-2.1.2.jar"/> |
||||||
<classpathentry kind="var" path="IVY_CACHE/org.apache.tiles/com.springsource.org.apache.tiles.servlet/2.1.2/com.springsource.org.apache.tiles.servlet-2.1.2.jar"/> |
<classpathentry kind="var" path="IVY_CACHE/org.apache.tiles/com.springsource.org.apache.tiles.servlet/2.1.2/com.springsource.org.apache.tiles.servlet-2.1.2.jar"/> |
||||||
<classpathentry kind="output" path="target/classes"/> |
<classpathentry kind="output" path="target/classes"/> |
||||||
</classpath> |
</classpath> |
||||||
|
|||||||
@ -1,211 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.bind; |
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
import org.springframework.validation.Errors; |
|
||||||
import org.springframework.validation.FieldError; |
|
||||||
import org.springframework.validation.ObjectError; |
|
||||||
import org.springframework.web.util.HtmlUtils; |
|
||||||
|
|
||||||
/** |
|
||||||
* Errors wrapper that adds automatic HTML escaping to the wrapped instance, |
|
||||||
* for convenient usage in HTML views. Can be retrieved easily via |
|
||||||
* RequestContext's <code>getErrors</code> method. |
|
||||||
* |
|
||||||
* <p>Note that BindTag does <i>not</i> use this class to avoid unnecessary |
|
||||||
* creation of ObjectError instances. It just escapes the messages and values |
|
||||||
* that get copied into the respective BindStatus instance. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 01.03.2003 |
|
||||||
* @see org.springframework.web.servlet.support.RequestContext#getErrors |
|
||||||
* @see org.springframework.web.servlet.tags.BindTag |
|
||||||
*/ |
|
||||||
public class EscapedErrors implements Errors { |
|
||||||
|
|
||||||
private final Errors source; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Create a new EscapedErrors instance for the given source instance. |
|
||||||
*/ |
|
||||||
public EscapedErrors(Errors source) { |
|
||||||
if (source == null) { |
|
||||||
throw new IllegalArgumentException("Cannot wrap a null instance"); |
|
||||||
} |
|
||||||
this.source = source; |
|
||||||
} |
|
||||||
|
|
||||||
public Errors getSource() { |
|
||||||
return this.source; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public String getObjectName() { |
|
||||||
return this.source.getObjectName(); |
|
||||||
} |
|
||||||
|
|
||||||
public void setNestedPath(String nestedPath) { |
|
||||||
this.source.setNestedPath(nestedPath); |
|
||||||
} |
|
||||||
|
|
||||||
public String getNestedPath() { |
|
||||||
return this.source.getNestedPath(); |
|
||||||
} |
|
||||||
|
|
||||||
public void pushNestedPath(String subPath) { |
|
||||||
this.source.pushNestedPath(subPath); |
|
||||||
} |
|
||||||
|
|
||||||
public void popNestedPath() throws IllegalStateException { |
|
||||||
this.source.popNestedPath(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void reject(String errorCode) { |
|
||||||
this.source.reject(errorCode); |
|
||||||
} |
|
||||||
|
|
||||||
public void reject(String errorCode, String defaultMessage) { |
|
||||||
this.source.reject(errorCode, defaultMessage); |
|
||||||
} |
|
||||||
|
|
||||||
public void reject(String errorCode, Object[] errorArgs, String defaultMessage) { |
|
||||||
this.source.reject(errorCode, errorArgs, defaultMessage); |
|
||||||
} |
|
||||||
|
|
||||||
public void rejectValue(String field, String errorCode) { |
|
||||||
this.source.rejectValue(field, errorCode); |
|
||||||
} |
|
||||||
|
|
||||||
public void rejectValue(String field, String errorCode, String defaultMessage) { |
|
||||||
this.source.rejectValue(field, errorCode, defaultMessage); |
|
||||||
} |
|
||||||
|
|
||||||
public void rejectValue(String field, String errorCode, Object[] errorArgs, String defaultMessage) { |
|
||||||
this.source.rejectValue(field, errorCode, errorArgs, defaultMessage); |
|
||||||
} |
|
||||||
|
|
||||||
public void addAllErrors(Errors errors) { |
|
||||||
this.source.addAllErrors(errors); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public boolean hasErrors() { |
|
||||||
return this.source.hasErrors(); |
|
||||||
} |
|
||||||
|
|
||||||
public int getErrorCount() { |
|
||||||
return this.source.getErrorCount(); |
|
||||||
} |
|
||||||
|
|
||||||
public List<ObjectError> getAllErrors() { |
|
||||||
return escapeObjectErrors(this.source.getAllErrors()); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean hasGlobalErrors() { |
|
||||||
return this.source.hasGlobalErrors(); |
|
||||||
} |
|
||||||
|
|
||||||
public int getGlobalErrorCount() { |
|
||||||
return this.source.getGlobalErrorCount(); |
|
||||||
} |
|
||||||
|
|
||||||
public List<ObjectError> getGlobalErrors() { |
|
||||||
return escapeObjectErrors(this.source.getGlobalErrors()); |
|
||||||
} |
|
||||||
|
|
||||||
public ObjectError getGlobalError() { |
|
||||||
return escapeObjectError(this.source.getGlobalError()); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean hasFieldErrors() { |
|
||||||
return this.source.hasFieldErrors(); |
|
||||||
} |
|
||||||
|
|
||||||
public int getFieldErrorCount() { |
|
||||||
return this.source.getFieldErrorCount(); |
|
||||||
} |
|
||||||
|
|
||||||
public List<FieldError> getFieldErrors() { |
|
||||||
return this.source.getFieldErrors(); |
|
||||||
} |
|
||||||
|
|
||||||
public FieldError getFieldError() { |
|
||||||
return this.source.getFieldError(); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean hasFieldErrors(String field) { |
|
||||||
return this.source.hasFieldErrors(field); |
|
||||||
} |
|
||||||
|
|
||||||
public int getFieldErrorCount(String field) { |
|
||||||
return this.source.getFieldErrorCount(field); |
|
||||||
} |
|
||||||
|
|
||||||
public List<FieldError> getFieldErrors(String field) { |
|
||||||
return escapeObjectErrors(this.source.getFieldErrors(field)); |
|
||||||
} |
|
||||||
|
|
||||||
public FieldError getFieldError(String field) { |
|
||||||
return escapeObjectError(this.source.getFieldError(field)); |
|
||||||
} |
|
||||||
|
|
||||||
public Object getFieldValue(String field) { |
|
||||||
Object value = this.source.getFieldValue(field); |
|
||||||
return (value instanceof String ? HtmlUtils.htmlEscape((String) value) : value); |
|
||||||
} |
|
||||||
|
|
||||||
public Class getFieldType(String field) { |
|
||||||
return this.source.getFieldType(field); |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
private <T extends ObjectError> T escapeObjectError(T source) { |
|
||||||
if (source == null) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
if (source instanceof FieldError) { |
|
||||||
FieldError fieldError = (FieldError) source; |
|
||||||
Object value = fieldError.getRejectedValue(); |
|
||||||
if (value instanceof String) { |
|
||||||
value = HtmlUtils.htmlEscape((String) value); |
|
||||||
} |
|
||||||
return (T) new FieldError( |
|
||||||
fieldError.getObjectName(), fieldError.getField(), value, |
|
||||||
fieldError.isBindingFailure(), fieldError.getCodes(), |
|
||||||
fieldError.getArguments(), HtmlUtils.htmlEscape(fieldError.getDefaultMessage())); |
|
||||||
} |
|
||||||
else { |
|
||||||
return (T) new ObjectError( |
|
||||||
source.getObjectName(), source.getCodes(), source.getArguments(), |
|
||||||
HtmlUtils.htmlEscape(source.getDefaultMessage())); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private <T extends ObjectError> List<T> escapeObjectErrors(List<T> source) { |
|
||||||
List<T> escaped = new ArrayList<T>(source.size()); |
|
||||||
for (T objectError : source) { |
|
||||||
escaped.add(escapeObjectError(objectError)); |
|
||||||
} |
|
||||||
return escaped; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,63 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind; |
|
||||||
|
|
||||||
/** |
|
||||||
* {@link ServletRequestBindingException} subclass that indicates a missing parameter. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.0.2 |
|
||||||
*/ |
|
||||||
public class MissingServletRequestParameterException extends ServletRequestBindingException { |
|
||||||
|
|
||||||
private final String parameterName; |
|
||||||
|
|
||||||
private final String parameterType; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Constructor for MissingServletRequestParameterException. |
|
||||||
* @param parameterName the name of the missing parameter |
|
||||||
* @param parameterType the expected type of the missing parameter |
|
||||||
*/ |
|
||||||
public MissingServletRequestParameterException(String parameterName, String parameterType) { |
|
||||||
super(""); |
|
||||||
this.parameterName = parameterName; |
|
||||||
this.parameterType = parameterType; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String getMessage() { |
|
||||||
return "Required " + this.parameterType + " parameter '" + this.parameterName + "' is not present"; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the name of the offending parameter. |
|
||||||
*/ |
|
||||||
public final String getParameterName() { |
|
||||||
return this.parameterName; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the expected type of the offending parameter. |
|
||||||
*/ |
|
||||||
public final String getParameterType() { |
|
||||||
return this.parameterType; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,51 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2006 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.bind; |
|
||||||
|
|
||||||
import org.springframework.web.util.NestedServletException; |
|
||||||
|
|
||||||
/** |
|
||||||
* Fatal binding exception, thrown when we want to |
|
||||||
* treat binding exceptions as unrecoverable. |
|
||||||
* |
|
||||||
* <p>Extends ServletException for convenient throwing in any Servlet resource |
|
||||||
* (such as a Filter), and NestedServletException for proper root cause handling |
|
||||||
* (as the plain ServletException doesn't expose its root cause at all). |
|
||||||
* |
|
||||||
* @author Rod Johnson |
|
||||||
* @author Juergen Hoeller |
|
||||||
*/ |
|
||||||
public class ServletRequestBindingException extends NestedServletException { |
|
||||||
|
|
||||||
/** |
|
||||||
* Constructor for ServletRequestBindingException. |
|
||||||
* @param msg the detail message |
|
||||||
*/ |
|
||||||
public ServletRequestBindingException(String msg) { |
|
||||||
super(msg); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Constructor for ServletRequestBindingException. |
|
||||||
* @param msg the detail message |
|
||||||
* @param cause the root cause |
|
||||||
*/ |
|
||||||
public ServletRequestBindingException(String msg, Throwable cause) { |
|
||||||
super(msg, cause); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,127 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.bind; |
|
||||||
|
|
||||||
import javax.servlet.ServletRequest; |
|
||||||
|
|
||||||
import org.springframework.beans.MutablePropertyValues; |
|
||||||
import org.springframework.validation.BindException; |
|
||||||
import org.springframework.web.multipart.MultipartHttpServletRequest; |
|
||||||
|
|
||||||
/** |
|
||||||
* Special {@link org.springframework.validation.DataBinder} to perform data binding |
|
||||||
* from servlet request parameters to JavaBeans, including support for multipart files. |
|
||||||
* |
|
||||||
* <p>See the DataBinder/WebDataBinder superclasses for customization options, |
|
||||||
* which include specifying allowed/required fields, and registering custom |
|
||||||
* property editors. |
|
||||||
* |
|
||||||
* <p>Used by Spring Web MVC's BaseCommandController and MultiActionController. |
|
||||||
* Note that BaseCommandController and its subclasses allow for easy customization |
|
||||||
* of the binder instances that they use through overriding <code>initBinder</code>. |
|
||||||
* |
|
||||||
* <p>Can also be used for manual data binding in custom web controllers: |
|
||||||
* for example, in a plain Controller implementation or in a MultiActionController |
|
||||||
* handler method. Simply instantiate a ServletRequestDataBinder for each binding |
|
||||||
* process, and invoke <code>bind</code> with the current ServletRequest as argument: |
|
||||||
* |
|
||||||
* <pre class="code"> |
|
||||||
* MyBean myBean = new MyBean(); |
|
||||||
* // apply binder to custom target object
|
|
||||||
* ServletRequestDataBinder binder = new ServletRequestDataBinder(myBean); |
|
||||||
* // register custom editors, if desired
|
|
||||||
* binder.registerCustomEditor(...); |
|
||||||
* // trigger actual binding of request parameters
|
|
||||||
* binder.bind(request); |
|
||||||
* // optionally evaluate binding errors
|
|
||||||
* Errors errors = binder.getErrors(); |
|
||||||
* ...</pre> |
|
||||||
* |
|
||||||
* @author Rod Johnson |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @see #bind(javax.servlet.ServletRequest) |
|
||||||
* @see #registerCustomEditor |
|
||||||
* @see #setAllowedFields |
|
||||||
* @see #setRequiredFields |
|
||||||
* @see #setFieldMarkerPrefix |
|
||||||
* @see org.springframework.web.servlet.mvc.BaseCommandController#initBinder |
|
||||||
*/ |
|
||||||
public class ServletRequestDataBinder extends WebDataBinder { |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a new ServletRequestDataBinder instance, with default object name. |
|
||||||
* @param target the target object to bind onto (or <code>null</code> |
|
||||||
* if the binder is just used to convert a plain parameter value) |
|
||||||
* @see #DEFAULT_OBJECT_NAME |
|
||||||
*/ |
|
||||||
public ServletRequestDataBinder(Object target) { |
|
||||||
super(target); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a new ServletRequestDataBinder instance. |
|
||||||
* @param target the target object to bind onto (or <code>null</code> |
|
||||||
* if the binder is just used to convert a plain parameter value) |
|
||||||
* @param objectName the name of the target object |
|
||||||
*/ |
|
||||||
public ServletRequestDataBinder(Object target, String objectName) { |
|
||||||
super(target, objectName); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Bind the parameters of the given request to this binder's target, |
|
||||||
* also binding multipart files in case of a multipart request. |
|
||||||
* <p>This call can create field errors, representing basic binding |
|
||||||
* errors like a required field (code "required"), or type mismatch |
|
||||||
* between value and bean property (code "typeMismatch"). |
|
||||||
* <p>Multipart files are bound via their parameter name, just like normal |
|
||||||
* HTTP parameters: i.e. "uploadedFile" to an "uploadedFile" bean property, |
|
||||||
* invoking a "setUploadedFile" setter method. |
|
||||||
* <p>The type of the target property for a multipart file can be MultipartFile, |
|
||||||
* byte[], or String. The latter two receive the contents of the uploaded file; |
|
||||||
* all metadata like original file name, content type, etc are lost in those cases. |
|
||||||
* @param request request with parameters to bind (can be multipart) |
|
||||||
* @see org.springframework.web.multipart.MultipartHttpServletRequest |
|
||||||
* @see org.springframework.web.multipart.MultipartFile |
|
||||||
* @see #bindMultipartFiles |
|
||||||
* @see #bind(org.springframework.beans.PropertyValues) |
|
||||||
*/ |
|
||||||
public void bind(ServletRequest request) { |
|
||||||
MutablePropertyValues mpvs = new ServletRequestParameterPropertyValues(request); |
|
||||||
if (request instanceof MultipartHttpServletRequest) { |
|
||||||
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; |
|
||||||
bindMultipartFiles(multipartRequest.getFileMap(), mpvs); |
|
||||||
} |
|
||||||
doBind(mpvs); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Treats errors as fatal. |
|
||||||
* <p>Use this method only if it's an error if the input isn't valid. |
|
||||||
* This might be appropriate if all input is from dropdowns, for example. |
|
||||||
* @throws ServletRequestBindingException subclass of ServletException on any binding problem |
|
||||||
*/ |
|
||||||
public void closeNoCatch() throws ServletRequestBindingException { |
|
||||||
if (getBindingResult().hasErrors()) { |
|
||||||
throw new ServletRequestBindingException( |
|
||||||
"Errors binding onto object '" + getBindingResult().getObjectName() + "'", |
|
||||||
new BindException(getBindingResult())); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,80 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2005 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.bind; |
|
||||||
|
|
||||||
import javax.servlet.ServletRequest; |
|
||||||
|
|
||||||
import org.springframework.beans.MutablePropertyValues; |
|
||||||
import org.springframework.web.util.WebUtils; |
|
||||||
|
|
||||||
/** |
|
||||||
* PropertyValues implementation created from parameters in a ServletRequest. |
|
||||||
* Can look for all property values beginning with a certain prefix and |
|
||||||
* prefix separator (default is "_"). |
|
||||||
* |
|
||||||
* <p>For example, with a prefix of "spring", "spring_param1" and |
|
||||||
* "spring_param2" result in a Map with "param1" and "param2" as keys. |
|
||||||
* |
|
||||||
* <p>This class is not immutable to be able to efficiently remove property |
|
||||||
* values that should be ignored for binding. |
|
||||||
* |
|
||||||
* @author Rod Johnson |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @see org.springframework.web.util.WebUtils#getParametersStartingWith |
|
||||||
*/ |
|
||||||
public class ServletRequestParameterPropertyValues extends MutablePropertyValues { |
|
||||||
|
|
||||||
/** Default prefix separator */ |
|
||||||
public static final String DEFAULT_PREFIX_SEPARATOR = "_"; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Create new ServletRequestPropertyValues using no prefix |
|
||||||
* (and hence, no prefix separator). |
|
||||||
* @param request HTTP request |
|
||||||
*/ |
|
||||||
public ServletRequestParameterPropertyValues(ServletRequest request) { |
|
||||||
this(request, null, null); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create new ServletRequestPropertyValues using the given prefix and |
|
||||||
* the default prefix separator (the underscore character "_"). |
|
||||||
* @param request HTTP request |
|
||||||
* @param prefix the prefix for parameters (the full prefix will |
|
||||||
* consist of this plus the separator) |
|
||||||
* @see #DEFAULT_PREFIX_SEPARATOR |
|
||||||
*/ |
|
||||||
public ServletRequestParameterPropertyValues(ServletRequest request, String prefix) { |
|
||||||
this(request, prefix, DEFAULT_PREFIX_SEPARATOR); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create new ServletRequestPropertyValues supplying both prefix and |
|
||||||
* prefix separator. |
|
||||||
* @param request HTTP request |
|
||||||
* @param prefix the prefix for parameters (the full prefix will |
|
||||||
* consist of this plus the separator) |
|
||||||
* @param prefixSeparator separator delimiting prefix (e.g. "spring") |
|
||||||
* and the rest of the parameter name ("param1", "param2") |
|
||||||
*/ |
|
||||||
public ServletRequestParameterPropertyValues(ServletRequest request, String prefix, String prefixSeparator) { |
|
||||||
super(WebUtils.getParametersStartingWith( |
|
||||||
request, (prefix != null) ? prefix + prefixSeparator : null)); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,709 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.bind; |
|
||||||
|
|
||||||
import javax.servlet.ServletRequest; |
|
||||||
|
|
||||||
/** |
|
||||||
* Parameter extraction methods, for an approach distinct from data binding, |
|
||||||
* in which parameters of specific types are required. |
|
||||||
* |
|
||||||
* <p>This approach is very useful for simple submissions, where binding |
|
||||||
* request parameters to a command object would be overkill. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @author Keith Donald |
|
||||||
* @since 2.0 |
|
||||||
*/ |
|
||||||
public abstract class ServletRequestUtils { |
|
||||||
|
|
||||||
private static final IntParser INT_PARSER = new IntParser(); |
|
||||||
|
|
||||||
private static final LongParser LONG_PARSER = new LongParser(); |
|
||||||
|
|
||||||
private static final FloatParser FLOAT_PARSER = new FloatParser(); |
|
||||||
|
|
||||||
private static final DoubleParser DOUBLE_PARSER = new DoubleParser(); |
|
||||||
|
|
||||||
private static final BooleanParser BOOLEAN_PARSER = new BooleanParser(); |
|
||||||
|
|
||||||
private static final StringParser STRING_PARSER = new StringParser(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get an Integer parameter, or <code>null</code> if not present. |
|
||||||
* Throws an exception if it the parameter value isn't a number. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @return the Integer value, or <code>null</code> if not present |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static Integer getIntParameter(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
if (request.getParameter(name) == null) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
return getRequiredIntParameter(request, name); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get an int parameter, with a fallback value. Never throws an exception. |
|
||||||
* Can pass a distinguished value as default to enable checks of whether it was supplied. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @param defaultVal the default value to use as fallback |
|
||||||
*/ |
|
||||||
public static int getIntParameter(ServletRequest request, String name, int defaultVal) { |
|
||||||
if (request.getParameter(name) == null) { |
|
||||||
return defaultVal; |
|
||||||
} |
|
||||||
try { |
|
||||||
return getRequiredIntParameter(request, name); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
return defaultVal; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get an array of int parameters, return an empty array if not found. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter with multiple possible values |
|
||||||
*/ |
|
||||||
public static int[] getIntParameters(ServletRequest request, String name) { |
|
||||||
try { |
|
||||||
return getRequiredIntParameters(request, name); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
return new int[0]; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get an int parameter, throwing an exception if it isn't found or isn't a number. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static int getRequiredIntParameter(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
return INT_PARSER.parseInt(name, request.getParameter(name)); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get an array of int parameters, throwing an exception if not found or one is not a number.. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter with multiple possible values |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static int[] getRequiredIntParameters(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
return INT_PARSER.parseInts(name, request.getParameterValues(name)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a Long parameter, or <code>null</code> if not present. |
|
||||||
* Throws an exception if it the parameter value isn't a number. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @return the Long value, or <code>null</code> if not present |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static Long getLongParameter(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
if (request.getParameter(name) == null) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
return getRequiredLongParameter(request, name); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get a long parameter, with a fallback value. Never throws an exception. |
|
||||||
* Can pass a distinguished value as default to enable checks of whether it was supplied. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @param defaultVal the default value to use as fallback |
|
||||||
*/ |
|
||||||
public static long getLongParameter(ServletRequest request, String name, long defaultVal) { |
|
||||||
if (request.getParameter(name) == null) { |
|
||||||
return defaultVal; |
|
||||||
} |
|
||||||
try { |
|
||||||
return getRequiredLongParameter(request, name); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
return defaultVal; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get an array of long parameters, return an empty array if not found. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter with multiple possible values |
|
||||||
*/ |
|
||||||
public static long[] getLongParameters(ServletRequest request, String name) { |
|
||||||
try { |
|
||||||
return getRequiredLongParameters(request, name); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
return new long[0]; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get a long parameter, throwing an exception if it isn't found or isn't a number. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static long getRequiredLongParameter(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
return LONG_PARSER.parseLong(name, request.getParameter(name)); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get an array of long parameters, throwing an exception if not found or one is not a number. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter with multiple possible values |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static long[] getRequiredLongParameters(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
return LONG_PARSER.parseLongs(name, request.getParameterValues(name)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a Float parameter, or <code>null</code> if not present. |
|
||||||
* Throws an exception if it the parameter value isn't a number. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @return the Float value, or <code>null</code> if not present |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static Float getFloatParameter(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
if (request.getParameter(name) == null) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
return getRequiredFloatParameter(request, name); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get a float parameter, with a fallback value. Never throws an exception. |
|
||||||
* Can pass a distinguished value as default to enable checks of whether it was supplied. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @param defaultVal the default value to use as fallback |
|
||||||
*/ |
|
||||||
public static float getFloatParameter(ServletRequest request, String name, float defaultVal) { |
|
||||||
if (request.getParameter(name) == null) { |
|
||||||
return defaultVal; |
|
||||||
} |
|
||||||
try { |
|
||||||
return getRequiredFloatParameter(request, name); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
return defaultVal; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get an array of float parameters, return an empty array if not found. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter with multiple possible values |
|
||||||
*/ |
|
||||||
public static float[] getFloatParameters(ServletRequest request, String name) { |
|
||||||
try { |
|
||||||
return getRequiredFloatParameters(request, name); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
return new float[0]; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get a float parameter, throwing an exception if it isn't found or isn't a number. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static float getRequiredFloatParameter(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
return FLOAT_PARSER.parseFloat(name, request.getParameter(name)); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get an array of float parameters, throwing an exception if not found or one is not a number. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter with multiple possible values |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static float[] getRequiredFloatParameters(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
return FLOAT_PARSER.parseFloats(name, request.getParameterValues(name)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a Double parameter, or <code>null</code> if not present. |
|
||||||
* Throws an exception if it the parameter value isn't a number. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @return the Double value, or <code>null</code> if not present |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static Double getDoubleParameter(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
if (request.getParameter(name) == null) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
return getRequiredDoubleParameter(request, name); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get a double parameter, with a fallback value. Never throws an exception. |
|
||||||
* Can pass a distinguished value as default to enable checks of whether it was supplied. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @param defaultVal the default value to use as fallback |
|
||||||
*/ |
|
||||||
public static double getDoubleParameter(ServletRequest request, String name, double defaultVal) { |
|
||||||
if (request.getParameter(name) == null) { |
|
||||||
return defaultVal; |
|
||||||
} |
|
||||||
try { |
|
||||||
return getRequiredDoubleParameter(request, name); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
return defaultVal; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get an array of double parameters, return an empty array if not found. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter with multiple possible values |
|
||||||
*/ |
|
||||||
public static double[] getDoubleParameters(ServletRequest request, String name) { |
|
||||||
try { |
|
||||||
return getRequiredDoubleParameters(request, name); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
return new double[0]; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get a double parameter, throwing an exception if it isn't found or isn't a number. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static double getRequiredDoubleParameter(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
return DOUBLE_PARSER.parseDouble(name, request.getParameter(name)); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get an array of double parameters, throwing an exception if not found or one is not a number. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter with multiple possible values |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static double[] getRequiredDoubleParameters(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
return DOUBLE_PARSER.parseDoubles(name, request.getParameterValues(name)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a Boolean parameter, or <code>null</code> if not present. |
|
||||||
* Throws an exception if it the parameter value isn't a boolean. |
|
||||||
* <p>Accepts "true", "on", "yes" (any case) and "1" as values for true; |
|
||||||
* treats every other non-empty value as false (i.e. parses leniently). |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @return the Boolean value, or <code>null</code> if not present |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static Boolean getBooleanParameter(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
if (request.getParameter(name) == null) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
return (getRequiredBooleanParameter(request, name)); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get a boolean parameter, with a fallback value. Never throws an exception. |
|
||||||
* Can pass a distinguished value as default to enable checks of whether it was supplied. |
|
||||||
* <p>Accepts "true", "on", "yes" (any case) and "1" as values for true; |
|
||||||
* treats every other non-empty value as false (i.e. parses leniently). |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @param defaultVal the default value to use as fallback |
|
||||||
*/ |
|
||||||
public static boolean getBooleanParameter(ServletRequest request, String name, boolean defaultVal) { |
|
||||||
if (request.getParameter(name) == null) { |
|
||||||
return defaultVal; |
|
||||||
} |
|
||||||
try { |
|
||||||
return getRequiredBooleanParameter(request, name); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
return defaultVal; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get an array of boolean parameters, return an empty array if not found. |
|
||||||
* <p>Accepts "true", "on", "yes" (any case) and "1" as values for true; |
|
||||||
* treats every other non-empty value as false (i.e. parses leniently). |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter with multiple possible values |
|
||||||
*/ |
|
||||||
public static boolean[] getBooleanParameters(ServletRequest request, String name) { |
|
||||||
try { |
|
||||||
return getRequiredBooleanParameters(request, name); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
return new boolean[0]; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get a boolean parameter, throwing an exception if it isn't found |
|
||||||
* or isn't a boolean. |
|
||||||
* <p>Accepts "true", "on", "yes" (any case) and "1" as values for true; |
|
||||||
* treats every other non-empty value as false (i.e. parses leniently). |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static boolean getRequiredBooleanParameter(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
return BOOLEAN_PARSER.parseBoolean(name, request.getParameter(name)); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get an array of boolean parameters, throwing an exception if not found |
|
||||||
* or one isn't a boolean. |
|
||||||
* <p>Accepts "true", "on", "yes" (any case) and "1" as values for true; |
|
||||||
* treats every other non-empty value as false (i.e. parses leniently). |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static boolean[] getRequiredBooleanParameters(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
return BOOLEAN_PARSER.parseBooleans(name, request.getParameterValues(name)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Get a String parameter, or <code>null</code> if not present. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @return the String value, or <code>null</code> if not present |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static String getStringParameter(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
if (request.getParameter(name) == null) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
return getRequiredStringParameter(request, name); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get a String parameter, with a fallback value. Never throws an exception. |
|
||||||
* Can pass a distinguished value to default to enable checks of whether it was supplied. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @param defaultVal the default value to use as fallback |
|
||||||
*/ |
|
||||||
public static String getStringParameter(ServletRequest request, String name, String defaultVal) { |
|
||||||
String val = request.getParameter(name); |
|
||||||
return (val != null ? val : defaultVal); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get an array of String parameters, return an empty array if not found. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter with multiple possible values |
|
||||||
*/ |
|
||||||
public static String[] getStringParameters(ServletRequest request, String name) { |
|
||||||
try { |
|
||||||
return getRequiredStringParameters(request, name); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
return new String[0]; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get a String parameter, throwing an exception if it isn't found. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static String getRequiredStringParameter(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
return STRING_PARSER.validateRequiredString(name, request.getParameter(name)); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get an array of String parameters, throwing an exception if not found. |
|
||||||
* @param request current HTTP request |
|
||||||
* @param name the name of the parameter |
|
||||||
* @throws ServletRequestBindingException a subclass of ServletException, |
|
||||||
* so it doesn't need to be caught |
|
||||||
*/ |
|
||||||
public static String[] getRequiredStringParameters(ServletRequest request, String name) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
return STRING_PARSER.validateRequiredStrings(name, request.getParameterValues(name)); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private abstract static class ParameterParser<T> { |
|
||||||
|
|
||||||
protected final T parse(String name, String parameter) throws ServletRequestBindingException { |
|
||||||
validateRequiredParameter(name, parameter); |
|
||||||
try { |
|
||||||
return doParse(parameter); |
|
||||||
} |
|
||||||
catch (NumberFormatException ex) { |
|
||||||
throw new ServletRequestBindingException( |
|
||||||
"Required " + getType() + " parameter '" + name + "' with value of '" + |
|
||||||
parameter + "' is not a valid number", ex); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected final void validateRequiredParameter(String name, Object parameter) |
|
||||||
throws ServletRequestBindingException { |
|
||||||
|
|
||||||
if (parameter == null) { |
|
||||||
throw new MissingServletRequestParameterException(name, getType()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected abstract String getType(); |
|
||||||
|
|
||||||
protected abstract T doParse(String parameter) throws NumberFormatException; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private static class IntParser extends ParameterParser<Integer> { |
|
||||||
|
|
||||||
@Override |
|
||||||
protected String getType() { |
|
||||||
return "int"; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected Integer doParse(String s) throws NumberFormatException { |
|
||||||
return Integer.valueOf(s); |
|
||||||
} |
|
||||||
|
|
||||||
public int parseInt(String name, String parameter) throws ServletRequestBindingException { |
|
||||||
return parse(name, parameter); |
|
||||||
} |
|
||||||
|
|
||||||
public int[] parseInts(String name, String[] values) throws ServletRequestBindingException { |
|
||||||
validateRequiredParameter(name, values); |
|
||||||
int[] parameters = new int[values.length]; |
|
||||||
for (int i = 0; i < values.length; i++) { |
|
||||||
parameters[i] = parseInt(name, values[i]); |
|
||||||
} |
|
||||||
return parameters; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private static class LongParser extends ParameterParser<Long> { |
|
||||||
|
|
||||||
@Override |
|
||||||
protected String getType() { |
|
||||||
return "long"; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected Long doParse(String parameter) throws NumberFormatException { |
|
||||||
return Long.valueOf(parameter); |
|
||||||
} |
|
||||||
|
|
||||||
public long parseLong(String name, String parameter) throws ServletRequestBindingException { |
|
||||||
return parse(name, parameter); |
|
||||||
} |
|
||||||
|
|
||||||
public long[] parseLongs(String name, String[] values) throws ServletRequestBindingException { |
|
||||||
validateRequiredParameter(name, values); |
|
||||||
long[] parameters = new long[values.length]; |
|
||||||
for (int i = 0; i < values.length; i++) { |
|
||||||
parameters[i] = parseLong(name, values[i]); |
|
||||||
} |
|
||||||
return parameters; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private static class FloatParser extends ParameterParser<Float> { |
|
||||||
|
|
||||||
@Override |
|
||||||
protected String getType() { |
|
||||||
return "float"; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected Float doParse(String parameter) throws NumberFormatException { |
|
||||||
return Float.valueOf(parameter); |
|
||||||
} |
|
||||||
|
|
||||||
public float parseFloat(String name, String parameter) throws ServletRequestBindingException { |
|
||||||
return parse(name, parameter); |
|
||||||
} |
|
||||||
|
|
||||||
public float[] parseFloats(String name, String[] values) throws ServletRequestBindingException { |
|
||||||
validateRequiredParameter(name, values); |
|
||||||
float[] parameters = new float[values.length]; |
|
||||||
for (int i = 0; i < values.length; i++) { |
|
||||||
parameters[i] = parseFloat(name, values[i]); |
|
||||||
} |
|
||||||
return parameters; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private static class DoubleParser extends ParameterParser<Double> { |
|
||||||
|
|
||||||
@Override |
|
||||||
protected String getType() { |
|
||||||
return "double"; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected Double doParse(String parameter) throws NumberFormatException { |
|
||||||
return Double.valueOf(parameter); |
|
||||||
} |
|
||||||
|
|
||||||
public double parseDouble(String name, String parameter) throws ServletRequestBindingException { |
|
||||||
return parse(name, parameter); |
|
||||||
} |
|
||||||
|
|
||||||
public double[] parseDoubles(String name, String[] values) throws ServletRequestBindingException { |
|
||||||
validateRequiredParameter(name, values); |
|
||||||
double[] parameters = new double[values.length]; |
|
||||||
for (int i = 0; i < values.length; i++) { |
|
||||||
parameters[i] = parseDouble(name, values[i]); |
|
||||||
} |
|
||||||
return parameters; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private static class BooleanParser extends ParameterParser<Boolean> { |
|
||||||
|
|
||||||
@Override |
|
||||||
protected String getType() { |
|
||||||
return "boolean"; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected Boolean doParse(String parameter) throws NumberFormatException { |
|
||||||
return (parameter.equalsIgnoreCase("true") || parameter.equalsIgnoreCase("on") || |
|
||||||
parameter.equalsIgnoreCase("yes") || parameter.equals("1")); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean parseBoolean(String name, String parameter) throws ServletRequestBindingException { |
|
||||||
return parse(name, parameter); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean[] parseBooleans(String name, String[] values) throws ServletRequestBindingException { |
|
||||||
validateRequiredParameter(name, values); |
|
||||||
boolean[] parameters = new boolean[values.length]; |
|
||||||
for (int i = 0; i < values.length; i++) { |
|
||||||
parameters[i] = parseBoolean(name, values[i]); |
|
||||||
} |
|
||||||
return parameters; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private static class StringParser extends ParameterParser<String> { |
|
||||||
|
|
||||||
@Override |
|
||||||
protected String getType() { |
|
||||||
return "string"; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
protected String doParse(String parameter) throws NumberFormatException { |
|
||||||
return parameter; |
|
||||||
} |
|
||||||
|
|
||||||
public String validateRequiredString(String name, String value) throws ServletRequestBindingException { |
|
||||||
validateRequiredParameter(name, value); |
|
||||||
return value; |
|
||||||
} |
|
||||||
|
|
||||||
public String[] validateRequiredStrings(String name, String[] values) throws ServletRequestBindingException { |
|
||||||
validateRequiredParameter(name, values); |
|
||||||
for (String value : values) { |
|
||||||
validateRequiredParameter(name, value); |
|
||||||
} |
|
||||||
return values; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,88 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind; |
|
||||||
|
|
||||||
import java.util.Iterator; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import org.springframework.util.ObjectUtils; |
|
||||||
import org.springframework.util.StringUtils; |
|
||||||
|
|
||||||
/** |
|
||||||
* {@link ServletRequestBindingException} subclass that indicates an unsatisfied |
|
||||||
* parameter condition, as typically expressed using an <code>@RequestMapping</code> |
|
||||||
* annotation at the <code>@Controller</code> type level. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 3.0 |
|
||||||
* @see org.springframework.web.bind.annotation.RequestMapping#params() |
|
||||||
*/ |
|
||||||
public class UnsatisfiedServletRequestParameterException extends ServletRequestBindingException { |
|
||||||
|
|
||||||
private final String[] paramConditions; |
|
||||||
|
|
||||||
private final Map<String, String[]> actualParams; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Create a new UnsatisfiedServletRequestParameterException. |
|
||||||
* @param paramConditions the parameter conditions that have been violated |
|
||||||
* @param actualParams the actual parameter Map associated with the ServletRequest |
|
||||||
*/ |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
public UnsatisfiedServletRequestParameterException(String[] paramConditions, Map actualParams) { |
|
||||||
super(""); |
|
||||||
this.paramConditions = paramConditions; |
|
||||||
this.actualParams = (Map<String, String[]>) actualParams; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public String getMessage() { |
|
||||||
return "Parameter conditions \"" + StringUtils.arrayToDelimitedString(this.paramConditions, ", ") + |
|
||||||
"\" not met for actual request parameters: " + requestParameterMapToString(this.actualParams); |
|
||||||
} |
|
||||||
|
|
||||||
private static String requestParameterMapToString(Map<String, String[]> actualParams) { |
|
||||||
StringBuilder result = new StringBuilder(); |
|
||||||
for (Iterator<Map.Entry<String, String[]>> it = actualParams.entrySet().iterator(); it.hasNext();) { |
|
||||||
Map.Entry<String, String[]> entry = it.next(); |
|
||||||
result.append(entry.getKey()).append('=').append(ObjectUtils.nullSafeToString(entry.getValue())); |
|
||||||
if (it.hasNext()) { |
|
||||||
result.append(", "); |
|
||||||
} |
|
||||||
} |
|
||||||
return result.toString(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the parameter conditions that have been violated. |
|
||||||
* @see org.springframework.web.bind.annotation.RequestMapping#params() |
|
||||||
*/ |
|
||||||
public final String[] getParamConditions() { |
|
||||||
return this.paramConditions; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the actual parameter Map associated with the ServletRequest. |
|
||||||
* @see javax.servlet.ServletRequest#getParameterMap() |
|
||||||
*/ |
|
||||||
public final Map<String, String[]> getActualParams() { |
|
||||||
return this.actualParams; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,290 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.bind; |
|
||||||
|
|
||||||
import java.lang.reflect.Array; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import org.springframework.beans.MutablePropertyValues; |
|
||||||
import org.springframework.beans.PropertyValue; |
|
||||||
import org.springframework.validation.DataBinder; |
|
||||||
import org.springframework.web.multipart.MultipartFile; |
|
||||||
|
|
||||||
/** |
|
||||||
* Special {@link DataBinder} for data binding from web request parameters |
|
||||||
* to JavaBean objects. Designed for web environments, but not dependent on |
|
||||||
* the Servlet API; serves as base class for more specific DataBinder variants, |
|
||||||
* such as {@link org.springframework.web.bind.ServletRequestDataBinder}. |
|
||||||
* |
|
||||||
* <p>Includes support for field markers which address a common problem with |
|
||||||
* HTML checkboxes and select options: detecting that a field was part of |
|
||||||
* the form, but did not generate a request parameter because it was empty. |
|
||||||
* A field marker allows to detect that state and reset the corresponding |
|
||||||
* bean property accordingly. Default values, for parameters that are otherwise |
|
||||||
* not present, can specify a value for the field other then empty. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @author Scott Andrews |
|
||||||
* @since 1.2 |
|
||||||
* @see #registerCustomEditor |
|
||||||
* @see #setAllowedFields |
|
||||||
* @see #setRequiredFields |
|
||||||
* @see #setFieldMarkerPrefix |
|
||||||
* @see #setFieldDefaultPrefix |
|
||||||
* @see ServletRequestDataBinder |
|
||||||
*/ |
|
||||||
public class WebDataBinder extends DataBinder { |
|
||||||
|
|
||||||
/** |
|
||||||
* Default prefix that field marker parameters start with, followed by the field |
|
||||||
* name: e.g. "_subscribeToNewsletter" for a field "subscribeToNewsletter". |
|
||||||
* <p>Such a marker parameter indicates that the field was visible, that is, |
|
||||||
* existed in the form that caused the submission. If no corresponding field |
|
||||||
* value parameter was found, the field will be reset. The value of the field |
|
||||||
* marker parameter does not matter in this case; an arbitrary value can be used. |
|
||||||
* This is particularly useful for HTML checkboxes and select options. |
|
||||||
* @see #setFieldMarkerPrefix |
|
||||||
*/ |
|
||||||
public static final String DEFAULT_FIELD_MARKER_PREFIX = "_"; |
|
||||||
|
|
||||||
/** |
|
||||||
* Default prefix that field default parameters start with, followed by the field |
|
||||||
* name: e.g. "!subscribeToNewsletter" for a field "subscribeToNewsletter". |
|
||||||
* <p>Default parameters differ from field markers in that they provide a default |
|
||||||
* value instead of an empty value. |
|
||||||
* @see #setFieldDefaultPrefix |
|
||||||
*/ |
|
||||||
public static final String DEFAULT_FIELD_DEFAULT_PREFIX = "!"; |
|
||||||
|
|
||||||
private String fieldMarkerPrefix = DEFAULT_FIELD_MARKER_PREFIX; |
|
||||||
|
|
||||||
private String fieldDefaultPrefix = DEFAULT_FIELD_DEFAULT_PREFIX; |
|
||||||
|
|
||||||
private boolean bindEmptyMultipartFiles = true; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Create a new WebDataBinder instance, with default object name. |
|
||||||
* @param target the target object to bind onto (or <code>null</code> |
|
||||||
* if the binder is just used to convert a plain parameter value) |
|
||||||
* @see #DEFAULT_OBJECT_NAME |
|
||||||
*/ |
|
||||||
public WebDataBinder(Object target) { |
|
||||||
super(target); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a new WebDataBinder instance. |
|
||||||
* @param target the target object to bind onto (or <code>null</code> |
|
||||||
* if the binder is just used to convert a plain parameter value) |
|
||||||
* @param objectName the name of the target object |
|
||||||
*/ |
|
||||||
public WebDataBinder(Object target, String objectName) { |
|
||||||
super(target, objectName); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Specify a prefix that can be used for parameters that mark potentially |
|
||||||
* empty fields, having "prefix + field" as name. Such a marker parameter is |
|
||||||
* checked by existence: You can send any value for it, for example "visible". |
|
||||||
* This is particularly useful for HTML checkboxes and select options. |
|
||||||
* <p>Default is "_", for "_FIELD" parameters (e.g. "_subscribeToNewsletter"). |
|
||||||
* Set this to null if you want to turn off the empty field check completely. |
|
||||||
* <p>HTML checkboxes only send a value when they're checked, so it is not |
|
||||||
* possible to detect that a formerly checked box has just been unchecked, |
|
||||||
* at least not with standard HTML means. |
|
||||||
* <p>One way to address this is to look for a checkbox parameter value if |
|
||||||
* you know that the checkbox has been visible in the form, resetting the |
|
||||||
* checkbox if no value found. In Spring web MVC, this typically happens |
|
||||||
* in a custom <code>onBind</code> implementation. |
|
||||||
* <p>This auto-reset mechanism addresses this deficiency, provided |
|
||||||
* that a marker parameter is sent for each checkbox field, like |
|
||||||
* "_subscribeToNewsletter" for a "subscribeToNewsletter" field. |
|
||||||
* As the marker parameter is sent in any case, the data binder can |
|
||||||
* detect an empty field and automatically reset its value. |
|
||||||
* @see #DEFAULT_FIELD_MARKER_PREFIX |
|
||||||
* @see org.springframework.web.servlet.mvc.BaseCommandController#onBind |
|
||||||
*/ |
|
||||||
public void setFieldMarkerPrefix(String fieldMarkerPrefix) { |
|
||||||
this.fieldMarkerPrefix = fieldMarkerPrefix; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the prefix for parameters that mark potentially empty fields. |
|
||||||
*/ |
|
||||||
public String getFieldMarkerPrefix() { |
|
||||||
return this.fieldMarkerPrefix; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Specify a prefix that can be used for parameters that indicate default |
|
||||||
* value fields, having "prefix + field" as name. The value of the default |
|
||||||
* field is used when the field is not provided. |
|
||||||
* <p>Default is "!", for "!FIELD" parameters (e.g. "!subscribeToNewsletter"). |
|
||||||
* Set this to null if you want to turn off the field defaults completely. |
|
||||||
* <p>HTML checkboxes only send a value when they're checked, so it is not |
|
||||||
* possible to detect that a formerly checked box has just been unchecked, |
|
||||||
* at least not with standard HTML means. A default field is especially |
|
||||||
* useful when a checkbox represents a non-boolean value. |
|
||||||
* <p>The presence of a default parameter preempts the behavior of a field |
|
||||||
* marker for the given field. |
|
||||||
* @see #DEFAULT_FIELD_DEFAULT_PREFIX |
|
||||||
* @see org.springframework.web.servlet.mvc.BaseCommandController#onBind |
|
||||||
*/ |
|
||||||
public void setFieldDefaultPrefix(String fieldDefaultPrefix) { |
|
||||||
this.fieldDefaultPrefix = fieldDefaultPrefix; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the prefix for parameters that mark default fields. |
|
||||||
*/ |
|
||||||
public String getFieldDefaultPrefix() { |
|
||||||
return this.fieldDefaultPrefix; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Set whether to bind empty MultipartFile parameters. Default is "true". |
|
||||||
* <p>Turn this off if you want to keep an already bound MultipartFile |
|
||||||
* when the user resubmits the form without choosing a different file. |
|
||||||
* Else, the already bound MultipartFile will be replaced by an empty |
|
||||||
* MultipartFile holder. |
|
||||||
* @see org.springframework.web.multipart.MultipartFile |
|
||||||
*/ |
|
||||||
public void setBindEmptyMultipartFiles(boolean bindEmptyMultipartFiles) { |
|
||||||
this.bindEmptyMultipartFiles = bindEmptyMultipartFiles; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return whether to bind empty MultipartFile parameters. |
|
||||||
*/ |
|
||||||
public boolean isBindEmptyMultipartFiles() { |
|
||||||
return this.bindEmptyMultipartFiles; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* This implementation performs a field default and marker check |
|
||||||
* before delegating to the superclass binding process. |
|
||||||
* @see #checkFieldDefaults |
|
||||||
* @see #checkFieldMarkers |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
protected void doBind(MutablePropertyValues mpvs) { |
|
||||||
checkFieldDefaults(mpvs); |
|
||||||
checkFieldMarkers(mpvs); |
|
||||||
super.doBind(mpvs); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Check the given property values for field defaults, |
|
||||||
* i.e. for fields that start with the field default prefix. |
|
||||||
* <p>The existence of a field defaults indicates that the specified |
|
||||||
* value should be used if the field is otherwise not present. |
|
||||||
* @param mpvs the property values to be bound (can be modified) |
|
||||||
* @see #getFieldDefaultPrefix |
|
||||||
*/ |
|
||||||
protected void checkFieldDefaults(MutablePropertyValues mpvs) { |
|
||||||
if (getFieldDefaultPrefix() != null) { |
|
||||||
String fieldDefaultPrefix = getFieldDefaultPrefix(); |
|
||||||
PropertyValue[] pvArray = mpvs.getPropertyValues(); |
|
||||||
for (PropertyValue pv : pvArray) { |
|
||||||
if (pv.getName().startsWith(fieldDefaultPrefix)) { |
|
||||||
String field = pv.getName().substring(fieldDefaultPrefix.length()); |
|
||||||
if (getPropertyAccessor().isWritableProperty(field) && !mpvs.contains(field)) { |
|
||||||
mpvs.addPropertyValue(field, pv.getValue()); |
|
||||||
} |
|
||||||
mpvs.removePropertyValue(pv); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Check the given property values for field markers, |
|
||||||
* i.e. for fields that start with the field marker prefix. |
|
||||||
* <p>The existence of a field marker indicates that the specified |
|
||||||
* field existed in the form. If the property values do not contain |
|
||||||
* a corresponding field value, the field will be considered as empty |
|
||||||
* and will be reset appropriately. |
|
||||||
* @param mpvs the property values to be bound (can be modified) |
|
||||||
* @see #getFieldMarkerPrefix |
|
||||||
* @see #getEmptyValue(String, Class) |
|
||||||
*/ |
|
||||||
protected void checkFieldMarkers(MutablePropertyValues mpvs) { |
|
||||||
if (getFieldMarkerPrefix() != null) { |
|
||||||
String fieldMarkerPrefix = getFieldMarkerPrefix(); |
|
||||||
PropertyValue[] pvArray = mpvs.getPropertyValues(); |
|
||||||
for (PropertyValue pv : pvArray) { |
|
||||||
if (pv.getName().startsWith(fieldMarkerPrefix)) { |
|
||||||
String field = pv.getName().substring(fieldMarkerPrefix.length()); |
|
||||||
if (getPropertyAccessor().isWritableProperty(field) && !mpvs.contains(field)) { |
|
||||||
Class fieldType = getPropertyAccessor().getPropertyType(field); |
|
||||||
mpvs.addPropertyValue(field, getEmptyValue(field, fieldType)); |
|
||||||
} |
|
||||||
mpvs.removePropertyValue(pv); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Determine an empty value for the specified field. |
|
||||||
* <p>Default implementation returns <code>Boolean.FALSE</code> |
|
||||||
* for boolean fields and an empty array of array types. |
|
||||||
* Else, <code>null</code> is used as default. |
|
||||||
* @param field the name of the field |
|
||||||
* @param fieldType the type of the field |
|
||||||
* @return the empty value (for most fields: null) |
|
||||||
*/ |
|
||||||
protected Object getEmptyValue(String field, Class fieldType) { |
|
||||||
if (fieldType != null && boolean.class.equals(fieldType) || Boolean.class.equals(fieldType)) { |
|
||||||
// Special handling of boolean property.
|
|
||||||
return Boolean.FALSE; |
|
||||||
} |
|
||||||
else if (fieldType != null && fieldType.isArray()) { |
|
||||||
// Special handling of array property.
|
|
||||||
return Array.newInstance(fieldType.getComponentType(), 0); |
|
||||||
} |
|
||||||
else { |
|
||||||
// Default value: try null.
|
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Bind the multipart files contained in the given request, if any |
|
||||||
* (in case of a multipart request). |
|
||||||
* <p>Multipart files will only be added to the property values if they |
|
||||||
* are not empty or if we're configured to bind empty multipart files too. |
|
||||||
* @param multipartFiles Map of field name String to MultipartFile object |
|
||||||
* @param mpvs the property values to be bound (can be modified) |
|
||||||
* @see org.springframework.web.multipart.MultipartFile |
|
||||||
* @see #setBindEmptyMultipartFiles |
|
||||||
*/ |
|
||||||
protected void bindMultipartFiles(Map<String, MultipartFile> multipartFiles, MutablePropertyValues mpvs) { |
|
||||||
for (Map.Entry<String, MultipartFile> entry : multipartFiles.entrySet()) { |
|
||||||
String key = entry.getKey(); |
|
||||||
MultipartFile value = entry.getValue(); |
|
||||||
if (isBindEmptyMultipartFiles() || !value.isEmpty()) { |
|
||||||
mpvs.addPropertyValue(key, value); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,67 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind.annotation; |
|
||||||
|
|
||||||
import java.lang.annotation.Documented; |
|
||||||
import java.lang.annotation.ElementType; |
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
import java.lang.annotation.Target; |
|
||||||
|
|
||||||
/** |
|
||||||
* Annotation which indicates that a method parameter should be bound to an HTTP cookie. |
|
||||||
* Supported for annotated handler methods in Servlet and Portlet environments. |
|
||||||
* |
|
||||||
* <p>The method parameter may be declared as type {@link javax.servlet.http.Cookie} |
|
||||||
* or as cookie value type (String, int, etc). |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 3.0 |
|
||||||
* @see RequestMapping |
|
||||||
* @see RequestParam |
|
||||||
* @see RequestHeader |
|
||||||
* @see org.springframework.web.bind.annotation.RequestMapping |
|
||||||
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter |
|
||||||
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter |
|
||||||
*/ |
|
||||||
@Target(ElementType.PARAMETER) |
|
||||||
@Retention(RetentionPolicy.RUNTIME) |
|
||||||
@Documented |
|
||||||
public @interface CookieValue { |
|
||||||
|
|
||||||
/** |
|
||||||
* The name of the cookie to bind to. |
|
||||||
*/ |
|
||||||
String value() default ""; |
|
||||||
|
|
||||||
/** |
|
||||||
* Whether the header is required. |
|
||||||
* <p>Default is <code>true</code>, leading to an exception thrown in case |
|
||||||
* of the header missing in the request. Switch this to <code>false</code> |
|
||||||
* if you prefer a <code>null</value> in case of the header missing. |
|
||||||
* <p>Alternatively, provide a {@link #defaultValue() defaultValue}, |
|
||||||
* which implicitely sets this flag to <code>false</code>. |
|
||||||
*/ |
|
||||||
boolean required() default true; |
|
||||||
|
|
||||||
/** |
|
||||||
* The default value to use as a fallback. Supplying a default value implicitely |
|
||||||
* sets {@link #required()} to false. |
|
||||||
*/ |
|
||||||
String defaultValue() default ""; |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,113 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind.annotation; |
|
||||||
|
|
||||||
import java.lang.annotation.Documented; |
|
||||||
import java.lang.annotation.ElementType; |
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
import java.lang.annotation.Target; |
|
||||||
|
|
||||||
/** |
|
||||||
* Annotation for handling exceptions in specific handler classes and/or |
|
||||||
* handler methods. Provides consistent style between Servlet and Portlet |
|
||||||
* environments, with the semantics adapting to the concrete environment. |
|
||||||
* |
|
||||||
* <p>Handler methods which are annotated with this annotation are allowed |
|
||||||
* to have very flexible signatures. They may have arguments of the following |
|
||||||
* types, in arbitrary order: |
|
||||||
* <ul> |
|
||||||
* <li>Request and/or response objects (Servlet API or Portlet API). |
|
||||||
* You may choose any specific request/response type, e.g. |
|
||||||
* {@link javax.servlet.ServletRequest} / {@link javax.servlet.http.HttpServletRequest} |
|
||||||
* or {@link javax.portlet.PortletRequest} / {@link javax.portlet.ActionRequest} / |
|
||||||
* {@link javax.portlet.RenderRequest}. Note that in the Portlet case, |
|
||||||
* an explicitly declared action/render argument is also used for mapping |
|
||||||
* specific request types onto a handler method (in case of no other |
|
||||||
* information given that differentiates between action and render requests). |
|
||||||
* <li>Session object (Servlet API or Portlet API): either |
|
||||||
* {@link javax.servlet.http.HttpSession} or {@link javax.portlet.PortletSession}. |
|
||||||
* An argument of this type will enforce the presence of a corresponding session. |
|
||||||
* As a consequence, such an argument will never be <code>null</code>. |
|
||||||
* <i>Note that session access may not be thread-safe, in particular in a |
|
||||||
* Servlet environment: Consider switching the |
|
||||||
* {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#setSynchronizeOnSession "synchronizeOnSession"} |
|
||||||
* flag to "true" if multiple requests are allowed to access a session concurrently.</i> |
|
||||||
* <li>{@link org.springframework.web.context.request.WebRequest} or |
|
||||||
* {@link org.springframework.web.context.request.NativeWebRequest}. |
|
||||||
* Allows for generic request parameter access as well as request/session |
|
||||||
* attribute access, without ties to the native Servlet/Portlet API. |
|
||||||
* <li>{@link java.util.Locale} for the current request locale |
|
||||||
* (determined by the most specific locale resolver available, |
|
||||||
* i.e. the configured {@link org.springframework.web.servlet.LocaleResolver} |
|
||||||
* in a Servlet environment and the portal locale in a Portlet environment). |
|
||||||
* <li>{@link java.io.InputStream} / {@link java.io.Reader} for access |
|
||||||
* to the request's content. This will be the raw InputStream/Reader as |
|
||||||
* exposed by the Servlet/Portlet API. |
|
||||||
* <li>{@link java.io.OutputStream} / {@link java.io.Writer} for generating |
|
||||||
* the response's content. This will be the raw OutputStream/Writer as |
|
||||||
* exposed by the Servlet/Portlet API. |
|
||||||
* </ul> |
|
||||||
* |
|
||||||
* <p>The following return types are supported for handler methods: |
|
||||||
* <ul> |
|
||||||
* <li>A <code>ModelAndView</code> object (Servlet MVC or Portlet MVC). |
|
||||||
* <li>A {@link org.springframework.ui.Model Model} object, with the view name |
|
||||||
* implicitly determined through a {@link org.springframework.web.servlet.RequestToViewNameTranslator}. |
|
||||||
* <li>A {@link java.util.Map} object for exposing a model, |
|
||||||
* with the view name implicitly determined through a |
|
||||||
* {@link org.springframework.web.servlet.RequestToViewNameTranslator}. |
|
||||||
* <li>A {@link org.springframework.web.servlet.View} object. |
|
||||||
* <li>A {@link java.lang.String} value which is interpreted as view name. |
|
||||||
* <li><code>void</code> if the method handles the response itself (by |
|
||||||
* writing the response content directly, declaring an argument of type |
|
||||||
* {@link javax.servlet.ServletResponse} / {@link javax.servlet.http.HttpServletResponse} |
|
||||||
* / {@link javax.portlet.RenderResponse} for that purpose) |
|
||||||
* or if the view name is supposed to be implicitly determined through a |
|
||||||
* {@link org.springframework.web.servlet.RequestToViewNameTranslator} |
|
||||||
* (not declaring a response argument in the handler method signature; |
|
||||||
* only applicable in a Servlet environment). |
|
||||||
* </ul> |
|
||||||
* |
|
||||||
* <p><b>NOTE: <code>@RequestMapping</code> will only be processed if a |
|
||||||
* corresponding <code>HandlerMapping</code> (for type level annotations) |
|
||||||
* and/or <code>HandlerAdapter</code> (for method level annotations) is |
|
||||||
* present in the dispatcher.</b> This is the case by default in both |
|
||||||
* <code>DispatcherServlet</code> and <code>DispatcherPortlet</code>. |
|
||||||
* However, if you are defining custom <code>HandlerMappings</code> or |
|
||||||
* <code>HandlerAdapters</code>, then you need to make sure that a |
|
||||||
* corresponding custom <code>DefaultAnnotationHandlerMapping</code> |
|
||||||
* and/or <code>AnnotationMethodHandlerAdapter</code> is defined as well |
|
||||||
* - provided that you intend to use <code>@RequestMapping</code>. |
|
||||||
* |
|
||||||
* @author Arjen Poutsma |
|
||||||
* @see org.springframework.web.context.request.WebRequest |
|
||||||
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver |
|
||||||
* @since 3.0 |
|
||||||
*/ |
|
||||||
@Target(ElementType.METHOD) |
|
||||||
@Retention(RetentionPolicy.RUNTIME) |
|
||||||
@Documented |
|
||||||
public @interface ExceptionHandler { |
|
||||||
|
|
||||||
/** |
|
||||||
* Exceptions handled by the annotation method. If empty, will default to any exceptions listed in the method |
|
||||||
* argument list. |
|
||||||
*/ |
|
||||||
Class<? extends Throwable>[] value() default {}; |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,61 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2007 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.bind.annotation; |
|
||||||
|
|
||||||
import java.lang.annotation.Documented; |
|
||||||
import java.lang.annotation.ElementType; |
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
import java.lang.annotation.Target; |
|
||||||
|
|
||||||
/** |
|
||||||
* Annotation that identifies methods which initialize the |
|
||||||
* {@link org.springframework.web.bind.WebDataBinder} which |
|
||||||
* will be used for populating command and form object arguments |
|
||||||
* of annotated handler methods. |
|
||||||
* |
|
||||||
* <p>Such init-binder methods support all arguments that {@link RequestMapping} |
|
||||||
* supports, except for command/form objects and corresponding validation result |
|
||||||
* objects. Init-binder methods must not have a return value; they are usually |
|
||||||
* declared as <code>void</code>. |
|
||||||
* |
|
||||||
* <p>Typical arguments are {@link org.springframework.web.bind.WebDataBinder} |
|
||||||
* in combination with {@link org.springframework.web.context.request.WebRequest} |
|
||||||
* or {@link java.util.Locale}, allowing to register context-specific editors. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5 |
|
||||||
* @see org.springframework.web.bind.WebDataBinder |
|
||||||
* @see org.springframework.web.context.request.WebRequest |
|
||||||
*/ |
|
||||||
@Target({ElementType.METHOD}) |
|
||||||
@Retention(RetentionPolicy.RUNTIME) |
|
||||||
@Documented |
|
||||||
public @interface InitBinder { |
|
||||||
|
|
||||||
/** |
|
||||||
* The names of command/form attributes and/or request parameters |
|
||||||
* that this init-binder method is supposed to apply to. |
|
||||||
* <p>Default is to apply to all command/form attributes and all request parameters |
|
||||||
* processed by the annotated handler class. Specifying model attribute names or |
|
||||||
* request parameter names here restricts the init-binder method to those specific |
|
||||||
* attributes/parameters, with different init-binder methods typically applying to |
|
||||||
* different groups of attributes or parameters. |
|
||||||
*/ |
|
||||||
String[] value() default {}; |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,35 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind.annotation; |
|
||||||
|
|
||||||
import java.lang.annotation.ElementType; |
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
import java.lang.annotation.Target; |
|
||||||
|
|
||||||
/** |
|
||||||
* Meta annotation that indicates a web mapping annotation. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 3.0 |
|
||||||
* @see RequestMapping |
|
||||||
*/ |
|
||||||
@Target({ElementType.ANNOTATION_TYPE}) |
|
||||||
@Retention(RetentionPolicy.RUNTIME) |
|
||||||
public @interface Mapping { |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,59 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2007 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.bind.annotation; |
|
||||||
|
|
||||||
import java.lang.annotation.Documented; |
|
||||||
import java.lang.annotation.ElementType; |
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
import java.lang.annotation.Target; |
|
||||||
|
|
||||||
/** |
|
||||||
* Annotation that binds a method parameter or method return value |
|
||||||
* to a named model attribute, exposed to a web view. Supported |
|
||||||
* for {@link RequestMapping} annotated handler classes. |
|
||||||
* |
|
||||||
* <p>Can be used to expose command objects to a web view, using |
|
||||||
* specific attribute names, through annotating corresponding |
|
||||||
* parameters of a {@link RequestMapping} annotated handler method). |
|
||||||
* |
|
||||||
* <p>Can also be used to expose reference data to a web view |
|
||||||
* through annotating accessor methods in a controller class which |
|
||||||
* is based on {@link RequestMapping} annotated handler methods, |
|
||||||
* with such accessor methods allowed to have any arguments that |
|
||||||
* {@link RequestMapping} supports for handler methods, returning |
|
||||||
* the model attribute value to expose. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5 |
|
||||||
*/ |
|
||||||
@Target({ElementType.PARAMETER, ElementType.METHOD}) |
|
||||||
@Retention(RetentionPolicy.RUNTIME) |
|
||||||
@Documented |
|
||||||
public @interface ModelAttribute { |
|
||||||
|
|
||||||
/** |
|
||||||
* The name of the model attribute to bind to. |
|
||||||
* <p>The default model attribute name is inferred from the declared |
|
||||||
* attribute type (i.e. the method parameter type or method return type), |
|
||||||
* based on the non-qualified class name: |
|
||||||
* e.g. "orderAddress" for class "mypackage.OrderAddress", |
|
||||||
* or "orderAddressList" for "List<mypackage.OrderAddress>". |
|
||||||
*/ |
|
||||||
String value() default ""; |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,26 +0,0 @@ |
|||||||
package org.springframework.web.bind.annotation; |
|
||||||
|
|
||||||
import java.lang.annotation.Documented; |
|
||||||
import java.lang.annotation.ElementType; |
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
import java.lang.annotation.Target; |
|
||||||
|
|
||||||
/** |
|
||||||
* Annotation which indicates that a method parameter should be bound to a URI template variable. Supported for {@link |
|
||||||
* RequestMapping} annotated handler methods in Servlet environments. |
|
||||||
* |
|
||||||
* @author Arjen Poutsma |
|
||||||
* @see RequestMapping |
|
||||||
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter |
|
||||||
* @since 3.0 |
|
||||||
*/ |
|
||||||
@Target(ElementType.PARAMETER) |
|
||||||
@Retention(RetentionPolicy.RUNTIME) |
|
||||||
@Documented |
|
||||||
public @interface PathVariable { |
|
||||||
|
|
||||||
/** The URI template variable to bind to. */ |
|
||||||
String value() default ""; |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,40 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind.annotation; |
|
||||||
|
|
||||||
import java.lang.annotation.Documented; |
|
||||||
import java.lang.annotation.ElementType; |
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
import java.lang.annotation.Target; |
|
||||||
|
|
||||||
/** |
|
||||||
* Annotation which indicates that a method parameter should be bound to the web request body. Supported for annotated |
|
||||||
* handler methods in Servlet environments. |
|
||||||
* |
|
||||||
* @author Arjen Poutsma |
|
||||||
* @see RequestHeader |
|
||||||
* @see ResponseBody |
|
||||||
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter |
|
||||||
* @since 3.0 |
|
||||||
*/ |
|
||||||
@Target(ElementType.PARAMETER) |
|
||||||
@Retention(RetentionPolicy.RUNTIME) |
|
||||||
@Documented |
|
||||||
public @interface RequestBody { |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,63 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind.annotation; |
|
||||||
|
|
||||||
import java.lang.annotation.Documented; |
|
||||||
import java.lang.annotation.ElementType; |
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
import java.lang.annotation.Target; |
|
||||||
|
|
||||||
/** |
|
||||||
* Annotation which indicates that a method parameter should be bound to a web request header. |
|
||||||
* Supported for annotated handler methods in Servlet and Portlet environments. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 3.0 |
|
||||||
* @see RequestMapping |
|
||||||
* @see RequestParam |
|
||||||
* @see CookieValue |
|
||||||
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter |
|
||||||
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter |
|
||||||
*/ |
|
||||||
@Target(ElementType.PARAMETER) |
|
||||||
@Retention(RetentionPolicy.RUNTIME) |
|
||||||
@Documented |
|
||||||
public @interface RequestHeader { |
|
||||||
|
|
||||||
/** |
|
||||||
* The name of the request header to bind to. |
|
||||||
*/ |
|
||||||
String value() default ""; |
|
||||||
|
|
||||||
/** |
|
||||||
* Whether the header is required. |
|
||||||
* <p>Default is <code>true</code>, leading to an exception thrown in case |
|
||||||
* of the header missing in the request. Switch this to <code>false</code> |
|
||||||
* if you prefer a <code>null</value> in case of the header missing. |
|
||||||
* <p>Alternatively, provide a {@link #defaultValue() defaultValue}, |
|
||||||
* which implicitely sets this flag to <code>false</code>. |
|
||||||
*/ |
|
||||||
boolean required() default true; |
|
||||||
|
|
||||||
/** |
|
||||||
* The default value to use as a fallback. Supplying a default value implicitely |
|
||||||
* sets {@link #required()} to false. |
|
||||||
*/ |
|
||||||
String defaultValue() default ""; |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,262 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind.annotation; |
|
||||||
|
|
||||||
import java.lang.annotation.Documented; |
|
||||||
import java.lang.annotation.ElementType; |
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
import java.lang.annotation.Target; |
|
||||||
|
|
||||||
/** |
|
||||||
* Annotation for mapping web requests onto specific handler classes and/or |
|
||||||
* handler methods. Provides consistent style between Servlet and Portlet |
|
||||||
* environments, with the semantics adapting to the concrete environment. |
|
||||||
* |
|
||||||
* <p><b>NOTE:</b> Method-level mappings are only allowed to narrow the mapping |
|
||||||
* expressed at the class level (if any). HTTP paths / portlet modes need to |
|
||||||
* uniquely map onto specific handler beans, with any given path / mode only |
|
||||||
* allowed to be mapped onto one specific handler bean (not spread across |
|
||||||
* multiple handler beans). It is strongly recommended to co-locate related |
|
||||||
* handler methods into the same bean. |
|
||||||
* |
|
||||||
* <p>Handler methods which are annotated with this annotation are allowed |
|
||||||
* to have very flexible signatures. They may have arguments of the following |
|
||||||
* types, in arbitrary order (except for validation results, which need to |
|
||||||
* follow right after the corresponding command object, if desired): |
|
||||||
* <ul> |
|
||||||
* <li>Request and/or response objects (Servlet API or Portlet API). |
|
||||||
* You may choose any specific request/response type, e.g. |
|
||||||
* {@link javax.servlet.ServletRequest} / {@link javax.servlet.http.HttpServletRequest} |
|
||||||
* or {@link javax.portlet.PortletRequest} / {@link javax.portlet.ActionRequest} / |
|
||||||
* {@link javax.portlet.RenderRequest}. Note that in the Portlet case, |
|
||||||
* an explicitly declared action/render argument is also used for mapping |
|
||||||
* specific request types onto a handler method (in case of no other |
|
||||||
* information given that differentiates between action and render requests). |
|
||||||
* <li>Session object (Servlet API or Portlet API): either |
|
||||||
* {@link javax.servlet.http.HttpSession} or {@link javax.portlet.PortletSession}. |
|
||||||
* An argument of this type will enforce the presence of a corresponding session. |
|
||||||
* As a consequence, such an argument will never be <code>null</code>. |
|
||||||
* <i>Note that session access may not be thread-safe, in particular in a |
|
||||||
* Servlet environment: Consider switching the |
|
||||||
* {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#setSynchronizeOnSession "synchronizeOnSession"} |
|
||||||
* flag to "true" if multiple requests are allowed to access a session concurrently.</i> |
|
||||||
* <li>{@link org.springframework.web.context.request.WebRequest} or |
|
||||||
* {@link org.springframework.web.context.request.NativeWebRequest}. |
|
||||||
* Allows for generic request parameter access as well as request/session |
|
||||||
* attribute access, without ties to the native Servlet/Portlet API. |
|
||||||
* <li>{@link java.util.Locale} for the current request locale |
|
||||||
* (determined by the most specific locale resolver available, |
|
||||||
* i.e. the configured {@link org.springframework.web.servlet.LocaleResolver} |
|
||||||
* in a Servlet environment and the portal locale in a Portlet environment). |
|
||||||
* <li>{@link java.io.InputStream} / {@link java.io.Reader} for access |
|
||||||
* to the request's content. This will be the raw InputStream/Reader as |
|
||||||
* exposed by the Servlet/Portlet API. |
|
||||||
* <li>{@link java.io.OutputStream} / {@link java.io.Writer} for generating |
|
||||||
* the response's content. This will be the raw OutputStream/Writer as |
|
||||||
* exposed by the Servlet/Portlet API. |
|
||||||
* <li>{@link PathVariable @PathVariable} annotated parameters for access to |
|
||||||
* URI template values (i.e. /hotels/{hotel}). Variable values will be |
|
||||||
* converted to the declared method argument type. |
|
||||||
* <li>{@link RequestParam @RequestParam} annotated parameters for access to |
|
||||||
* specific Servlet/Portlet request parameters. Parameter values will be |
|
||||||
* converted to the declared method argument type. |
|
||||||
* <li>{@link RequestHeader @RequestHeader} annotated parameters for access to |
|
||||||
* specific Servlet/Portlet request HTTP headers. Parameter values will be |
|
||||||
* converted to the declared method argument type. |
|
||||||
* <li>{@link RequestBody @RequestBody} annotated parameters for access to |
|
||||||
* the Servlet request HTTP contents. Parameter values will be |
|
||||||
* converted to the declared method argument type using |
|
||||||
* {@linkplain org.springframework.http.converter.HttpMessageConverter message |
|
||||||
* converters}. |
|
||||||
* <li>{@link java.util.Map} / {@link org.springframework.ui.Model} / |
|
||||||
* {@link org.springframework.ui.ModelMap} for enriching the implicit model |
|
||||||
* that will be exposed to the web view. |
|
||||||
* <li>Command/form objects to bind parameters to: as bean properties or fields, |
|
||||||
* with customizable type conversion, depending on {@link InitBinder} methods |
|
||||||
* and/or the HandlerAdapter configuration - see the "webBindingInitializer" |
|
||||||
* property on AnnotationMethodHandlerAdapter. |
|
||||||
* Such command objects along with their validation results will be exposed |
|
||||||
* as model attributes, by default using the non-qualified command class name |
|
||||||
* in property notation (e.g. "orderAddress" for type "mypackage.OrderAddress"). |
|
||||||
* Specify a parameter-level {@link ModelAttribute} annotation for declaring |
|
||||||
* a specific model attribute name. |
|
||||||
* <li>{@link org.springframework.validation.Errors} / |
|
||||||
* {@link org.springframework.validation.BindingResult} validation results |
|
||||||
* for a preceding command/form object (the immediate preceding argument). |
|
||||||
* <li>{@link org.springframework.web.bind.support.SessionStatus} status handle |
|
||||||
* for marking form processing as complete (triggering the cleanup of session |
|
||||||
* attributes that have been indicated by the {@link SessionAttributes} annotation |
|
||||||
* at the handler type level). |
|
||||||
* </ul> |
|
||||||
* |
|
||||||
* <p>The following return types are supported for handler methods: |
|
||||||
* <ul> |
|
||||||
* <li>A <code>ModelAndView</code> object (Servlet MVC or Portlet MVC), |
|
||||||
* with the model implicitly enriched with command objects and the results |
|
||||||
* of {@link ModelAttribute} annotated reference data accessor methods. |
|
||||||
* <li>A {@link org.springframework.ui.Model Model} object, with the view name |
|
||||||
* implicitly determined through a {@link org.springframework.web.servlet.RequestToViewNameTranslator} |
|
||||||
* and the model implicitly enriched with command objects and the results |
|
||||||
* of {@link ModelAttribute} annotated reference data accessor methods. |
|
||||||
* <li>A {@link java.util.Map} object for exposing a model, |
|
||||||
* with the view name implicitly determined through a |
|
||||||
* {@link org.springframework.web.servlet.RequestToViewNameTranslator} |
|
||||||
* and the model implicitly enriched with command objects and the results |
|
||||||
* of {@link ModelAttribute} annotated reference data accessor methods. |
|
||||||
* <li>A {@link org.springframework.web.servlet.View} object, with the |
|
||||||
* model implicitly determined through command objects and |
|
||||||
* {@link ModelAttribute} annotated reference data accessor methods. |
|
||||||
* The handler method may also programmatically enrich the model by |
|
||||||
* declaring a {@link org.springframework.ui.Model} argument (see above). |
|
||||||
* <li>A {@link java.lang.String} value which is interpreted as view name, |
|
||||||
* with the model implicitly determined through command objects and |
|
||||||
* {@link ModelAttribute} annotated reference data accessor methods. |
|
||||||
* The handler method may also programmatically enrich the model by |
|
||||||
* declaring a {@link org.springframework.ui.ModelMap} argument |
|
||||||
* (see above). |
|
||||||
* <li><code>void</code> if the method handles the response itself (by |
|
||||||
* writing the response content directly, declaring an argument of type |
|
||||||
* {@link javax.servlet.ServletResponse} / {@link javax.servlet.http.HttpServletResponse} |
|
||||||
* / {@link javax.portlet.RenderResponse} for that purpose) |
|
||||||
* or if the view name is supposed to be implicitly determined through a |
|
||||||
* {@link org.springframework.web.servlet.RequestToViewNameTranslator} |
|
||||||
* (not declaring a response argument in the handler method signature; |
|
||||||
* only applicable in a Servlet environment). |
|
||||||
* <li>Any other return type will be considered as single model attribute |
|
||||||
* to be exposed to the view, using the attribute name specified through |
|
||||||
* {@link ModelAttribute} at the method level (or the default attribute name |
|
||||||
* based on the return type's class name otherwise). The model will be |
|
||||||
* implicitly enriched with command objects and the results of |
|
||||||
* {@link ModelAttribute} annotated reference data accessor methods. |
|
||||||
* </ul> |
|
||||||
* |
|
||||||
* <p><b>NOTE: <code>@RequestMapping</code> will only be processed if a |
|
||||||
* corresponding <code>HandlerMapping</code> (for type level annotations) |
|
||||||
* and/or <code>HandlerAdapter</code> (for method level annotations) is |
|
||||||
* present in the dispatcher.</b> This is the case by default in both |
|
||||||
* <code>DispatcherServlet</code> and <code>DispatcherPortlet</code>. |
|
||||||
* However, if you are defining custom <code>HandlerMappings</code> or |
|
||||||
* <code>HandlerAdapters</code>, then you need to make sure that a |
|
||||||
* corresponding custom <code>DefaultAnnotationHandlerMapping</code> |
|
||||||
* and/or <code>AnnotationMethodHandlerAdapter</code> is defined as well |
|
||||||
* - provided that you intend to use <code>@RequestMapping</code>. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @author Arjen Poutsma |
|
||||||
* @author Sam Brannen |
|
||||||
* @since 2.5 |
|
||||||
* @see RequestParam |
|
||||||
* @see ModelAttribute |
|
||||||
* @see SessionAttributes |
|
||||||
* @see InitBinder |
|
||||||
* @see org.springframework.web.context.request.WebRequest |
|
||||||
* @see org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping |
|
||||||
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter |
|
||||||
* @see org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping |
|
||||||
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter |
|
||||||
*/ |
|
||||||
@Target({ElementType.METHOD, ElementType.TYPE}) |
|
||||||
@Retention(RetentionPolicy.RUNTIME) |
|
||||||
@Documented |
|
||||||
@Mapping |
|
||||||
public @interface RequestMapping { |
|
||||||
|
|
||||||
/** |
|
||||||
* The primary mapping expressed by this annotation. |
|
||||||
* <p>In a Servlet environment: the path mapping URIs (e.g. "/myPath.do"). |
|
||||||
* Ant-style path patterns are also supported (e.g. "/myPath/*.do"). |
|
||||||
* At the method level, relative paths (e.g. "edit.do") are supported |
|
||||||
* within the primary mapping expressed at the type level. |
|
||||||
* <p>In a Portlet environment: the mapped portlet modes |
|
||||||
* (i.e. "EDIT", "VIEW", "HELP" or any custom modes). |
|
||||||
* <p><b>Supported at the type level as well as at the method level!</b> |
|
||||||
* When used at the type level, all method-level mappings inherit |
|
||||||
* this primary mapping, narrowing it for a specific handler method. |
|
||||||
* <p>In case of Servlet-based handler methods, the method names are |
|
||||||
* taken into account for narrowing if no path was specified explicitly, |
|
||||||
* according to the specified |
|
||||||
* {@link org.springframework.web.servlet.mvc.multiaction.MethodNameResolver} |
|
||||||
* (by default an |
|
||||||
* {@link org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver}). |
|
||||||
* Note that this only applies in case of ambiguous annotation mappings |
|
||||||
* that do not specify a path mapping explicitly. In other words, |
|
||||||
* the method name is only used for narrowing among a set of matching |
|
||||||
* methods; it does not constitute a primary path mapping itself. |
|
||||||
* <p>If you have a single default method (without explicit path mapping), |
|
||||||
* then all requests without a more specific mapped method found will |
|
||||||
* be dispatched to it. If you have multiple such default methods, then |
|
||||||
* the method name will be taken into account for choosing between them. |
|
||||||
*/ |
|
||||||
String[] value() default {}; |
|
||||||
|
|
||||||
/** |
|
||||||
* The HTTP request methods to map to, narrowing the primary mapping: |
|
||||||
* GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE. |
|
||||||
* <p><b>Supported at the type level as well as at the method level!</b> |
|
||||||
* When used at the type level, all method-level mappings inherit |
|
||||||
* this HTTP method restriction (i.e. the type-level restriction |
|
||||||
* gets checked before the handler method is even resolved). |
|
||||||
* <p>Supported for Servlet environments as well as Portlet 2.0 environments. |
|
||||||
*/ |
|
||||||
RequestMethod[] method() default {}; |
|
||||||
|
|
||||||
/** |
|
||||||
* The parameters of the mapped request, narrowing the primary mapping. |
|
||||||
* <p>Same format for any environment: a sequence of "myParam=myValue" style |
|
||||||
* expressions, with a request only mapped if each such parameter is found |
|
||||||
* to have the given value. "myParam" style expressions are also supported, |
|
||||||
* with such parameters having to be present in the request (allowed to have |
|
||||||
* any value). Finally, "!myParam" style expressions indicate that the |
|
||||||
* specified parameter is <i>not</i> supposed to be present in the request. |
|
||||||
* <p><b>Supported at the type level as well as at the method level!</b> |
|
||||||
* When used at the type level, all method-level mappings inherit |
|
||||||
* this parameter restriction (i.e. the type-level restriction |
|
||||||
* gets checked before the handler method is even resolved). |
|
||||||
* <p>In a Servlet environment, parameter mappings are considered as restrictions |
|
||||||
* that are enforced at the type level. The primary path mapping (i.e. the |
|
||||||
* specified URI value) still has to uniquely identify the target handler, with |
|
||||||
* parameter mappings simply expressing preconditions for invoking the handler. |
|
||||||
* <p>In a Portlet environment, parameters are taken into account as mapping |
|
||||||
* differentiators, i.e. the primary portlet mode mapping plus the parameter |
|
||||||
* conditions uniquely identify the target handler. Different handlers may be |
|
||||||
* mapped onto the same portlet mode, as long as their parameter mappings differ. |
|
||||||
*/ |
|
||||||
String[] params() default {}; |
|
||||||
|
|
||||||
/** |
|
||||||
* The headers of the mapped request, narrowing the primary mapping. |
|
||||||
* <p>Same format for any environment: a sequence of "My-Header=myValue" style |
|
||||||
* expressions, with a request only mapped if each such header is found |
|
||||||
* to have the given value. "My-Header" style expressions are also supported, |
|
||||||
* with such headers having to be present in the request (allowed to have |
|
||||||
* any value). Finally, "!My-Header" style expressions indicate that the |
|
||||||
* specified header is <i>not</i> supposed to be present in the request. |
|
||||||
* <p>Also supports media type wildcards (*), for headers such as Accept |
|
||||||
* and Content-Type. For instance, |
|
||||||
* <pre> |
|
||||||
* @RequestMapping(value = "/something", headers = "content-type=text/*") |
|
||||||
* </pre> |
|
||||||
* will match requests with a Content-Type of "text/html", "text/plain", etc. |
|
||||||
* <p><b>Supported at the type level as well as at the method level!</b> |
|
||||||
* When used at the type level, all method-level mappings inherit |
|
||||||
* this header restriction (i.e. the type-level restriction |
|
||||||
* gets checked before the handler method is even resolved). |
|
||||||
* @see org.springframework.http.MediaType |
|
||||||
*/ |
|
||||||
String[] headers() default {}; |
|
||||||
} |
|
||||||
@ -1,41 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind.annotation; |
|
||||||
|
|
||||||
/** |
|
||||||
* Java 5 enumeration of HTTP request methods. Intended for use |
|
||||||
* with the {@link RequestMapping#method()} attribute of the |
|
||||||
* {@link RequestMapping} annotation. |
|
||||||
* |
|
||||||
* <p>Note that, by default, {@link org.springframework.web.servlet.DispatcherServlet} |
|
||||||
* supports GET, HEAD, POST, PUT and DELETE only. DispatcherServlet will |
|
||||||
* process TRACE and OPTIONS with the default HttpServlet behavior unless |
|
||||||
* explicitly told to dispatch those request types as well: Check out |
|
||||||
* the "dispatchOptionsRequest" and "dispatchTraceRequest" properties, |
|
||||||
* switching them to "true" if necessary. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5 |
|
||||||
* @see RequestMapping |
|
||||||
* @see org.springframework.web.servlet.DispatcherServlet#setDispatchOptionsRequest |
|
||||||
* @see org.springframework.web.servlet.DispatcherServlet#setDispatchTraceRequest |
|
||||||
*/ |
|
||||||
public enum RequestMethod { |
|
||||||
|
|
||||||
GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,64 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind.annotation; |
|
||||||
|
|
||||||
import java.lang.annotation.Documented; |
|
||||||
import java.lang.annotation.ElementType; |
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
import java.lang.annotation.Target; |
|
||||||
|
|
||||||
/** |
|
||||||
* Annotation which indicates that a method parameter should be bound to a web request parameter. |
|
||||||
* Supported for annotated handler methods in Servlet and Portlet environments. |
|
||||||
* |
|
||||||
* @author Arjen Poutsma |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5 |
|
||||||
* @see RequestMapping |
|
||||||
* @see RequestHeader |
|
||||||
* @see CookieValue |
|
||||||
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter |
|
||||||
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter |
|
||||||
*/ |
|
||||||
@Target(ElementType.PARAMETER) |
|
||||||
@Retention(RetentionPolicy.RUNTIME) |
|
||||||
@Documented |
|
||||||
public @interface RequestParam { |
|
||||||
|
|
||||||
/** |
|
||||||
* The name of the request parameter to bind to. |
|
||||||
*/ |
|
||||||
String value() default ""; |
|
||||||
|
|
||||||
/** |
|
||||||
* Whether the parameter is required. |
|
||||||
* <p>Default is <code>true</code>, leading to an exception thrown in case |
|
||||||
* of the parameter missing in the request. Switch this to <code>false</code> |
|
||||||
* if you prefer a <code>null</value> in case of the parameter missing. |
|
||||||
* <p>Alternatively, provide a {@link #defaultValue() defaultValue}, |
|
||||||
* which implicitely sets this flag to <code>false</code>. |
|
||||||
*/ |
|
||||||
boolean required() default true; |
|
||||||
|
|
||||||
/** |
|
||||||
* The default value to use as a fallback. Supplying a default value implicitely |
|
||||||
* sets {@link #required()} to false. |
|
||||||
*/ |
|
||||||
String defaultValue() default ""; |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,39 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind.annotation; |
|
||||||
|
|
||||||
import java.lang.annotation.Documented; |
|
||||||
import java.lang.annotation.ElementType; |
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
import java.lang.annotation.Target; |
|
||||||
|
|
||||||
/** |
|
||||||
* Annotation which indicates that a method return value should be bound to the web response body. Supported for annotated |
|
||||||
* handler methods in Servlet environments. |
|
||||||
* |
|
||||||
* @author Arjen Poutsma |
|
||||||
* @see RequestBody |
|
||||||
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter |
|
||||||
* @since 3.0 |
|
||||||
*/ |
|
||||||
@Target(ElementType.METHOD) |
|
||||||
@Retention(RetentionPolicy.RUNTIME) |
|
||||||
@Documented |
|
||||||
public @interface ResponseBody { |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,55 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind.annotation; |
|
||||||
|
|
||||||
import java.lang.annotation.Documented; |
|
||||||
import java.lang.annotation.ElementType; |
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
import java.lang.annotation.Target; |
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus; |
|
||||||
|
|
||||||
/** |
|
||||||
* Marks a method or exception class with the status code and reason that should be returned. The status code is applied |
|
||||||
* to the HTTP response when the handler method is invoked, or whenever said exception is thrown. |
|
||||||
* |
|
||||||
* @author Arjen Poutsma |
|
||||||
* @see org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver |
|
||||||
* @since 3.0 |
|
||||||
*/ |
|
||||||
@Target({ElementType.TYPE, ElementType.METHOD}) |
|
||||||
@Retention(RetentionPolicy.RUNTIME) |
|
||||||
@Documented |
|
||||||
public @interface ResponseStatus { |
|
||||||
|
|
||||||
/** |
|
||||||
* The status code to use for the response. |
|
||||||
* |
|
||||||
* @see javax.servlet.http.HttpServletResponse#setStatus(int) |
|
||||||
*/ |
|
||||||
HttpStatus value(); |
|
||||||
|
|
||||||
/** |
|
||||||
* The reason to be used for the response. <p>If this element is not set, it will default to the standard status |
|
||||||
* message for the status code. |
|
||||||
* |
|
||||||
* @see javax.servlet.http.HttpServletResponse#sendError(int, String) |
|
||||||
*/ |
|
||||||
String reason() default ""; |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,71 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.bind.annotation; |
|
||||||
|
|
||||||
import java.lang.annotation.Documented; |
|
||||||
import java.lang.annotation.ElementType; |
|
||||||
import java.lang.annotation.Inherited; |
|
||||||
import java.lang.annotation.Retention; |
|
||||||
import java.lang.annotation.RetentionPolicy; |
|
||||||
import java.lang.annotation.Target; |
|
||||||
|
|
||||||
/** |
|
||||||
* Annotation that indicates the session attributes that a specific handler |
|
||||||
* uses. This will typically list the names of model attributes which should be |
|
||||||
* transparently stored in the session or some conversational storage, |
|
||||||
* serving as form-backing beans. <b>Declared at the type level,</b> applying |
|
||||||
* to the model attributes that the annotated handler class operates on. |
|
||||||
* |
|
||||||
* <p><b>NOTE:</b> Session attributes as indicated using this annotation |
|
||||||
* correspond to a specific handler's model attributes, getting transparently |
|
||||||
* stored in a conversational session. Those attributes will be removed once |
|
||||||
* the handler indicates completion of its conversational session. Therefore, |
|
||||||
* use this facility for such conversational attributes which are supposed |
|
||||||
* to be stored in the session <i>temporarily</i> during the course of a |
|
||||||
* specific handler's conversation. |
|
||||||
* |
|
||||||
* <p>For permanent session attributes, e.g. a user authentication object, |
|
||||||
* use the traditional <code>session.setAttribute</code> method instead. |
|
||||||
* Alternatively, consider using the attribute management capabilities of the |
|
||||||
* generic {@link org.springframework.web.context.request.WebRequest} interface. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5 |
|
||||||
*/ |
|
||||||
@Target({ElementType.TYPE}) |
|
||||||
@Retention(RetentionPolicy.RUNTIME) |
|
||||||
@Inherited |
|
||||||
@Documented |
|
||||||
public @interface SessionAttributes { |
|
||||||
|
|
||||||
/** |
|
||||||
* The names of session attributes in the model, to be stored in the |
|
||||||
* session or some conversational storage. |
|
||||||
* <p>Note: This indicates the model attribute names. The session attribute |
|
||||||
* names may or may not match the model attribute names; applications should |
|
||||||
* not rely on the session attribute names but rather operate on the model only. |
|
||||||
*/ |
|
||||||
String[] value() default {}; |
|
||||||
|
|
||||||
/** |
|
||||||
* The types of session attributes in the model, to be stored in the |
|
||||||
* session or some conversational storage. All model attributes of this |
|
||||||
* type will be stored in the session, regardless of attribute name. |
|
||||||
*/ |
|
||||||
Class[] types() default {}; |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,9 +0,0 @@ |
|||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* Annotations for binding requests to controllers and handler methods |
|
||||||
* as well as for binding request parameters to method arguments. |
|
||||||
* |
|
||||||
*/ |
|
||||||
package org.springframework.web.bind.annotation; |
|
||||||
|
|
||||||
@ -1,41 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.bind.annotation.support; |
|
||||||
|
|
||||||
import java.lang.reflect.Method; |
|
||||||
|
|
||||||
import org.springframework.core.NestedRuntimeException; |
|
||||||
|
|
||||||
/** |
|
||||||
* Exception indicating that the execution of an annotated MVC handler method failed. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5.6 |
|
||||||
* @see HandlerMethodInvoker#invokeHandlerMethod |
|
||||||
*/ |
|
||||||
public class HandlerMethodInvocationException extends NestedRuntimeException { |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a new HandlerMethodInvocationException for the given Method handle and cause. |
|
||||||
* @param handlerMethod the handler method handle |
|
||||||
* @param cause the cause of the invocation failure |
|
||||||
*/ |
|
||||||
public HandlerMethodInvocationException(Method handlerMethod, Throwable cause) { |
|
||||||
super("Failed to invoke handler method [" + handlerMethod + "]", cause); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,745 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind.annotation.support; |
|
||||||
|
|
||||||
import java.lang.annotation.Annotation; |
|
||||||
import java.lang.reflect.InvocationTargetException; |
|
||||||
import java.lang.reflect.Method; |
|
||||||
import java.lang.reflect.ParameterizedType; |
|
||||||
import java.lang.reflect.Type; |
|
||||||
import java.lang.reflect.TypeVariable; |
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.Arrays; |
|
||||||
import java.util.Collection; |
|
||||||
import java.util.HashSet; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Map; |
|
||||||
import java.util.Set; |
|
||||||
|
|
||||||
import org.apache.commons.logging.Log; |
|
||||||
import org.apache.commons.logging.LogFactory; |
|
||||||
import org.springframework.beans.BeanUtils; |
|
||||||
import org.springframework.core.BridgeMethodResolver; |
|
||||||
import org.springframework.core.Conventions; |
|
||||||
import org.springframework.core.GenericTypeResolver; |
|
||||||
import org.springframework.core.MethodParameter; |
|
||||||
import org.springframework.core.ParameterNameDiscoverer; |
|
||||||
import org.springframework.core.annotation.AnnotationUtils; |
|
||||||
import org.springframework.http.HttpInputMessage; |
|
||||||
import org.springframework.http.MediaType; |
|
||||||
import org.springframework.http.converter.HttpMessageConverter; |
|
||||||
import org.springframework.model.ui.PresentationModelFactory; |
|
||||||
import org.springframework.model.ui.config.BindingLifecycle; |
|
||||||
import org.springframework.ui.ExtendedModelMap; |
|
||||||
import org.springframework.ui.Model; |
|
||||||
import org.springframework.ui.MvcBindingLifecycle; |
|
||||||
import org.springframework.util.ClassUtils; |
|
||||||
import org.springframework.util.ReflectionUtils; |
|
||||||
import org.springframework.util.StringUtils; |
|
||||||
import org.springframework.validation.BindingResult; |
|
||||||
import org.springframework.validation.Errors; |
|
||||||
import org.springframework.web.HttpMediaTypeNotSupportedException; |
|
||||||
import org.springframework.web.bind.WebDataBinder; |
|
||||||
import org.springframework.web.bind.annotation.CookieValue; |
|
||||||
import org.springframework.web.bind.annotation.InitBinder; |
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute; |
|
||||||
import org.springframework.web.bind.annotation.PathVariable; |
|
||||||
import org.springframework.web.bind.annotation.RequestBody; |
|
||||||
import org.springframework.web.bind.annotation.RequestHeader; |
|
||||||
import org.springframework.web.bind.annotation.RequestParam; |
|
||||||
import org.springframework.web.bind.support.DefaultSessionAttributeStore; |
|
||||||
import org.springframework.web.bind.support.SessionAttributeStore; |
|
||||||
import org.springframework.web.bind.support.SessionStatus; |
|
||||||
import org.springframework.web.bind.support.SimpleSessionStatus; |
|
||||||
import org.springframework.web.bind.support.WebArgumentResolver; |
|
||||||
import org.springframework.web.bind.support.WebBindingInitializer; |
|
||||||
import org.springframework.web.bind.support.WebRequestDataBinder; |
|
||||||
import org.springframework.web.context.request.NativeWebRequest; |
|
||||||
import org.springframework.web.context.request.NativeWebRequestParameterMap; |
|
||||||
import org.springframework.web.context.request.WebRequest; |
|
||||||
import org.springframework.web.multipart.MultipartRequest; |
|
||||||
import org.springframework.web.servlet.support.PresentationModelUtils; |
|
||||||
|
|
||||||
/** |
|
||||||
* Support class for invoking an annotated handler method. Operates on the introspection results of a {@link |
|
||||||
* HandlerMethodResolver} for a specific handler type. |
|
||||||
* |
|
||||||
* <p>Used by {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter} and {@link |
|
||||||
* org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter}. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @author Arjen Poutsma |
|
||||||
* @see #invokeHandlerMethod |
|
||||||
* @since 2.5.2 |
|
||||||
*/ |
|
||||||
public class HandlerMethodInvoker { |
|
||||||
|
|
||||||
/** We'll create a lot of these objects, so we don't want a new logger every time. */ |
|
||||||
private static final Log logger = LogFactory.getLog(HandlerMethodInvoker.class); |
|
||||||
|
|
||||||
private final HandlerMethodResolver methodResolver; |
|
||||||
|
|
||||||
private final WebBindingInitializer bindingInitializer; |
|
||||||
|
|
||||||
private final SessionAttributeStore sessionAttributeStore; |
|
||||||
|
|
||||||
private final ParameterNameDiscoverer parameterNameDiscoverer; |
|
||||||
|
|
||||||
private final WebArgumentResolver[] customArgumentResolvers; |
|
||||||
|
|
||||||
private final SimpleSessionStatus sessionStatus = new SimpleSessionStatus(); |
|
||||||
|
|
||||||
private final HttpMessageConverter[] messageConverters; |
|
||||||
|
|
||||||
|
|
||||||
public HandlerMethodInvoker(HandlerMethodResolver methodResolver) { |
|
||||||
this(methodResolver, null); |
|
||||||
} |
|
||||||
|
|
||||||
public HandlerMethodInvoker(HandlerMethodResolver methodResolver, WebBindingInitializer bindingInitializer) { |
|
||||||
this(methodResolver, bindingInitializer, new DefaultSessionAttributeStore(), null, new WebArgumentResolver[0], |
|
||||||
new HttpMessageConverter[0]); |
|
||||||
} |
|
||||||
|
|
||||||
public HandlerMethodInvoker(HandlerMethodResolver methodResolver, WebBindingInitializer bindingInitializer, |
|
||||||
SessionAttributeStore sessionAttributeStore, ParameterNameDiscoverer parameterNameDiscoverer, |
|
||||||
WebArgumentResolver[] customArgumentResolvers, HttpMessageConverter[] messageConverters) { |
|
||||||
|
|
||||||
this.methodResolver = methodResolver; |
|
||||||
this.bindingInitializer = bindingInitializer; |
|
||||||
this.sessionAttributeStore = sessionAttributeStore; |
|
||||||
this.parameterNameDiscoverer = parameterNameDiscoverer; |
|
||||||
this.customArgumentResolvers = customArgumentResolvers; |
|
||||||
this.messageConverters = messageConverters; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public final Object invokeHandlerMethod(Method handlerMethod, Object handler, |
|
||||||
NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception { |
|
||||||
|
|
||||||
Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod); |
|
||||||
try { |
|
||||||
boolean debug = logger.isDebugEnabled(); |
|
||||||
for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) { |
|
||||||
Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod); |
|
||||||
Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel); |
|
||||||
if (debug) { |
|
||||||
logger.debug("Invoking model attribute method: " + attributeMethodToInvoke); |
|
||||||
} |
|
||||||
Object attrValue = doInvokeMethod(attributeMethodToInvoke, handler, args); |
|
||||||
String attrName = AnnotationUtils.findAnnotation(attributeMethodToInvoke, ModelAttribute.class).value(); |
|
||||||
if ("".equals(attrName)) { |
|
||||||
Class resolvedType = GenericTypeResolver.resolveReturnType( |
|
||||||
attributeMethodToInvoke, handler.getClass()); |
|
||||||
attrName = Conventions.getVariableNameForReturnType( |
|
||||||
attributeMethodToInvoke, resolvedType, attrValue); |
|
||||||
} |
|
||||||
implicitModel.addAttribute(attrName, attrValue); |
|
||||||
} |
|
||||||
Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel); |
|
||||||
if (debug) { |
|
||||||
logger.debug("Invoking request handler method: " + handlerMethodToInvoke); |
|
||||||
} |
|
||||||
return doInvokeMethod(handlerMethodToInvoke, handler, args); |
|
||||||
} |
|
||||||
catch (IllegalStateException ex) { |
|
||||||
// Throw exception with full handler method context...
|
|
||||||
throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
private Object[] resolveHandlerArguments(Method handlerMethod, Object handler, |
|
||||||
NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception { |
|
||||||
|
|
||||||
Class[] paramTypes = handlerMethod.getParameterTypes(); |
|
||||||
Object[] args = new Object[paramTypes.length]; |
|
||||||
|
|
||||||
for (int i = 0; i < args.length; i++) { |
|
||||||
MethodParameter methodParam = new MethodParameter(handlerMethod, i); |
|
||||||
methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer); |
|
||||||
GenericTypeResolver.resolveParameterType(methodParam, handler.getClass()); |
|
||||||
String paramName = null; |
|
||||||
String headerName = null; |
|
||||||
boolean requestBodyFound = false; |
|
||||||
String cookieName = null; |
|
||||||
String pathVarName = null; |
|
||||||
String attrName = null; |
|
||||||
boolean required = false; |
|
||||||
String defaultValue = null; |
|
||||||
int found = 0; |
|
||||||
Annotation[] paramAnns = methodParam.getParameterAnnotations(); |
|
||||||
|
|
||||||
for (Annotation paramAnn : paramAnns) { |
|
||||||
if (RequestParam.class.isInstance(paramAnn)) { |
|
||||||
RequestParam requestParam = (RequestParam) paramAnn; |
|
||||||
paramName = requestParam.value(); |
|
||||||
required = requestParam.required(); |
|
||||||
defaultValue = requestParam.defaultValue(); |
|
||||||
found++; |
|
||||||
} |
|
||||||
else if (RequestHeader.class.isInstance(paramAnn)) { |
|
||||||
RequestHeader requestHeader = (RequestHeader) paramAnn; |
|
||||||
headerName = requestHeader.value(); |
|
||||||
required = requestHeader.required(); |
|
||||||
defaultValue = requestHeader.defaultValue(); |
|
||||||
found++; |
|
||||||
} |
|
||||||
else if (RequestBody.class.isInstance(paramAnn)) { |
|
||||||
requestBodyFound = true; |
|
||||||
found++; |
|
||||||
} |
|
||||||
else if (CookieValue.class.isInstance(paramAnn)) { |
|
||||||
CookieValue cookieValue = (CookieValue) paramAnn; |
|
||||||
cookieName = cookieValue.value(); |
|
||||||
required = cookieValue.required(); |
|
||||||
defaultValue = cookieValue.defaultValue(); |
|
||||||
found++; |
|
||||||
} |
|
||||||
else if (PathVariable.class.isInstance(paramAnn)) { |
|
||||||
PathVariable pathVar = (PathVariable) paramAnn; |
|
||||||
pathVarName = pathVar.value(); |
|
||||||
found++; |
|
||||||
} |
|
||||||
else if (ModelAttribute.class.isInstance(paramAnn)) { |
|
||||||
ModelAttribute attr = (ModelAttribute) paramAnn; |
|
||||||
attrName = attr.value(); |
|
||||||
found++; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (found > 1) { |
|
||||||
throw new IllegalStateException("Handler parameter annotations are exclusive choices - " + |
|
||||||
"do not specify more than one such annotation on the same parameter: " + handlerMethod); |
|
||||||
} |
|
||||||
|
|
||||||
if (found == 0) { |
|
||||||
Object argValue = resolveCommonArgument(methodParam, webRequest); |
|
||||||
if (argValue != WebArgumentResolver.UNRESOLVED) { |
|
||||||
args[i] = argValue; |
|
||||||
} |
|
||||||
else { |
|
||||||
Class paramType = methodParam.getParameterType(); |
|
||||||
if (Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType)) { |
|
||||||
args[i] = implicitModel; |
|
||||||
} |
|
||||||
else if (SessionStatus.class.isAssignableFrom(paramType)) { |
|
||||||
args[i] = this.sessionStatus; |
|
||||||
} |
|
||||||
else if (Errors.class.isAssignableFrom(paramType)) { |
|
||||||
throw new IllegalStateException("Errors/BindingResult argument declared " + |
|
||||||
"without preceding model attribute. Check your handler method signature!"); |
|
||||||
} |
|
||||||
// TODO - Code Review - NEW BINDING LIFECYCLE RESOLVABLE ARG
|
|
||||||
else if (BindingLifecycle.class.isAssignableFrom(paramType)) { |
|
||||||
Class<?> modelType = resolveBindingLifecycleModelType(methodParam); |
|
||||||
PresentationModelFactory factory = PresentationModelUtils.getPresentationModelFactory(webRequest); |
|
||||||
Map<String, Object> fieldValues = new NativeWebRequestParameterMap(webRequest); |
|
||||||
args[i] = new MvcBindingLifecycle(modelType, factory, implicitModel, fieldValues); |
|
||||||
} |
|
||||||
else if (BeanUtils.isSimpleProperty(paramType)) { |
|
||||||
paramName = ""; |
|
||||||
} |
|
||||||
else { |
|
||||||
attrName = ""; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (paramName != null) { |
|
||||||
args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler); |
|
||||||
} |
|
||||||
else if (headerName != null) { |
|
||||||
args[i] = resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler); |
|
||||||
} |
|
||||||
else if (requestBodyFound) { |
|
||||||
args[i] = resolveRequestBody(methodParam, webRequest, handler); |
|
||||||
} |
|
||||||
else if (cookieName != null) { |
|
||||||
args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler); |
|
||||||
} |
|
||||||
else if (pathVarName != null) { |
|
||||||
args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler); |
|
||||||
} |
|
||||||
else if (attrName != null) { |
|
||||||
WebDataBinder binder = resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler); |
|
||||||
boolean assignBindingResult = (args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1])); |
|
||||||
if (binder.getTarget() != null) { |
|
||||||
doBind(webRequest, binder, !assignBindingResult); |
|
||||||
} |
|
||||||
args[i] = binder.getTarget(); |
|
||||||
if (assignBindingResult) { |
|
||||||
args[i + 1] = binder.getBindingResult(); |
|
||||||
i++; |
|
||||||
} |
|
||||||
implicitModel.putAll(binder.getBindingResult().getModel()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return args; |
|
||||||
} |
|
||||||
|
|
||||||
protected void initBinder(Object handler, String attrName, WebDataBinder binder, NativeWebRequest webRequest) |
|
||||||
throws Exception { |
|
||||||
|
|
||||||
if (this.bindingInitializer != null) { |
|
||||||
this.bindingInitializer.initBinder(binder, webRequest); |
|
||||||
} |
|
||||||
if (handler != null) { |
|
||||||
Set<Method> initBinderMethods = this.methodResolver.getInitBinderMethods(); |
|
||||||
if (!initBinderMethods.isEmpty()) { |
|
||||||
boolean debug = logger.isDebugEnabled(); |
|
||||||
for (Method initBinderMethod : initBinderMethods) { |
|
||||||
Method methodToInvoke = BridgeMethodResolver.findBridgedMethod(initBinderMethod); |
|
||||||
String[] targetNames = AnnotationUtils.findAnnotation(methodToInvoke, InitBinder.class).value(); |
|
||||||
if (targetNames.length == 0 || Arrays.asList(targetNames).contains(attrName)) { |
|
||||||
Object[] initBinderArgs = |
|
||||||
resolveInitBinderArguments(handler, methodToInvoke, binder, webRequest); |
|
||||||
if (debug) { |
|
||||||
logger.debug("Invoking init-binder method: " + methodToInvoke); |
|
||||||
} |
|
||||||
Object returnValue = doInvokeMethod(methodToInvoke, handler, initBinderArgs); |
|
||||||
if (returnValue != null) { |
|
||||||
throw new IllegalStateException( |
|
||||||
"InitBinder methods must not have a return value: " + methodToInvoke); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private Object[] resolveInitBinderArguments(Object handler, Method initBinderMethod, |
|
||||||
WebDataBinder binder, NativeWebRequest webRequest) throws Exception { |
|
||||||
|
|
||||||
Class[] initBinderParams = initBinderMethod.getParameterTypes(); |
|
||||||
Object[] initBinderArgs = new Object[initBinderParams.length]; |
|
||||||
|
|
||||||
for (int i = 0; i < initBinderArgs.length; i++) { |
|
||||||
MethodParameter methodParam = new MethodParameter(initBinderMethod, i); |
|
||||||
methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer); |
|
||||||
GenericTypeResolver.resolveParameterType(methodParam, handler.getClass()); |
|
||||||
String paramName = null; |
|
||||||
boolean paramRequired = false; |
|
||||||
String paramDefaultValue = null; |
|
||||||
String pathVarName = null; |
|
||||||
Annotation[] paramAnns = methodParam.getParameterAnnotations(); |
|
||||||
|
|
||||||
for (Annotation paramAnn : paramAnns) { |
|
||||||
if (RequestParam.class.isInstance(paramAnn)) { |
|
||||||
RequestParam requestParam = (RequestParam) paramAnn; |
|
||||||
paramName = requestParam.value(); |
|
||||||
paramRequired = requestParam.required(); |
|
||||||
paramDefaultValue = requestParam.defaultValue(); |
|
||||||
break; |
|
||||||
} |
|
||||||
else if (ModelAttribute.class.isInstance(paramAnn)) { |
|
||||||
throw new IllegalStateException( |
|
||||||
"@ModelAttribute is not supported on @InitBinder methods: " + initBinderMethod); |
|
||||||
} |
|
||||||
else if (PathVariable.class.isInstance(paramAnn)) { |
|
||||||
PathVariable pathVar = (PathVariable) paramAnn; |
|
||||||
pathVarName = pathVar.value(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (paramName == null && pathVarName == null) { |
|
||||||
Object argValue = resolveCommonArgument(methodParam, webRequest); |
|
||||||
if (argValue != WebArgumentResolver.UNRESOLVED) { |
|
||||||
initBinderArgs[i] = argValue; |
|
||||||
} |
|
||||||
else { |
|
||||||
Class paramType = initBinderParams[i]; |
|
||||||
if (paramType.isInstance(binder)) { |
|
||||||
initBinderArgs[i] = binder; |
|
||||||
} |
|
||||||
else if (BeanUtils.isSimpleProperty(paramType)) { |
|
||||||
paramName = ""; |
|
||||||
} |
|
||||||
else { |
|
||||||
throw new IllegalStateException( |
|
||||||
"Unsupported argument [" + paramType.getName() + "] for @InitBinder method: " + |
|
||||||
initBinderMethod); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (paramName != null) { |
|
||||||
initBinderArgs[i] = resolveRequestParam( |
|
||||||
paramName, paramRequired, paramDefaultValue, methodParam, webRequest, null); |
|
||||||
} |
|
||||||
else if (pathVarName != null) { |
|
||||||
initBinderArgs[i] = resolvePathVariable(pathVarName, methodParam, webRequest, null); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return initBinderArgs; |
|
||||||
} |
|
||||||
|
|
||||||
private Object resolveRequestParam(String paramName, boolean required, String defaultValue, |
|
||||||
MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall) |
|
||||||
throws Exception { |
|
||||||
|
|
||||||
Class paramType = methodParam.getParameterType(); |
|
||||||
if (paramName.length() == 0) { |
|
||||||
paramName = getRequiredParameterName(methodParam); |
|
||||||
} |
|
||||||
Object paramValue = null; |
|
||||||
if (webRequest.getNativeRequest() instanceof MultipartRequest) { |
|
||||||
paramValue = ((MultipartRequest) webRequest.getNativeRequest()).getFile(paramName); |
|
||||||
} |
|
||||||
if (paramValue == null) { |
|
||||||
String[] paramValues = webRequest.getParameterValues(paramName); |
|
||||||
if (paramValues != null) { |
|
||||||
paramValue = (paramValues.length == 1 ? paramValues[0] : paramValues); |
|
||||||
} |
|
||||||
} |
|
||||||
if (paramValue == null) { |
|
||||||
if (StringUtils.hasText(defaultValue)) { |
|
||||||
paramValue = defaultValue; |
|
||||||
} |
|
||||||
else if (required) { |
|
||||||
raiseMissingParameterException(paramName, paramType); |
|
||||||
} |
|
||||||
paramValue = checkValue(paramName, paramValue, paramType); |
|
||||||
} |
|
||||||
WebDataBinder binder = createBinder(webRequest, null, paramName); |
|
||||||
initBinder(handlerForInitBinderCall, paramName, binder, webRequest); |
|
||||||
return binder.convertIfNecessary(paramValue, paramType, methodParam); |
|
||||||
} |
|
||||||
|
|
||||||
private Object resolveRequestHeader(String headerName, boolean required, String defaultValue, |
|
||||||
MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall) |
|
||||||
throws Exception { |
|
||||||
|
|
||||||
Class paramType = methodParam.getParameterType(); |
|
||||||
if (headerName.length() == 0) { |
|
||||||
headerName = getRequiredParameterName(methodParam); |
|
||||||
} |
|
||||||
Object headerValue = null; |
|
||||||
String[] headerValues = webRequest.getHeaderValues(headerName); |
|
||||||
if (headerValues != null) { |
|
||||||
headerValue = (headerValues.length == 1 ? headerValues[0] : headerValues); |
|
||||||
} |
|
||||||
if (headerValue == null) { |
|
||||||
if (StringUtils.hasText(defaultValue)) { |
|
||||||
headerValue = defaultValue; |
|
||||||
} |
|
||||||
else if (required) { |
|
||||||
raiseMissingHeaderException(headerName, paramType); |
|
||||||
} |
|
||||||
headerValue = checkValue(headerName, headerValue, paramType); |
|
||||||
} |
|
||||||
WebDataBinder binder = createBinder(webRequest, null, headerName); |
|
||||||
initBinder(handlerForInitBinderCall, headerName, binder, webRequest); |
|
||||||
return binder.convertIfNecessary(headerValue, paramType, methodParam); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Resolves the given {@link RequestBody @RequestBody} annotation. |
|
||||||
*/ |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
protected Object resolveRequestBody(MethodParameter methodParam, NativeWebRequest webRequest, Object handler) |
|
||||||
throws Exception { |
|
||||||
|
|
||||||
HttpInputMessage inputMessage = createHttpInputMessage(webRequest); |
|
||||||
Class paramType = methodParam.getParameterType(); |
|
||||||
MediaType contentType = inputMessage.getHeaders().getContentType(); |
|
||||||
if (contentType == null) { |
|
||||||
StringBuilder builder = new StringBuilder(ClassUtils.getShortName(methodParam.getParameterType())); |
|
||||||
String paramName = methodParam.getParameterName(); |
|
||||||
if (paramName != null) { |
|
||||||
builder.append(' '); |
|
||||||
builder.append(paramName); |
|
||||||
} |
|
||||||
throw new HttpMediaTypeNotSupportedException( |
|
||||||
"Cannot extract @RequestBody parameter (" + builder.toString() + "): no Content-Type found"); |
|
||||||
} |
|
||||||
List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>(); |
|
||||||
for (HttpMessageConverter<?> messageConverter : messageConverters) { |
|
||||||
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes()); |
|
||||||
if (messageConverter.supports(paramType)) { |
|
||||||
for (MediaType supportedMediaType : messageConverter.getSupportedMediaTypes()) { |
|
||||||
if (supportedMediaType.includes(contentType)) { |
|
||||||
return messageConverter.read(paramType, inputMessage); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return a {@link HttpInputMessage} for the given {@link NativeWebRequest}. |
|
||||||
* Throws an UnsupportedOperationException by default. |
|
||||||
*/ |
|
||||||
protected HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest) throws Exception { |
|
||||||
throw new UnsupportedOperationException("@RequestBody not supported"); |
|
||||||
} |
|
||||||
|
|
||||||
private Object resolveCookieValue(String cookieName, boolean required, String defaultValue, |
|
||||||
MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall) |
|
||||||
throws Exception { |
|
||||||
|
|
||||||
Class paramType = methodParam.getParameterType(); |
|
||||||
if (cookieName.length() == 0) { |
|
||||||
cookieName = getRequiredParameterName(methodParam); |
|
||||||
} |
|
||||||
Object cookieValue = resolveCookieValue(cookieName, paramType, webRequest); |
|
||||||
if (cookieValue == null) { |
|
||||||
if (StringUtils.hasText(defaultValue)) { |
|
||||||
cookieValue = defaultValue; |
|
||||||
} |
|
||||||
else if (required) { |
|
||||||
raiseMissingCookieException(cookieName, paramType); |
|
||||||
} |
|
||||||
cookieValue = checkValue(cookieName, cookieValue, paramType); |
|
||||||
} |
|
||||||
WebDataBinder binder = createBinder(webRequest, null, cookieName); |
|
||||||
initBinder(handlerForInitBinderCall, cookieName, binder, webRequest); |
|
||||||
return binder.convertIfNecessary(cookieValue, paramType, methodParam); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Resolves the given {@link CookieValue @CookieValue} annotation. |
|
||||||
* Throws an UnsupportedOperationException by default. |
|
||||||
*/ |
|
||||||
protected Object resolveCookieValue(String cookieName, Class paramType, NativeWebRequest webRequest) |
|
||||||
throws Exception { |
|
||||||
|
|
||||||
throw new UnsupportedOperationException("@CookieValue not supported"); |
|
||||||
} |
|
||||||
|
|
||||||
private Object resolvePathVariable(String pathVarName, MethodParameter methodParam, |
|
||||||
NativeWebRequest webRequest, Object handlerForInitBinderCall) throws Exception { |
|
||||||
|
|
||||||
Class paramType = methodParam.getParameterType(); |
|
||||||
if (pathVarName.length() == 0) { |
|
||||||
pathVarName = getRequiredParameterName(methodParam); |
|
||||||
} |
|
||||||
String pathVarValue = resolvePathVariable(pathVarName, paramType, webRequest); |
|
||||||
WebDataBinder binder = createBinder(webRequest, null, pathVarName); |
|
||||||
initBinder(handlerForInitBinderCall, pathVarName, binder, webRequest); |
|
||||||
return binder.convertIfNecessary(pathVarValue, paramType, methodParam); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Resolves the given {@link PathVariable @PathVariable} annotation. |
|
||||||
* Throws an UnsupportedOperationException by default. |
|
||||||
*/ |
|
||||||
protected String resolvePathVariable(String pathVarName, Class paramType, NativeWebRequest webRequest) |
|
||||||
throws Exception { |
|
||||||
|
|
||||||
throw new UnsupportedOperationException("@PathVariable not supported"); |
|
||||||
} |
|
||||||
|
|
||||||
private String getRequiredParameterName(MethodParameter methodParam) { |
|
||||||
String name = methodParam.getParameterName(); |
|
||||||
if (name == null) { |
|
||||||
throw new IllegalStateException("No parameter name specified for argument of type [" + |
|
||||||
methodParam.getParameterType().getName() + |
|
||||||
"], and no parameter name information found in class file either."); |
|
||||||
} |
|
||||||
return name; |
|
||||||
} |
|
||||||
|
|
||||||
private Object checkValue(String name, Object value, Class paramType) { |
|
||||||
if (value == null) { |
|
||||||
if (boolean.class.equals(paramType)) { |
|
||||||
return Boolean.FALSE; |
|
||||||
} |
|
||||||
else if (paramType.isPrimitive()) { |
|
||||||
throw new IllegalStateException("Optional " + paramType + " parameter '" + name + |
|
||||||
"' is not present but cannot be translated into a null value due to being declared as a " + |
|
||||||
"primitive type. Consider declaring it as object wrapper for the corresponding primitive type."); |
|
||||||
} |
|
||||||
} |
|
||||||
return value; |
|
||||||
} |
|
||||||
|
|
||||||
private WebDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam, |
|
||||||
ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler) |
|
||||||
throws Exception { |
|
||||||
|
|
||||||
// Bind request parameter onto object...
|
|
||||||
String name = attrName; |
|
||||||
if ("".equals(name)) { |
|
||||||
name = Conventions.getVariableNameForParameter(methodParam); |
|
||||||
} |
|
||||||
Class paramType = methodParam.getParameterType(); |
|
||||||
Object bindObject = null; |
|
||||||
if (implicitModel.containsKey(name)) { |
|
||||||
bindObject = implicitModel.get(name); |
|
||||||
} |
|
||||||
else if (this.methodResolver.isSessionAttribute(name, paramType)) { |
|
||||||
bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name); |
|
||||||
if (bindObject == null) { |
|
||||||
raiseSessionRequiredException("Session attribute '" + name + "' required - not found in session"); |
|
||||||
} |
|
||||||
} |
|
||||||
else { |
|
||||||
bindObject = BeanUtils.instantiateClass(paramType); |
|
||||||
} |
|
||||||
WebDataBinder binder = createBinder(webRequest, bindObject, name); |
|
||||||
initBinder(handler, name, binder, webRequest); |
|
||||||
return binder; |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
public final void updateModelAttributes(Object handler, Map<String, Object> mavModel, |
|
||||||
ExtendedModelMap implicitModel, NativeWebRequest webRequest) throws Exception { |
|
||||||
|
|
||||||
if (this.methodResolver.hasSessionAttributes() && this.sessionStatus.isComplete()) { |
|
||||||
for (String attrName : this.methodResolver.getActualSessionAttributeNames()) { |
|
||||||
this.sessionAttributeStore.cleanupAttribute(webRequest, attrName); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Expose model attributes as session attributes, if required.
|
|
||||||
// Expose BindingResults for all attributes, making custom editors available.
|
|
||||||
Map<String, Object> model = (mavModel != null ? mavModel : implicitModel); |
|
||||||
for (String attrName : new HashSet<String>(model.keySet())) { |
|
||||||
Object attrValue = model.get(attrName); |
|
||||||
boolean isSessionAttr = |
|
||||||
this.methodResolver.isSessionAttribute(attrName, (attrValue != null ? attrValue.getClass() : null)); |
|
||||||
if (isSessionAttr && !this.sessionStatus.isComplete()) { |
|
||||||
this.sessionAttributeStore.storeAttribute(webRequest, attrName, attrValue); |
|
||||||
} |
|
||||||
if (!attrName.startsWith(BindingResult.MODEL_KEY_PREFIX) && |
|
||||||
(isSessionAttr || isBindingCandidate(attrValue))) { |
|
||||||
String bindingResultKey = BindingResult.MODEL_KEY_PREFIX + attrName; |
|
||||||
if (mavModel != null && !model.containsKey(bindingResultKey)) { |
|
||||||
WebDataBinder binder = createBinder(webRequest, attrValue, attrName); |
|
||||||
initBinder(handler, attrName, binder, webRequest); |
|
||||||
mavModel.put(bindingResultKey, binder.getBindingResult()); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Determine whether the given value qualifies as a "binding candidate", i.e. might potentially be subject to |
|
||||||
* bean-style data binding later on. |
|
||||||
*/ |
|
||||||
protected boolean isBindingCandidate(Object value) { |
|
||||||
return (value != null && !value.getClass().isArray() && !(value instanceof Collection) && |
|
||||||
!(value instanceof Map) && !BeanUtils.isSimpleValueType(value.getClass())); |
|
||||||
} |
|
||||||
|
|
||||||
private Object doInvokeMethod(Method method, Object target, Object[] args) throws Exception { |
|
||||||
ReflectionUtils.makeAccessible(method); |
|
||||||
try { |
|
||||||
return method.invoke(target, args); |
|
||||||
} |
|
||||||
catch (InvocationTargetException ex) { |
|
||||||
ReflectionUtils.rethrowException(ex.getTargetException()); |
|
||||||
} |
|
||||||
throw new IllegalStateException("Should never get here"); |
|
||||||
} |
|
||||||
|
|
||||||
protected void raiseMissingParameterException(String paramName, Class paramType) throws Exception { |
|
||||||
throw new IllegalStateException("Missing parameter '" + paramName + "' of type [" + paramType.getName() + "]"); |
|
||||||
} |
|
||||||
|
|
||||||
protected void raiseMissingHeaderException(String headerName, Class paramType) throws Exception { |
|
||||||
throw new IllegalStateException("Missing header '" + headerName + "' of type [" + paramType.getName() + "]"); |
|
||||||
} |
|
||||||
|
|
||||||
protected void raiseMissingCookieException(String cookieName, Class paramType) throws Exception { |
|
||||||
throw new IllegalStateException("Missing cookie value '" + cookieName + "' of type [" + paramType.getName() + "]"); |
|
||||||
} |
|
||||||
|
|
||||||
protected void raiseSessionRequiredException(String message) throws Exception { |
|
||||||
throw new IllegalStateException(message); |
|
||||||
} |
|
||||||
|
|
||||||
protected WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName) throws Exception { |
|
||||||
return new WebRequestDataBinder(target, objectName); |
|
||||||
} |
|
||||||
|
|
||||||
protected void doBind(NativeWebRequest webRequest, WebDataBinder binder, boolean failOnErrors) throws Exception { |
|
||||||
WebRequestDataBinder requestBinder = (WebRequestDataBinder) binder; |
|
||||||
requestBinder.bind(webRequest); |
|
||||||
if (failOnErrors) { |
|
||||||
requestBinder.closeNoCatch(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected Object resolveCommonArgument(MethodParameter methodParameter, NativeWebRequest webRequest) |
|
||||||
throws Exception { |
|
||||||
|
|
||||||
// Invoke custom argument resolvers if present...
|
|
||||||
if (this.customArgumentResolvers != null) { |
|
||||||
for (WebArgumentResolver argumentResolver : this.customArgumentResolvers) { |
|
||||||
Object value = argumentResolver.resolveArgument(methodParameter, webRequest); |
|
||||||
if (value != WebArgumentResolver.UNRESOLVED) { |
|
||||||
return value; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Resolution of standard parameter types...
|
|
||||||
Class paramType = methodParameter.getParameterType(); |
|
||||||
Object value = resolveStandardArgument(paramType, webRequest); |
|
||||||
if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignableValue(paramType, value)) { |
|
||||||
throw new IllegalStateException( |
|
||||||
"Standard argument type [" + paramType.getName() + "] resolved to incompatible value of type [" + |
|
||||||
(value != null ? value.getClass() : null) + |
|
||||||
"]. Consider declaring the argument type in a less specific fashion."); |
|
||||||
} |
|
||||||
return value; |
|
||||||
} |
|
||||||
|
|
||||||
protected Object resolveStandardArgument(Class parameterType, NativeWebRequest webRequest) throws Exception { |
|
||||||
if (WebRequest.class.isAssignableFrom(parameterType)) { |
|
||||||
return webRequest; |
|
||||||
} |
|
||||||
return WebArgumentResolver.UNRESOLVED; |
|
||||||
} |
|
||||||
|
|
||||||
protected final void addReturnValueAsModelAttribute( |
|
||||||
Method handlerMethod, Class handlerType, Object returnValue, ExtendedModelMap implicitModel) { |
|
||||||
|
|
||||||
ModelAttribute attr = AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class); |
|
||||||
String attrName = (attr != null ? attr.value() : ""); |
|
||||||
if ("".equals(attrName)) { |
|
||||||
Class resolvedType = GenericTypeResolver.resolveReturnType(handlerMethod, handlerType); |
|
||||||
attrName = Conventions.getVariableNameForReturnType(handlerMethod, resolvedType, returnValue); |
|
||||||
} |
|
||||||
implicitModel.addAttribute(attrName, returnValue); |
|
||||||
} |
|
||||||
|
|
||||||
// TODO - Code Review - BINDING LIFECYCLE RELATED INTERNAL HELPERS
|
|
||||||
|
|
||||||
// TODO - this generic arg identification looping code is duplicated in several places now...
|
|
||||||
private Class<?> resolveBindingLifecycleModelType(MethodParameter methodParam) { |
|
||||||
Type type = GenericTypeResolver.getTargetType(methodParam); |
|
||||||
if (type instanceof ParameterizedType) { |
|
||||||
ParameterizedType paramType = (ParameterizedType) type; |
|
||||||
Type rawType = paramType.getRawType(); |
|
||||||
Type arg = paramType.getActualTypeArguments()[0]; |
|
||||||
if (arg instanceof TypeVariable) { |
|
||||||
arg = GenericTypeResolver.resolveTypeVariable((TypeVariable) arg, BindingLifecycle.class); |
|
||||||
} |
|
||||||
if (arg instanceof Class) { |
|
||||||
return (Class) arg; |
|
||||||
} |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,141 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind.annotation.support; |
|
||||||
|
|
||||||
import java.lang.reflect.Method; |
|
||||||
import java.util.Arrays; |
|
||||||
import java.util.Collections; |
|
||||||
import java.util.HashSet; |
|
||||||
import java.util.LinkedHashSet; |
|
||||||
import java.util.Set; |
|
||||||
|
|
||||||
import org.springframework.util.ClassUtils; |
|
||||||
import org.springframework.util.ReflectionUtils; |
|
||||||
import org.springframework.web.bind.annotation.InitBinder; |
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute; |
|
||||||
import org.springframework.web.bind.annotation.RequestMapping; |
|
||||||
import org.springframework.web.bind.annotation.SessionAttributes; |
|
||||||
|
|
||||||
/** |
|
||||||
* Support class for resolving web method annotations in a handler type. |
|
||||||
* Processes <code>@RequestMapping</code>, <code>@InitBinder</code>, |
|
||||||
* <code>@ModelAttribute</code> and <code>@SessionAttributes</code>. |
|
||||||
* |
|
||||||
* <p>Used by {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter} |
|
||||||
* and {@link org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter}. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5.2 |
|
||||||
* @see org.springframework.web.bind.annotation.RequestMapping |
|
||||||
* @see org.springframework.web.bind.annotation.InitBinder |
|
||||||
* @see org.springframework.web.bind.annotation.ModelAttribute |
|
||||||
* @see org.springframework.web.bind.annotation.SessionAttributes |
|
||||||
*/ |
|
||||||
public class HandlerMethodResolver { |
|
||||||
|
|
||||||
private final Set<Method> handlerMethods = new LinkedHashSet<Method>(); |
|
||||||
|
|
||||||
private final Set<Method> initBinderMethods = new LinkedHashSet<Method>(); |
|
||||||
|
|
||||||
private final Set<Method> modelAttributeMethods = new LinkedHashSet<Method>(); |
|
||||||
|
|
||||||
private RequestMapping typeLevelMapping; |
|
||||||
|
|
||||||
private boolean sessionAttributesFound; |
|
||||||
|
|
||||||
private final Set<String> sessionAttributeNames = new HashSet<String>(); |
|
||||||
|
|
||||||
private final Set<Class> sessionAttributeTypes = new HashSet<Class>(); |
|
||||||
|
|
||||||
private final Set<String> actualSessionAttributeNames = Collections.synchronizedSet(new HashSet<String>(4)); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize a new HandlerMethodResolver for the specified handler type. |
|
||||||
* @param handlerType the handler class to introspect |
|
||||||
*/ |
|
||||||
public void init(final Class<?> handlerType) { |
|
||||||
ReflectionUtils.doWithMethods(handlerType, new ReflectionUtils.MethodCallback() { |
|
||||||
public void doWith(Method method) { |
|
||||||
if (isHandlerMethod(method)) { |
|
||||||
handlerMethods.add(ClassUtils.getMostSpecificMethod(method, handlerType)); |
|
||||||
} |
|
||||||
else if (method.isAnnotationPresent(InitBinder.class)) { |
|
||||||
initBinderMethods.add(ClassUtils.getMostSpecificMethod(method, handlerType)); |
|
||||||
} |
|
||||||
else if (method.isAnnotationPresent(ModelAttribute.class)) { |
|
||||||
modelAttributeMethods.add(ClassUtils.getMostSpecificMethod(method, handlerType)); |
|
||||||
} |
|
||||||
} |
|
||||||
}); |
|
||||||
this.typeLevelMapping = handlerType.getAnnotation(RequestMapping.class); |
|
||||||
SessionAttributes sessionAttributes = handlerType.getAnnotation(SessionAttributes.class); |
|
||||||
this.sessionAttributesFound = (sessionAttributes != null); |
|
||||||
if (this.sessionAttributesFound) { |
|
||||||
this.sessionAttributeNames.addAll(Arrays.asList(sessionAttributes.value())); |
|
||||||
this.sessionAttributeTypes.addAll(Arrays.asList(sessionAttributes.types())); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected boolean isHandlerMethod(Method method) { |
|
||||||
return method.isAnnotationPresent(RequestMapping.class); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public final boolean hasHandlerMethods() { |
|
||||||
return !this.handlerMethods.isEmpty(); |
|
||||||
} |
|
||||||
|
|
||||||
public final Set<Method> getHandlerMethods() { |
|
||||||
return this.handlerMethods; |
|
||||||
} |
|
||||||
|
|
||||||
public final Set<Method> getInitBinderMethods() { |
|
||||||
return this.initBinderMethods; |
|
||||||
} |
|
||||||
|
|
||||||
public final Set<Method> getModelAttributeMethods() { |
|
||||||
return this.modelAttributeMethods; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean hasTypeLevelMapping() { |
|
||||||
return (this.typeLevelMapping != null); |
|
||||||
} |
|
||||||
|
|
||||||
public RequestMapping getTypeLevelMapping() { |
|
||||||
return this.typeLevelMapping; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean hasSessionAttributes() { |
|
||||||
return this.sessionAttributesFound; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isSessionAttribute(String attrName, Class attrType) { |
|
||||||
if (this.sessionAttributeNames.contains(attrName) || this.sessionAttributeTypes.contains(attrType)) { |
|
||||||
this.actualSessionAttributeNames.add(attrName); |
|
||||||
return true; |
|
||||||
} |
|
||||||
else { |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public Set<String> getActualSessionAttributeNames() { |
|
||||||
return this.actualSessionAttributeNames; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* Support classes for web annotation processing. |
|
||||||
* |
|
||||||
*/ |
|
||||||
package org.springframework.web.bind.annotation.support; |
|
||||||
|
|
||||||
@ -1,8 +0,0 @@ |
|||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* Provides web-specific data binding functionality. |
|
||||||
* |
|
||||||
*/ |
|
||||||
package org.springframework.web.bind; |
|
||||||
|
|
||||||
@ -1,135 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2007 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.bind.support; |
|
||||||
|
|
||||||
import org.springframework.beans.PropertyEditorRegistrar; |
|
||||||
import org.springframework.validation.BindingErrorProcessor; |
|
||||||
import org.springframework.validation.MessageCodesResolver; |
|
||||||
import org.springframework.web.bind.WebDataBinder; |
|
||||||
import org.springframework.web.context.request.WebRequest; |
|
||||||
|
|
||||||
/** |
|
||||||
* Convenient {@link WebBindingInitializer} for declarative configuration |
|
||||||
* in a Spring application context. Allows for reusing pre-configured |
|
||||||
* initializers with multiple controller/handlers. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5 |
|
||||||
* @see #setDirectFieldAccess |
|
||||||
* @see #setMessageCodesResolver |
|
||||||
* @see #setBindingErrorProcessor |
|
||||||
* @see #setPropertyEditorRegistrar |
|
||||||
*/ |
|
||||||
public class ConfigurableWebBindingInitializer implements WebBindingInitializer { |
|
||||||
|
|
||||||
private boolean directFieldAccess = false; |
|
||||||
|
|
||||||
private MessageCodesResolver messageCodesResolver; |
|
||||||
|
|
||||||
private BindingErrorProcessor bindingErrorProcessor; |
|
||||||
|
|
||||||
private PropertyEditorRegistrar[] propertyEditorRegistrars; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set whether to use direct field access instead of bean property access. |
|
||||||
* <p>Default is <code>false</code>, using bean property access. |
|
||||||
* Switch this to <code>true</code> for enforcing direct field access. |
|
||||||
*/ |
|
||||||
public final void setDirectFieldAccess(boolean directFieldAccess) { |
|
||||||
this.directFieldAccess = directFieldAccess; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Set the strategy to use for resolving errors into message codes. |
|
||||||
* Applies the given strategy to all data binders used by this controller. |
|
||||||
* <p>Default is <code>null</code>, i.e. using the default strategy of |
|
||||||
* the data binder. |
|
||||||
* @see org.springframework.validation.DataBinder#setMessageCodesResolver |
|
||||||
*/ |
|
||||||
public final void setMessageCodesResolver(MessageCodesResolver messageCodesResolver) { |
|
||||||
this.messageCodesResolver = messageCodesResolver; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the strategy to use for resolving errors into message codes. |
|
||||||
*/ |
|
||||||
public final MessageCodesResolver getMessageCodesResolver() { |
|
||||||
return this.messageCodesResolver; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Set the strategy to use for processing binding errors, that is, |
|
||||||
* required field errors and <code>PropertyAccessException</code>s. |
|
||||||
* <p>Default is <code>null</code>, that is, using the default strategy |
|
||||||
* of the data binder. |
|
||||||
* @see org.springframework.validation.DataBinder#setBindingErrorProcessor |
|
||||||
*/ |
|
||||||
public final void setBindingErrorProcessor(BindingErrorProcessor bindingErrorProcessor) { |
|
||||||
this.bindingErrorProcessor = bindingErrorProcessor; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the strategy to use for processing binding errors. |
|
||||||
*/ |
|
||||||
public final BindingErrorProcessor getBindingErrorProcessor() { |
|
||||||
return this.bindingErrorProcessor; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Specify a single PropertyEditorRegistrar to be applied |
|
||||||
* to every DataBinder that this controller uses. |
|
||||||
*/ |
|
||||||
public final void setPropertyEditorRegistrar(PropertyEditorRegistrar propertyEditorRegistrar) { |
|
||||||
this.propertyEditorRegistrars = new PropertyEditorRegistrar[] {propertyEditorRegistrar}; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Specify multiple PropertyEditorRegistrars to be applied |
|
||||||
* to every DataBinder that this controller uses. |
|
||||||
*/ |
|
||||||
public final void setPropertyEditorRegistrars(PropertyEditorRegistrar[] propertyEditorRegistrars) { |
|
||||||
this.propertyEditorRegistrars = propertyEditorRegistrars; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the PropertyEditorRegistrars to be applied |
|
||||||
* to every DataBinder that this controller uses. |
|
||||||
*/ |
|
||||||
public final PropertyEditorRegistrar[] getPropertyEditorRegistrars() { |
|
||||||
return this.propertyEditorRegistrars; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void initBinder(WebDataBinder binder, WebRequest request) { |
|
||||||
if (this.directFieldAccess) { |
|
||||||
binder.initDirectFieldAccess(); |
|
||||||
} |
|
||||||
if (this.messageCodesResolver != null) { |
|
||||||
binder.setMessageCodesResolver(this.messageCodesResolver); |
|
||||||
} |
|
||||||
if (this.bindingErrorProcessor != null) { |
|
||||||
binder.setBindingErrorProcessor(this.bindingErrorProcessor); |
|
||||||
} |
|
||||||
if (this.propertyEditorRegistrars != null) { |
|
||||||
for (int i = 0; i < this.propertyEditorRegistrars.length; i++) { |
|
||||||
this.propertyEditorRegistrars[i].registerCustomEditors(binder); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,84 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2007 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.bind.support; |
|
||||||
|
|
||||||
import org.springframework.util.Assert; |
|
||||||
import org.springframework.web.context.request.WebRequest; |
|
||||||
|
|
||||||
/** |
|
||||||
* Default implementation of the {@link SessionAttributeStore} interface, |
|
||||||
* storing the attributes in the WebRequest session (i.e. HttpSession |
|
||||||
* or PortletSession). |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5 |
|
||||||
* @see #setAttributeNamePrefix |
|
||||||
* @see org.springframework.web.context.request.WebRequest#setAttribute |
|
||||||
* @see org.springframework.web.context.request.WebRequest#getAttribute |
|
||||||
* @see org.springframework.web.context.request.WebRequest#removeAttribute |
|
||||||
*/ |
|
||||||
public class DefaultSessionAttributeStore implements SessionAttributeStore { |
|
||||||
|
|
||||||
private String attributeNamePrefix = ""; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Specify a prefix to use for the attribute names in the backend session. |
|
||||||
* <p>Default is to use no prefix, storing the session attributes with the |
|
||||||
* same name as in the model. |
|
||||||
*/ |
|
||||||
public void setAttributeNamePrefix(String attributeNamePrefix) { |
|
||||||
this.attributeNamePrefix = (attributeNamePrefix != null ? attributeNamePrefix : ""); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public void storeAttribute(WebRequest request, String attributeName, Object attributeValue) { |
|
||||||
Assert.notNull(request, "WebRequest must not be null"); |
|
||||||
Assert.notNull(attributeName, "Attribute name must not be null"); |
|
||||||
Assert.notNull(attributeValue, "Attribute value must not be null"); |
|
||||||
String storeAttributeName = getAttributeNameInSession(request, attributeName); |
|
||||||
request.setAttribute(storeAttributeName, attributeValue, WebRequest.SCOPE_SESSION); |
|
||||||
} |
|
||||||
|
|
||||||
public Object retrieveAttribute(WebRequest request, String attributeName) { |
|
||||||
Assert.notNull(request, "WebRequest must not be null"); |
|
||||||
Assert.notNull(attributeName, "Attribute name must not be null"); |
|
||||||
String storeAttributeName = getAttributeNameInSession(request, attributeName); |
|
||||||
return request.getAttribute(storeAttributeName, WebRequest.SCOPE_SESSION); |
|
||||||
} |
|
||||||
|
|
||||||
public void cleanupAttribute(WebRequest request, String attributeName) { |
|
||||||
Assert.notNull(request, "WebRequest must not be null"); |
|
||||||
Assert.notNull(attributeName, "Attribute name must not be null"); |
|
||||||
String storeAttributeName = getAttributeNameInSession(request, attributeName); |
|
||||||
request.removeAttribute(storeAttributeName, WebRequest.SCOPE_SESSION); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Calculate the attribute name in the backend session. |
|
||||||
* <p>The default implementation simply prepends the configured |
|
||||||
* {@link #setAttributeNamePrefix "attributeNamePrefix"}, if any. |
|
||||||
* @param request the current request |
|
||||||
* @param attributeName the name of the attribute |
|
||||||
* @return the attribute name in the backend session |
|
||||||
*/ |
|
||||||
protected String getAttributeNameInSession(WebRequest request, String attributeName) { |
|
||||||
return this.attributeNamePrefix + attributeName; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,59 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2007 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.bind.support; |
|
||||||
|
|
||||||
import org.springframework.web.context.request.WebRequest; |
|
||||||
|
|
||||||
/** |
|
||||||
* Strategy interface for storing model attributes in a backend session. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5 |
|
||||||
* @see org.springframework.web.bind.annotation.SessionAttributes |
|
||||||
*/ |
|
||||||
public interface SessionAttributeStore { |
|
||||||
|
|
||||||
/** |
|
||||||
* Store the supplied attribute in the backend session. |
|
||||||
* <p>Can be called for new attributes as well as for existing attributes. |
|
||||||
* In the latter case, this signals that the attribute value may have been modified. |
|
||||||
* @param request the current request |
|
||||||
* @param attributeName the name of the attribute |
|
||||||
* @param attributeValue the attribute value to store |
|
||||||
*/ |
|
||||||
void storeAttribute(WebRequest request, String attributeName, Object attributeValue); |
|
||||||
|
|
||||||
/** |
|
||||||
* Retrieve the specified attribute from the backend session. |
|
||||||
* <p>This will typically be called with the expectation that the |
|
||||||
* attribute is already present, with an exception to be thrown |
|
||||||
* if this method returns <code>null</code>. |
|
||||||
* @param request the current request |
|
||||||
* @param attributeName the name of the attribute |
|
||||||
* @return the current attribute value, or <code>null</code> if none |
|
||||||
*/ |
|
||||||
Object retrieveAttribute(WebRequest request, String attributeName); |
|
||||||
|
|
||||||
/** |
|
||||||
* Clean up the specified attribute in the backend session. |
|
||||||
* <p>Indicates that the attribute name will not be used anymore. |
|
||||||
* @param request the current request |
|
||||||
* @param attributeName the name of the attribute |
|
||||||
*/ |
|
||||||
void cleanupAttribute(WebRequest request, String attributeName); |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,47 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2007 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.bind.support; |
|
||||||
|
|
||||||
/** |
|
||||||
* Simple interface that can be injected into handler methods, allowing them to |
|
||||||
* signal that their session processing is complete. The handler invoker may |
|
||||||
* then follow up with appropriate cleanup, e.g. of session attributes which |
|
||||||
* have been implicitly created during this handler's processing (according to |
|
||||||
* the |
|
||||||
* {@link org.springframework.web.bind.annotation.SessionAttributes @SessionAttributes} |
|
||||||
* annotation). |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5 |
|
||||||
* @see org.springframework.web.bind.annotation.RequestMapping |
|
||||||
* @see org.springframework.web.bind.annotation.SessionAttributes |
|
||||||
*/ |
|
||||||
public interface SessionStatus { |
|
||||||
|
|
||||||
/** |
|
||||||
* Mark the current handler's session processing as complete, allowing for |
|
||||||
* cleanup of session attributes. |
|
||||||
*/ |
|
||||||
void setComplete(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Return whether the current handler's session processing has been marked |
|
||||||
* as complete. |
|
||||||
*/ |
|
||||||
boolean isComplete(); |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,39 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2007 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.bind.support; |
|
||||||
|
|
||||||
/** |
|
||||||
* Simple implementation of the {@link SessionStatus} interface, |
|
||||||
* keeping the <code>complete</code> flag as an instance variable. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5 |
|
||||||
*/ |
|
||||||
public class SimpleSessionStatus implements SessionStatus { |
|
||||||
|
|
||||||
private boolean complete = false; |
|
||||||
|
|
||||||
|
|
||||||
public void setComplete() { |
|
||||||
this.complete = true; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isComplete() { |
|
||||||
return this.complete; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,63 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2009 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.bind.support; |
|
||||||
|
|
||||||
import org.springframework.core.MethodParameter; |
|
||||||
import org.springframework.web.context.request.NativeWebRequest; |
|
||||||
|
|
||||||
/** |
|
||||||
* SPI for resolving custom arguments for a specific handler method parameter. |
|
||||||
* Typically implemented to detect special parameter types, resolving |
|
||||||
* well-known argument values for them. |
|
||||||
* |
|
||||||
* <p>A typical implementation could look like as follows: |
|
||||||
* |
|
||||||
* <pre class="code"> |
|
||||||
* public class MySpecialArgumentResolver implements WebArgumentResolver { |
|
||||||
* |
|
||||||
* public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) { |
|
||||||
* if (methodParameter.getParameterType().equals(MySpecialArg.class)) { |
|
||||||
* return new MySpecialArg("myValue"); |
|
||||||
* } |
|
||||||
* return UNRESOLVED; |
|
||||||
* } |
|
||||||
* }</pre> |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5.2 |
|
||||||
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#setCustomArgumentResolvers |
|
||||||
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter#setCustomArgumentResolvers |
|
||||||
*/ |
|
||||||
public interface WebArgumentResolver { |
|
||||||
|
|
||||||
/** |
|
||||||
* Marker to be returned when the resolver does not know how to |
|
||||||
* handle the given method parameter. |
|
||||||
*/ |
|
||||||
Object UNRESOLVED = new Object(); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Resolve an argument for the given handler method parameter within the given web request. |
|
||||||
* @param methodParameter the handler method parameter to resolve |
|
||||||
* @param webRequest the current web request, allowing access to the native request as well |
|
||||||
* @return the argument value, or <code>UNRESOLVED</code> if not resolvable |
|
||||||
* @throws Exception in case of resolution failure |
|
||||||
*/ |
|
||||||
Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception; |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,38 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2007 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.bind.support; |
|
||||||
|
|
||||||
import org.springframework.web.bind.WebDataBinder; |
|
||||||
import org.springframework.web.context.request.WebRequest; |
|
||||||
|
|
||||||
/** |
|
||||||
* Callback interface for initializing a {@link org.springframework.web.bind.WebDataBinder} |
|
||||||
* for performing data binding in the context of a specific web request. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5 |
|
||||||
*/ |
|
||||||
public interface WebBindingInitializer { |
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize the given DataBinder for the given request. |
|
||||||
* @param binder the DataBinder to initialize |
|
||||||
* @param request the web request that the data binding happens within |
|
||||||
*/ |
|
||||||
void initBinder(WebDataBinder binder, WebRequest request); |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,125 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.bind.support; |
|
||||||
|
|
||||||
import org.springframework.beans.MutablePropertyValues; |
|
||||||
import org.springframework.validation.BindException; |
|
||||||
import org.springframework.web.bind.WebDataBinder; |
|
||||||
import org.springframework.web.context.request.NativeWebRequest; |
|
||||||
import org.springframework.web.context.request.WebRequest; |
|
||||||
import org.springframework.web.multipart.MultipartRequest; |
|
||||||
|
|
||||||
/** |
|
||||||
* Special {@link org.springframework.validation.DataBinder} to perform data binding |
|
||||||
* from web request parameters to JavaBeans, including support for multipart files. |
|
||||||
* |
|
||||||
* <p>See the DataBinder/WebDataBinder superclasses for customization options, |
|
||||||
* which include specifying allowed/required fields, and registering custom |
|
||||||
* property editors. |
|
||||||
* |
|
||||||
* <p>Can also used for manual data binding in custom web controllers or interceptors |
|
||||||
* that build on Spring's {@link org.springframework.web.context.request.WebRequest} |
|
||||||
* abstraction: e.g. in a {@link org.springframework.web.context.request.WebRequestInterceptor} |
|
||||||
* implementation. Simply instantiate a WebRequestDataBinder for each binding |
|
||||||
* process, and invoke <code>bind</code> with the current WebRequest as argument: |
|
||||||
* |
|
||||||
* <pre class="code"> |
|
||||||
* MyBean myBean = new MyBean(); |
|
||||||
* // apply binder to custom target object
|
|
||||||
* WebRequestDataBinder binder = new WebRequestDataBinder(myBean); |
|
||||||
* // register custom editors, if desired
|
|
||||||
* binder.registerCustomEditor(...); |
|
||||||
* // trigger actual binding of request parameters
|
|
||||||
* binder.bind(request); |
|
||||||
* // optionally evaluate binding errors
|
|
||||||
* Errors errors = binder.getErrors(); |
|
||||||
* ...</pre> |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5.2 |
|
||||||
* @see #bind(org.springframework.web.context.request.WebRequest) |
|
||||||
* @see #registerCustomEditor |
|
||||||
* @see #setAllowedFields |
|
||||||
* @see #setRequiredFields |
|
||||||
* @see #setFieldMarkerPrefix |
|
||||||
*/ |
|
||||||
public class WebRequestDataBinder extends WebDataBinder { |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a new WebRequestDataBinder instance, with default object name. |
|
||||||
* @param target the target object to bind onto (or <code>null</code> |
|
||||||
* if the binder is just used to convert a plain parameter value) |
|
||||||
* @see #DEFAULT_OBJECT_NAME |
|
||||||
*/ |
|
||||||
public WebRequestDataBinder(Object target) { |
|
||||||
super(target); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a new WebRequestDataBinder instance. |
|
||||||
* @param target the target object to bind onto (or <code>null</code> |
|
||||||
* if the binder is just used to convert a plain parameter value) |
|
||||||
* @param objectName the name of the target object |
|
||||||
*/ |
|
||||||
public WebRequestDataBinder(Object target, String objectName) { |
|
||||||
super(target, objectName); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Bind the parameters of the given request to this binder's target, |
|
||||||
* also binding multipart files in case of a multipart request. |
|
||||||
* <p>This call can create field errors, representing basic binding |
|
||||||
* errors like a required field (code "required"), or type mismatch |
|
||||||
* between value and bean property (code "typeMismatch"). |
|
||||||
* <p>Multipart files are bound via their parameter name, just like normal |
|
||||||
* HTTP parameters: i.e. "uploadedFile" to an "uploadedFile" bean property, |
|
||||||
* invoking a "setUploadedFile" setter method. |
|
||||||
* <p>The type of the target property for a multipart file can be MultipartFile, |
|
||||||
* byte[], or String. The latter two receive the contents of the uploaded file; |
|
||||||
* all metadata like original file name, content type, etc are lost in those cases. |
|
||||||
* @param request request with parameters to bind (can be multipart) |
|
||||||
* @see org.springframework.web.multipart.MultipartRequest |
|
||||||
* @see org.springframework.web.multipart.MultipartFile |
|
||||||
* @see #bindMultipartFiles |
|
||||||
* @see #bind(org.springframework.beans.PropertyValues) |
|
||||||
*/ |
|
||||||
public void bind(WebRequest request) { |
|
||||||
MutablePropertyValues mpvs = new MutablePropertyValues(request.getParameterMap()); |
|
||||||
if (request instanceof NativeWebRequest) { |
|
||||||
Object nativeRequest = ((NativeWebRequest) request).getNativeRequest(); |
|
||||||
if (nativeRequest instanceof MultipartRequest) { |
|
||||||
MultipartRequest multipartRequest = (MultipartRequest) request; |
|
||||||
bindMultipartFiles(multipartRequest.getFileMap(), mpvs); |
|
||||||
} |
|
||||||
} |
|
||||||
doBind(mpvs); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Treats errors as fatal. |
|
||||||
* <p>Use this method only if it's an error if the input isn't valid. |
|
||||||
* This might be appropriate if all input is from dropdowns, for example. |
|
||||||
* @throws BindException if binding errors have been encountered |
|
||||||
*/ |
|
||||||
public void closeNoCatch() throws BindException { |
|
||||||
if (getBindingResult().hasErrors()) { |
|
||||||
throw new BindException(getBindingResult()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,8 +0,0 @@ |
|||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* Support classes for web data binding. |
|
||||||
* |
|
||||||
*/ |
|
||||||
package org.springframework.web.bind.support; |
|
||||||
|
|
||||||
@ -1,57 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2005 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.multipart; |
|
||||||
|
|
||||||
/** |
|
||||||
* MultipartException subclass thrown when an upload exceeds the |
|
||||||
* maximum upload size allowed. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 1.0.1 |
|
||||||
*/ |
|
||||||
public class MaxUploadSizeExceededException extends MultipartException { |
|
||||||
|
|
||||||
private final long maxUploadSize; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Constructor for MaxUploadSizeExceededException. |
|
||||||
* @param maxUploadSize the maximum upload size allowed |
|
||||||
*/ |
|
||||||
public MaxUploadSizeExceededException(long maxUploadSize) { |
|
||||||
this(maxUploadSize, null); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Constructor for MaxUploadSizeExceededException. |
|
||||||
* @param maxUploadSize the maximum upload size allowed |
|
||||||
* @param ex root cause from multipart parsing API in use |
|
||||||
*/ |
|
||||||
public MaxUploadSizeExceededException(long maxUploadSize, Throwable ex) { |
|
||||||
super("Maximum upload size of " + maxUploadSize + " bytes exceeded", ex); |
|
||||||
this.maxUploadSize = maxUploadSize; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Return the maximum upload size allowed. |
|
||||||
*/ |
|
||||||
public long getMaxUploadSize() { |
|
||||||
return maxUploadSize; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,49 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2007 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.multipart; |
|
||||||
|
|
||||||
import org.springframework.core.NestedRuntimeException; |
|
||||||
|
|
||||||
/** |
|
||||||
* Exception thrown when multipart resolution fails. |
|
||||||
* |
|
||||||
* @author Trevor D. Cook |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 29.09.2003 |
|
||||||
* @see MultipartResolver#resolveMultipart |
|
||||||
* @see org.springframework.web.multipart.support.MultipartFilter |
|
||||||
*/ |
|
||||||
public class MultipartException extends NestedRuntimeException { |
|
||||||
|
|
||||||
/** |
|
||||||
* Constructor for MultipartException. |
|
||||||
* @param msg the detail message |
|
||||||
*/ |
|
||||||
public MultipartException(String msg) { |
|
||||||
super(msg); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Constructor for MultipartException. |
|
||||||
* @param msg the detail message |
|
||||||
* @param cause the root cause from the multipart parsing API in use |
|
||||||
*/ |
|
||||||
public MultipartException(String msg, Throwable cause) { |
|
||||||
super(msg, cause); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,103 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2006 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.multipart; |
|
||||||
|
|
||||||
import java.io.File; |
|
||||||
import java.io.IOException; |
|
||||||
import java.io.InputStream; |
|
||||||
|
|
||||||
/** |
|
||||||
* A representation of an uploaded file received in a multipart request. |
|
||||||
* |
|
||||||
* <p>The file contents are either stored in memory or temporarily on disk. |
|
||||||
* In either case, the user is responsible for copying file contents to a |
|
||||||
* session-level or persistent store as and if desired. The temporary storages |
|
||||||
* will be cleared at the end of request processing. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @author Trevor D. Cook |
|
||||||
* @since 29.09.2003 |
|
||||||
* @see org.springframework.web.multipart.MultipartHttpServletRequest |
|
||||||
* @see org.springframework.web.multipart.MultipartResolver |
|
||||||
*/ |
|
||||||
public interface MultipartFile { |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the name of the parameter in the multipart form. |
|
||||||
* @return the name of the parameter (never <code>null</code> or empty) |
|
||||||
*/ |
|
||||||
String getName(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the original filename in the client's filesystem. |
|
||||||
* <p>This may contain path information depending on the browser used, |
|
||||||
* but it typically will not with any other than Opera. |
|
||||||
* @return the original filename, or the empty String if no file |
|
||||||
* has been chosen in the multipart form |
|
||||||
*/ |
|
||||||
String getOriginalFilename(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the content type of the file. |
|
||||||
* @return the content type, or <code>null</code> if not defined |
|
||||||
* (or no file has been chosen in the multipart form) |
|
||||||
*/ |
|
||||||
String getContentType(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Return whether the uploaded file is empty, that is, either no file has |
|
||||||
* been chosen in the multipart form or the chosen file has no content. |
|
||||||
*/ |
|
||||||
boolean isEmpty(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the size of the file in bytes. |
|
||||||
* @return the size of the file, or 0 if empty |
|
||||||
*/ |
|
||||||
long getSize(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the contents of the file as an array of bytes. |
|
||||||
* @return the contents of the file as bytes, or an empty byte array if empty |
|
||||||
* @throws IOException in case of access errors (if the temporary store fails) |
|
||||||
*/ |
|
||||||
byte[] getBytes() throws IOException; |
|
||||||
|
|
||||||
/** |
|
||||||
* Return an InputStream to read the contents of the file from. |
|
||||||
* The user is responsible for closing the stream. |
|
||||||
* @return the contents of the file as stream, or an empty stream if empty |
|
||||||
* @throws IOException in case of access errors (if the temporary store fails) |
|
||||||
*/ |
|
||||||
InputStream getInputStream() throws IOException; |
|
||||||
|
|
||||||
/** |
|
||||||
* Transfer the received file to the given destination file. |
|
||||||
* <p>This may either move the file in the filesystem, copy the file in the |
|
||||||
* filesystem, or save memory-held contents to the destination file. |
|
||||||
* If the destination file already exists, it will be deleted first. |
|
||||||
* <p>If the file has been moved in the filesystem, this operation cannot |
|
||||||
* be invoked again. Therefore, call this method just once to be able to |
|
||||||
* work with any storage mechanism. |
|
||||||
* @param dest the destination file |
|
||||||
* @throws IOException in case of reading or writing errors |
|
||||||
* @throws IllegalStateException if the file has already been moved |
|
||||||
* in the filesystem and is not available anymore for another transfer |
|
||||||
*/ |
|
||||||
void transferTo(File dest) throws IOException, IllegalStateException; |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,47 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.multipart; |
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest; |
|
||||||
|
|
||||||
/** |
|
||||||
* Provides additional methods for dealing with multipart content within a |
|
||||||
* servlet request, allowing to access uploaded files. |
|
||||||
* Implementations also need to override the standard |
|
||||||
* {@link javax.servlet.ServletRequest} methods for parameter access, making |
|
||||||
* multipart parameters available. |
|
||||||
* |
|
||||||
* <p>A concrete implementation is |
|
||||||
* {@link org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest}. |
|
||||||
* As an intermediate step, |
|
||||||
* {@link org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest} |
|
||||||
* can be subclassed. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @author Trevor D. Cook |
|
||||||
* @since 29.09.2003 |
|
||||||
* @see MultipartResolver |
|
||||||
* @see MultipartFile |
|
||||||
* @see javax.servlet.http.HttpServletRequest#getParameter |
|
||||||
* @see javax.servlet.http.HttpServletRequest#getParameterNames |
|
||||||
* @see javax.servlet.http.HttpServletRequest#getParameterMap |
|
||||||
* @see org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest |
|
||||||
* @see org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest |
|
||||||
*/ |
|
||||||
public interface MultipartHttpServletRequest extends HttpServletRequest, MultipartRequest { |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,58 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.multipart; |
|
||||||
|
|
||||||
import java.util.Iterator; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
/** |
|
||||||
* This interface defines the multipart request access operations |
|
||||||
* that are exposed for actual multipart requests. It is extended |
|
||||||
* by {@link MultipartHttpServletRequest} and the Portlet |
|
||||||
* {@link org.springframework.web.portlet.multipart.MultipartActionRequest}. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.5.2 |
|
||||||
*/ |
|
||||||
public interface MultipartRequest { |
|
||||||
|
|
||||||
/** |
|
||||||
* Return an {@link java.util.Iterator} of String objects containing the |
|
||||||
* parameter names of the multipart files contained in this request. These |
|
||||||
* are the field names of the form (like with normal parameters), not the |
|
||||||
* original file names. |
|
||||||
* @return the names of the files |
|
||||||
*/ |
|
||||||
Iterator<String> getFileNames(); |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the contents plus description of an uploaded file in this request, |
|
||||||
* or <code>null</code> if it does not exist. |
|
||||||
* @param name a String specifying the parameter name of the multipart file |
|
||||||
* @return the uploaded content in the form of a {@link org.springframework.web.multipart.MultipartFile} object |
|
||||||
*/ |
|
||||||
MultipartFile getFile(String name); |
|
||||||
|
|
||||||
/** |
|
||||||
* Return a {@link java.util.Map} of the multipart files contained in this request. |
|
||||||
* @return a map containing the parameter names as keys, and the |
|
||||||
* {@link org.springframework.web.multipart.MultipartFile} objects as values |
|
||||||
* @see MultipartFile |
|
||||||
*/ |
|
||||||
Map<String, MultipartFile> getFileMap(); |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,127 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2007 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.multipart; |
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest; |
|
||||||
|
|
||||||
/** |
|
||||||
* A strategy interface for multipart file upload resolution in accordance |
|
||||||
* with <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>. |
|
||||||
* Implementations are typically usable both within an application context |
|
||||||
* and standalone. |
|
||||||
* |
|
||||||
* <p>There is only one concrete implementation included in Spring, |
|
||||||
* as of Spring 2.5: |
|
||||||
* <ul> |
|
||||||
* <li>{@link org.springframework.web.multipart.commons.CommonsMultipartResolver} for Jakarta Commons FileUpload |
|
||||||
* </ul> |
|
||||||
* |
|
||||||
* <p>There is no default resolver implementation used for Spring |
|
||||||
* {@link org.springframework.web.servlet.DispatcherServlet DispatcherServlets}, |
|
||||||
* as an application might choose to parse its multipart requests itself. To define |
|
||||||
* an implementation, create a bean with the id "multipartResolver" in a |
|
||||||
* {@link org.springframework.web.servlet.DispatcherServlet DispatcherServlet's} |
|
||||||
* application context. Such a resolver gets applied to all requests handled |
|
||||||
* by that {@link org.springframework.web.servlet.DispatcherServlet}. |
|
||||||
* |
|
||||||
* <p>If a {@link org.springframework.web.servlet.DispatcherServlet} detects |
|
||||||
* a multipart request, it will resolve it via the configured |
|
||||||
* {@link org.springframework.web.multipart.MultipartResolver} and pass on a |
|
||||||
* wrapped {@link javax.servlet.http.HttpServletRequest}. |
|
||||||
* Controllers can then cast their given request to the |
|
||||||
* {@link org.springframework.web.multipart.MultipartHttpServletRequest} |
|
||||||
* interface, which permits access to any |
|
||||||
* {@link org.springframework.web.multipart.MultipartFile MultipartFiles}. |
|
||||||
* Note that this cast is only supported in case of an actual multipart request. |
|
||||||
* |
|
||||||
* <pre class="code"> |
|
||||||
* public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { |
|
||||||
* MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; |
|
||||||
* MultipartFile multipartFile = multipartRequest.getFile("image"); |
|
||||||
* ... |
|
||||||
* }</pre> |
|
||||||
* |
|
||||||
* Instead of direct access, command or form controllers can register a |
|
||||||
* {@link org.springframework.web.multipart.support.ByteArrayMultipartFileEditor} |
|
||||||
* or {@link org.springframework.web.multipart.support.StringMultipartFileEditor} |
|
||||||
* with their data binder, to automatically apply multipart content to command |
|
||||||
* bean properties. |
|
||||||
* |
|
||||||
* <p>As an alternative to using a |
|
||||||
* {@link org.springframework.web.multipart.MultipartResolver} with a |
|
||||||
* {@link org.springframework.web.servlet.DispatcherServlet}, |
|
||||||
* a {@link org.springframework.web.multipart.support.MultipartFilter} can be |
|
||||||
* registered in <code>web.xml</code>. It will delegate to a corresponding |
|
||||||
* {@link org.springframework.web.multipart.MultipartResolver} bean in the root |
|
||||||
* application context. This is mainly intended for applications that do not |
|
||||||
* use Spring's own web MVC framework. |
|
||||||
* |
|
||||||
* <p>Note: There is hardly ever a need to access the |
|
||||||
* {@link org.springframework.web.multipart.MultipartResolver} itself |
|
||||||
* from application code. It will simply do its work behind the scenes, |
|
||||||
* making |
|
||||||
* {@link org.springframework.web.multipart.MultipartHttpServletRequest MultipartHttpServletRequests} |
|
||||||
* available to controllers. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @author Trevor D. Cook |
|
||||||
* @since 29.09.2003 |
|
||||||
* @see MultipartHttpServletRequest |
|
||||||
* @see MultipartFile |
|
||||||
* @see org.springframework.web.multipart.commons.CommonsMultipartResolver |
|
||||||
* @see org.springframework.web.multipart.support.ByteArrayMultipartFileEditor |
|
||||||
* @see org.springframework.web.multipart.support.StringMultipartFileEditor |
|
||||||
* @see org.springframework.web.servlet.DispatcherServlet |
|
||||||
*/ |
|
||||||
public interface MultipartResolver { |
|
||||||
|
|
||||||
/** |
|
||||||
* Determine if the given request contains multipart content. |
|
||||||
* <p>Will typically check for content type "multipart/form-data", but the actually |
|
||||||
* accepted requests might depend on the capabilities of the resolver implementation. |
|
||||||
* @param request the servlet request to be evaluated |
|
||||||
* @return whether the request contains multipart content |
|
||||||
*/ |
|
||||||
boolean isMultipart(HttpServletRequest request); |
|
||||||
|
|
||||||
/** |
|
||||||
* Parse the given HTTP request into multipart files and parameters, |
|
||||||
* and wrap the request inside a |
|
||||||
* {@link org.springframework.web.multipart.MultipartHttpServletRequest} object |
|
||||||
* that provides access to file descriptors and makes contained |
|
||||||
* parameters accessible via the standard ServletRequest methods. |
|
||||||
* @param request the servlet request to wrap (must be of a multipart content type) |
|
||||||
* @return the wrapped servlet request |
|
||||||
* @throws MultipartException if the servlet request is not multipart, or if |
|
||||||
* implementation-specific problems are encountered (such as exceeding file size limits) |
|
||||||
* @see MultipartHttpServletRequest#getFile |
|
||||||
* @see MultipartHttpServletRequest#getFileNames |
|
||||||
* @see MultipartHttpServletRequest#getFileMap |
|
||||||
* @see javax.servlet.http.HttpServletRequest#getParameter |
|
||||||
* @see javax.servlet.http.HttpServletRequest#getParameterNames |
|
||||||
* @see javax.servlet.http.HttpServletRequest#getParameterMap |
|
||||||
*/ |
|
||||||
MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException; |
|
||||||
|
|
||||||
/** |
|
||||||
* Cleanup any resources used for the multipart handling, |
|
||||||
* like a storage for the uploaded files. |
|
||||||
* @param request the request to cleanup resources for |
|
||||||
*/ |
|
||||||
void cleanupMultipart(MultipartHttpServletRequest request); |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,322 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.multipart.commons; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.io.UnsupportedEncodingException; |
|
||||||
import java.util.Collection; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import org.apache.commons.fileupload.FileItem; |
|
||||||
import org.apache.commons.fileupload.FileItemFactory; |
|
||||||
import org.apache.commons.fileupload.FileUpload; |
|
||||||
import org.apache.commons.fileupload.disk.DiskFileItemFactory; |
|
||||||
import org.apache.commons.logging.Log; |
|
||||||
import org.apache.commons.logging.LogFactory; |
|
||||||
|
|
||||||
import org.springframework.core.io.Resource; |
|
||||||
import org.springframework.util.StringUtils; |
|
||||||
import org.springframework.web.multipart.MultipartException; |
|
||||||
import org.springframework.web.multipart.MultipartFile; |
|
||||||
import org.springframework.web.util.WebUtils; |
|
||||||
|
|
||||||
/** |
|
||||||
* Base class for multipart resolvers that use Jakarta Commons FileUpload |
|
||||||
* 1.1 or higher. |
|
||||||
* |
|
||||||
* <p>Provides common configuration properties and parsing functionality |
|
||||||
* for multipart requests, using a Map of Spring CommonsMultipartFile instances |
|
||||||
* as representation of uploaded files and a String-based parameter Map as |
|
||||||
* representation of uploaded form fields. |
|
||||||
* |
|
||||||
* <p>Subclasses implement concrete resolution strategies for Servlet or Portlet |
|
||||||
* environments: see CommonsMultipartResolver and CommonsPortletMultipartResolver, |
|
||||||
* respectively. This base class is not tied to either of those APIs, factoring |
|
||||||
* out common functionality. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 2.0 |
|
||||||
* @see CommonsMultipartFile |
|
||||||
* @see CommonsMultipartResolver |
|
||||||
* @see org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver |
|
||||||
*/ |
|
||||||
public abstract class CommonsFileUploadSupport { |
|
||||||
|
|
||||||
protected final Log logger = LogFactory.getLog(getClass()); |
|
||||||
|
|
||||||
private final DiskFileItemFactory fileItemFactory; |
|
||||||
|
|
||||||
private final FileUpload fileUpload; |
|
||||||
|
|
||||||
private boolean uploadTempDirSpecified = false; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Instantiate a new CommonsFileUploadSupport with its |
|
||||||
* corresponding FileItemFactory and FileUpload instances. |
|
||||||
* @see #newFileItemFactory |
|
||||||
* @see #newFileUpload |
|
||||||
*/ |
|
||||||
public CommonsFileUploadSupport() { |
|
||||||
this.fileItemFactory = newFileItemFactory(); |
|
||||||
this.fileUpload = newFileUpload(getFileItemFactory()); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Return the underlying <code>org.apache.commons.fileupload.disk.DiskFileItemFactory</code> |
|
||||||
* instance. There is hardly any need to access this. |
|
||||||
* @return the underlying DiskFileItemFactory instance |
|
||||||
*/ |
|
||||||
public DiskFileItemFactory getFileItemFactory() { |
|
||||||
return this.fileItemFactory; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the underlying <code>org.apache.commons.fileupload.FileUpload</code> |
|
||||||
* instance. There is hardly any need to access this. |
|
||||||
* @return the underlying FileUpload instance |
|
||||||
*/ |
|
||||||
public FileUpload getFileUpload() { |
|
||||||
return this.fileUpload; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Set the maximum allowed size (in bytes) before uploads are refused. |
|
||||||
* -1 indicates no limit (the default). |
|
||||||
* @param maxUploadSize the maximum upload size allowed |
|
||||||
* @see org.apache.commons.fileupload.FileUploadBase#setSizeMax |
|
||||||
*/ |
|
||||||
public void setMaxUploadSize(long maxUploadSize) { |
|
||||||
this.fileUpload.setSizeMax(maxUploadSize); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Set the maximum allowed size (in bytes) before uploads are written to disk. |
|
||||||
* Uploaded files will still be received past this amount, but they will not be |
|
||||||
* stored in memory. Default is 10240, according to Commons FileUpload. |
|
||||||
* @param maxInMemorySize the maximum in memory size allowed |
|
||||||
* @see org.apache.commons.fileupload.disk.DiskFileItemFactory#setSizeThreshold |
|
||||||
*/ |
|
||||||
public void setMaxInMemorySize(int maxInMemorySize) { |
|
||||||
this.fileItemFactory.setSizeThreshold(maxInMemorySize); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Set the default character encoding to use for parsing requests, |
|
||||||
* to be applied to headers of individual parts and to form fields. |
|
||||||
* Default is ISO-8859-1, according to the Servlet spec. |
|
||||||
* <p>If the request specifies a character encoding itself, the request |
|
||||||
* encoding will override this setting. This also allows for generically |
|
||||||
* overriding the character encoding in a filter that invokes the |
|
||||||
* <code>ServletRequest.setCharacterEncoding</code> method. |
|
||||||
* @param defaultEncoding the character encoding to use |
|
||||||
* @see javax.servlet.ServletRequest#getCharacterEncoding |
|
||||||
* @see javax.servlet.ServletRequest#setCharacterEncoding |
|
||||||
* @see WebUtils#DEFAULT_CHARACTER_ENCODING |
|
||||||
* @see org.apache.commons.fileupload.FileUploadBase#setHeaderEncoding |
|
||||||
*/ |
|
||||||
public void setDefaultEncoding(String defaultEncoding) { |
|
||||||
this.fileUpload.setHeaderEncoding(defaultEncoding); |
|
||||||
} |
|
||||||
|
|
||||||
protected String getDefaultEncoding() { |
|
||||||
String encoding = getFileUpload().getHeaderEncoding(); |
|
||||||
if (encoding == null) { |
|
||||||
encoding = WebUtils.DEFAULT_CHARACTER_ENCODING; |
|
||||||
} |
|
||||||
return encoding; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Set the temporary directory where uploaded files get stored. |
|
||||||
* Default is the servlet container's temporary directory for the web application. |
|
||||||
* @see org.springframework.web.util.WebUtils#TEMP_DIR_CONTEXT_ATTRIBUTE |
|
||||||
*/ |
|
||||||
public void setUploadTempDir(Resource uploadTempDir) throws IOException { |
|
||||||
if (!uploadTempDir.exists() && !uploadTempDir.getFile().mkdirs()) { |
|
||||||
throw new IllegalArgumentException("Given uploadTempDir [" + uploadTempDir + "] could not be created"); |
|
||||||
} |
|
||||||
this.fileItemFactory.setRepository(uploadTempDir.getFile()); |
|
||||||
this.uploadTempDirSpecified = true; |
|
||||||
} |
|
||||||
|
|
||||||
protected boolean isUploadTempDirSpecified() { |
|
||||||
return this.uploadTempDirSpecified; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Factory method for a Commons DiskFileItemFactory instance. |
|
||||||
* <p>Default implementation returns a standard DiskFileItemFactory. |
|
||||||
* Can be overridden to use a custom subclass, e.g. for testing purposes. |
|
||||||
* @return the new DiskFileItemFactory instance |
|
||||||
*/ |
|
||||||
protected DiskFileItemFactory newFileItemFactory() { |
|
||||||
return new DiskFileItemFactory(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Factory method for a Commons FileUpload instance. |
|
||||||
* <p><b>To be implemented by subclasses.</b> |
|
||||||
* @param fileItemFactory the Commons FileItemFactory to build upon |
|
||||||
* @return the Commons FileUpload instance |
|
||||||
*/ |
|
||||||
protected abstract FileUpload newFileUpload(FileItemFactory fileItemFactory); |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Determine an appropriate FileUpload instance for the given encoding. |
|
||||||
* <p>Default implementation returns the shared FileUpload instance |
|
||||||
* if the encoding matches, else creates a new FileUpload instance |
|
||||||
* with the same configuration other than the desired encoding. |
|
||||||
* @param encoding the character encoding to use |
|
||||||
* @return an appropriate FileUpload instance. |
|
||||||
*/ |
|
||||||
protected FileUpload prepareFileUpload(String encoding) { |
|
||||||
FileUpload fileUpload = getFileUpload(); |
|
||||||
FileUpload actualFileUpload = fileUpload; |
|
||||||
|
|
||||||
// Use new temporary FileUpload instance if the request specifies
|
|
||||||
// its own encoding that does not match the default encoding.
|
|
||||||
if (encoding != null && !encoding.equals(fileUpload.getHeaderEncoding())) { |
|
||||||
actualFileUpload = newFileUpload(getFileItemFactory()); |
|
||||||
actualFileUpload.setSizeMax(fileUpload.getSizeMax()); |
|
||||||
actualFileUpload.setHeaderEncoding(encoding); |
|
||||||
} |
|
||||||
|
|
||||||
return actualFileUpload; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Parse the given List of Commons FileItems into a Spring MultipartParsingResult, |
|
||||||
* containing Spring MultipartFile instances and a Map of multipart parameter. |
|
||||||
* @param fileItems the Commons FileIterms to parse |
|
||||||
* @param encoding the encoding to use for form fields |
|
||||||
* @return the Spring MultipartParsingResult |
|
||||||
* @see CommonsMultipartFile#CommonsMultipartFile(org.apache.commons.fileupload.FileItem) |
|
||||||
*/ |
|
||||||
protected MultipartParsingResult parseFileItems(List<FileItem> fileItems, String encoding) { |
|
||||||
Map<String, MultipartFile> multipartFiles = new HashMap<String, MultipartFile>(); |
|
||||||
Map<String, String[]> multipartParameters = new HashMap<String, String[]>(); |
|
||||||
|
|
||||||
// Extract multipart files and multipart parameters.
|
|
||||||
for (FileItem fileItem : fileItems) { |
|
||||||
if (fileItem.isFormField()) { |
|
||||||
String value = null; |
|
||||||
if (encoding != null) { |
|
||||||
try { |
|
||||||
value = fileItem.getString(encoding); |
|
||||||
} |
|
||||||
catch (UnsupportedEncodingException ex) { |
|
||||||
if (logger.isWarnEnabled()) { |
|
||||||
logger.warn("Could not decode multipart item '" + fileItem.getFieldName() + |
|
||||||
"' with encoding '" + encoding + "': using platform default"); |
|
||||||
} |
|
||||||
value = fileItem.getString(); |
|
||||||
} |
|
||||||
} |
|
||||||
else { |
|
||||||
value = fileItem.getString(); |
|
||||||
} |
|
||||||
String[] curParam = multipartParameters.get(fileItem.getFieldName()); |
|
||||||
if (curParam == null) { |
|
||||||
// simple form field
|
|
||||||
multipartParameters.put(fileItem.getFieldName(), new String[] {value}); |
|
||||||
} |
|
||||||
else { |
|
||||||
// array of simple form fields
|
|
||||||
String[] newParam = StringUtils.addStringToArray(curParam, value); |
|
||||||
multipartParameters.put(fileItem.getFieldName(), newParam); |
|
||||||
} |
|
||||||
} |
|
||||||
else { |
|
||||||
// multipart file field
|
|
||||||
CommonsMultipartFile file = new CommonsMultipartFile(fileItem); |
|
||||||
if (multipartFiles.put(file.getName(), file) != null) { |
|
||||||
throw new MultipartException("Multiple files for field name [" + file.getName() + |
|
||||||
"] found - not supported by MultipartResolver"); |
|
||||||
} |
|
||||||
if (logger.isDebugEnabled()) { |
|
||||||
logger.debug("Found multipart file [" + file.getName() + "] of size " + file.getSize() + |
|
||||||
" bytes with original filename [" + file.getOriginalFilename() + "], stored " + |
|
||||||
file.getStorageDescription()); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return new MultipartParsingResult(multipartFiles, multipartParameters); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Cleanup the Spring MultipartFiles created during multipart parsing, |
|
||||||
* potentially holding temporary data on disk. |
|
||||||
* <p>Deletes the underlying Commons FileItem instances. |
|
||||||
* @param multipartFiles Collection of MultipartFile instances |
|
||||||
* @see org.apache.commons.fileupload.FileItem#delete() |
|
||||||
*/ |
|
||||||
protected void cleanupFileItems(Collection<MultipartFile> multipartFiles) { |
|
||||||
for (MultipartFile file : multipartFiles) { |
|
||||||
if (file instanceof CommonsMultipartFile) { |
|
||||||
CommonsMultipartFile cmf = (CommonsMultipartFile) file; |
|
||||||
cmf.getFileItem().delete(); |
|
||||||
if (logger.isDebugEnabled()) { |
|
||||||
logger.debug("Cleaning up multipart file [" + cmf.getName() + "] with original filename [" + |
|
||||||
cmf.getOriginalFilename() + "], stored " + cmf.getStorageDescription()); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Holder for a Map of Spring MultipartFiles and a Map of |
|
||||||
* multipart parameters. |
|
||||||
*/ |
|
||||||
protected static class MultipartParsingResult { |
|
||||||
|
|
||||||
private final Map<String, MultipartFile> multipartFiles; |
|
||||||
|
|
||||||
private final Map<String, String[]> multipartParameters; |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a new MultipartParsingResult. |
|
||||||
* @param mpFiles Map of field name to MultipartFile instance |
|
||||||
* @param mpParams Map of field name to form field String value |
|
||||||
*/ |
|
||||||
public MultipartParsingResult(Map<String, MultipartFile> mpFiles, Map<String, String[]> mpParams) { |
|
||||||
this.multipartFiles = mpFiles; |
|
||||||
this.multipartParameters = mpParams; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the multipart files as Map of field name to MultipartFile instance. |
|
||||||
*/ |
|
||||||
public Map<String, MultipartFile> getMultipartFiles() { |
|
||||||
return this.multipartFiles; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the multipart parameters as Map of field name to form field String value. |
|
||||||
*/ |
|
||||||
public Map<String, String[]> getMultipartParameters() { |
|
||||||
return this.multipartParameters; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,194 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2006 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.multipart.commons; |
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream; |
|
||||||
import java.io.File; |
|
||||||
import java.io.IOException; |
|
||||||
import java.io.InputStream; |
|
||||||
import java.io.Serializable; |
|
||||||
|
|
||||||
import org.apache.commons.fileupload.FileItem; |
|
||||||
import org.apache.commons.fileupload.FileUploadException; |
|
||||||
import org.apache.commons.fileupload.disk.DiskFileItem; |
|
||||||
import org.apache.commons.logging.Log; |
|
||||||
import org.apache.commons.logging.LogFactory; |
|
||||||
|
|
||||||
import org.springframework.web.multipart.MultipartFile; |
|
||||||
|
|
||||||
/** |
|
||||||
* MultipartFile implementation for Jakarta Commons FileUpload. |
|
||||||
* |
|
||||||
* <p><b>NOTE:</b> As of Spring 2.0, this class requires Commons FileUpload 1.1 |
|
||||||
* or higher. The implementation does not use any deprecated FileUpload 1.0 API |
|
||||||
* anymore, to be compatible with future Commons FileUpload releases. |
|
||||||
* |
|
||||||
* @author Trevor D. Cook |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 29.09.2003 |
|
||||||
* @see CommonsMultipartResolver |
|
||||||
*/ |
|
||||||
public class CommonsMultipartFile implements MultipartFile, Serializable { |
|
||||||
|
|
||||||
protected static final Log logger = LogFactory.getLog(CommonsMultipartFile.class); |
|
||||||
|
|
||||||
private final FileItem fileItem; |
|
||||||
|
|
||||||
private final long size; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Create an instance wrapping the given FileItem. |
|
||||||
* @param fileItem the FileItem to wrap |
|
||||||
*/ |
|
||||||
public CommonsMultipartFile(FileItem fileItem) { |
|
||||||
this.fileItem = fileItem; |
|
||||||
this.size = this.fileItem.getSize(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the underlying <code>org.apache.commons.fileupload.FileItem</code> |
|
||||||
* instance. There is hardly any need to access this. |
|
||||||
*/ |
|
||||||
public final FileItem getFileItem() { |
|
||||||
return this.fileItem; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public String getName() { |
|
||||||
return this.fileItem.getFieldName(); |
|
||||||
} |
|
||||||
|
|
||||||
public String getOriginalFilename() { |
|
||||||
String filename = this.fileItem.getName(); |
|
||||||
if (filename == null) { |
|
||||||
// Should never happen.
|
|
||||||
return ""; |
|
||||||
} |
|
||||||
// check for Unix-style path
|
|
||||||
int pos = filename.lastIndexOf("/"); |
|
||||||
if (pos == -1) { |
|
||||||
// check for Windows-style path
|
|
||||||
pos = filename.lastIndexOf("\\"); |
|
||||||
} |
|
||||||
if (pos != -1) { |
|
||||||
// any sort of path separator found
|
|
||||||
return filename.substring(pos + 1); |
|
||||||
} |
|
||||||
else { |
|
||||||
// plain name
|
|
||||||
return filename; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public String getContentType() { |
|
||||||
return this.fileItem.getContentType(); |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isEmpty() { |
|
||||||
return (this.size == 0); |
|
||||||
} |
|
||||||
|
|
||||||
public long getSize() { |
|
||||||
return this.size; |
|
||||||
} |
|
||||||
|
|
||||||
public byte[] getBytes() { |
|
||||||
if (!isAvailable()) { |
|
||||||
throw new IllegalStateException("File has been moved - cannot be read again"); |
|
||||||
} |
|
||||||
byte[] bytes = this.fileItem.get(); |
|
||||||
return (bytes != null ? bytes : new byte[0]); |
|
||||||
} |
|
||||||
|
|
||||||
public InputStream getInputStream() throws IOException { |
|
||||||
if (!isAvailable()) { |
|
||||||
throw new IllegalStateException("File has been moved - cannot be read again"); |
|
||||||
} |
|
||||||
InputStream inputStream = this.fileItem.getInputStream(); |
|
||||||
return (inputStream != null ? inputStream : new ByteArrayInputStream(new byte[0])); |
|
||||||
} |
|
||||||
|
|
||||||
public void transferTo(File dest) throws IOException, IllegalStateException { |
|
||||||
if (!isAvailable()) { |
|
||||||
throw new IllegalStateException("File has already been moved - cannot be transferred again"); |
|
||||||
} |
|
||||||
|
|
||||||
if (dest.exists() && !dest.delete()) { |
|
||||||
throw new IOException( |
|
||||||
"Destination file [" + dest.getAbsolutePath() + "] already exists and could not be deleted"); |
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
this.fileItem.write(dest); |
|
||||||
if (logger.isDebugEnabled()) { |
|
||||||
String action = "transferred"; |
|
||||||
if (!this.fileItem.isInMemory()) { |
|
||||||
action = isAvailable() ? "copied" : "moved"; |
|
||||||
} |
|
||||||
logger.debug("Multipart file '" + getName() + "' with original filename [" + |
|
||||||
getOriginalFilename() + "], stored " + getStorageDescription() + ": " + |
|
||||||
action + " to [" + dest.getAbsolutePath() + "]"); |
|
||||||
} |
|
||||||
} |
|
||||||
catch (FileUploadException ex) { |
|
||||||
throw new IllegalStateException(ex.getMessage()); |
|
||||||
} |
|
||||||
catch (IOException ex) { |
|
||||||
throw ex; |
|
||||||
} |
|
||||||
catch (Exception ex) { |
|
||||||
logger.error("Could not transfer to file", ex); |
|
||||||
throw new IOException("Could not transfer to file: " + ex.getMessage()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Determine whether the multipart content is still available. |
|
||||||
* If a temporary file has been moved, the content is no longer available. |
|
||||||
*/ |
|
||||||
protected boolean isAvailable() { |
|
||||||
// If in memory, it's available.
|
|
||||||
if (this.fileItem.isInMemory()) { |
|
||||||
return true; |
|
||||||
} |
|
||||||
// Check actual existence of temporary file.
|
|
||||||
if (this.fileItem instanceof DiskFileItem) { |
|
||||||
return ((DiskFileItem) this.fileItem).getStoreLocation().exists(); |
|
||||||
} |
|
||||||
// Check whether current file size is different than original one.
|
|
||||||
return (this.fileItem.getSize() == this.size); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return a description for the storage location of the multipart content. |
|
||||||
* Tries to be as specific as possible: mentions the file location in case |
|
||||||
* of a temporary file. |
|
||||||
*/ |
|
||||||
public String getStorageDescription() { |
|
||||||
if (this.fileItem.isInMemory()) { |
|
||||||
return "in memory"; |
|
||||||
} |
|
||||||
else if (this.fileItem instanceof DiskFileItem) { |
|
||||||
return "at [" + ((DiskFileItem) this.fileItem).getStoreLocation().getAbsolutePath() + "]"; |
|
||||||
} |
|
||||||
else { |
|
||||||
return "on disk"; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,195 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.multipart.commons; |
|
||||||
|
|
||||||
import java.util.List; |
|
||||||
import javax.servlet.ServletContext; |
|
||||||
import javax.servlet.http.HttpServletRequest; |
|
||||||
|
|
||||||
import org.apache.commons.fileupload.FileItemFactory; |
|
||||||
import org.apache.commons.fileupload.FileUpload; |
|
||||||
import org.apache.commons.fileupload.FileUploadBase; |
|
||||||
import org.apache.commons.fileupload.FileUploadException; |
|
||||||
import org.apache.commons.fileupload.FileItem; |
|
||||||
import org.apache.commons.fileupload.servlet.ServletFileUpload; |
|
||||||
|
|
||||||
import org.springframework.util.Assert; |
|
||||||
import org.springframework.web.context.ServletContextAware; |
|
||||||
import org.springframework.web.multipart.MaxUploadSizeExceededException; |
|
||||||
import org.springframework.web.multipart.MultipartException; |
|
||||||
import org.springframework.web.multipart.MultipartHttpServletRequest; |
|
||||||
import org.springframework.web.multipart.MultipartResolver; |
|
||||||
import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest; |
|
||||||
import org.springframework.web.util.WebUtils; |
|
||||||
|
|
||||||
/** |
|
||||||
* Servlet-based {@link org.springframework.web.multipart.MultipartResolver} implementation |
|
||||||
* for <a href="http://jakarta.apache.org/commons/fileupload">Jakarta Commons FileUpload</a> |
|
||||||
* 1.2 or above. |
|
||||||
* |
|
||||||
* <p>Provides "maxUploadSize", "maxInMemorySize" and "defaultEncoding" settings as |
|
||||||
* bean properties (inherited from {@link CommonsFileUploadSupport}). See corresponding |
|
||||||
* ServletFileUpload / DiskFileItemFactory properties ("sizeMax", "sizeThreshold", |
|
||||||
* "headerEncoding") for details in terms of defaults and accepted values. |
|
||||||
* |
|
||||||
* <p>Saves temporary files to the servlet container's temporary directory. |
|
||||||
* Needs to be initialized <i>either</i> by an application context <i>or</i> |
|
||||||
* via the constructor that takes a ServletContext (for standalone usage). |
|
||||||
* |
|
||||||
* @author Trevor D. Cook |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 29.09.2003 |
|
||||||
* @see #CommonsMultipartResolver(ServletContext) |
|
||||||
* @see #setResolveLazily |
|
||||||
* @see org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver |
|
||||||
* @see org.apache.commons.fileupload.servlet.ServletFileUpload |
|
||||||
* @see org.apache.commons.fileupload.disk.DiskFileItemFactory |
|
||||||
*/ |
|
||||||
public class CommonsMultipartResolver extends CommonsFileUploadSupport |
|
||||||
implements MultipartResolver, ServletContextAware { |
|
||||||
|
|
||||||
private boolean resolveLazily = false; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Constructor for use as bean. Determines the servlet container's |
|
||||||
* temporary directory via the ServletContext passed in as through the |
|
||||||
* ServletContextAware interface (typically by a WebApplicationContext). |
|
||||||
* @see #setServletContext |
|
||||||
* @see org.springframework.web.context.ServletContextAware |
|
||||||
* @see org.springframework.web.context.WebApplicationContext |
|
||||||
*/ |
|
||||||
public CommonsMultipartResolver() { |
|
||||||
super(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Constructor for standalone usage. Determines the servlet container's |
|
||||||
* temporary directory via the given ServletContext. |
|
||||||
* @param servletContext the ServletContext to use |
|
||||||
*/ |
|
||||||
public CommonsMultipartResolver(ServletContext servletContext) { |
|
||||||
this(); |
|
||||||
setServletContext(servletContext); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set whether to resolve the multipart request lazily at the time of |
|
||||||
* file or parameter access. |
|
||||||
* <p>Default is "false", resolving the multipart elements immediately, throwing |
|
||||||
* corresponding exceptions at the time of the {@link #resolveMultipart} call. |
|
||||||
* Switch this to "true" for lazy multipart parsing, throwing parse exceptions |
|
||||||
* once the application attempts to obtain multipart files or parameters. |
|
||||||
*/ |
|
||||||
public void setResolveLazily(boolean resolveLazily) { |
|
||||||
this.resolveLazily = resolveLazily; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Initialize the underlying <code>org.apache.commons.fileupload.servlet.ServletFileUpload</code> |
|
||||||
* instance. Can be overridden to use a custom subclass, e.g. for testing purposes. |
|
||||||
* @param fileItemFactory the Commons FileItemFactory to use |
|
||||||
* @return the new ServletFileUpload instance |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
protected FileUpload newFileUpload(FileItemFactory fileItemFactory) { |
|
||||||
return new ServletFileUpload(fileItemFactory); |
|
||||||
} |
|
||||||
|
|
||||||
public void setServletContext(ServletContext servletContext) { |
|
||||||
if (!isUploadTempDirSpecified()) { |
|
||||||
getFileItemFactory().setRepository(WebUtils.getTempDir(servletContext)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public boolean isMultipart(HttpServletRequest request) { |
|
||||||
return (request != null && ServletFileUpload.isMultipartContent(request)); |
|
||||||
} |
|
||||||
|
|
||||||
public MultipartHttpServletRequest resolveMultipart(final HttpServletRequest request) throws MultipartException { |
|
||||||
Assert.notNull(request, "Request must not be null"); |
|
||||||
if (this.resolveLazily) { |
|
||||||
return new DefaultMultipartHttpServletRequest(request) { |
|
||||||
@Override |
|
||||||
protected void initializeMultipart() { |
|
||||||
MultipartParsingResult parsingResult = parseRequest(request); |
|
||||||
setMultipartFiles(parsingResult.getMultipartFiles()); |
|
||||||
setMultipartParameters(parsingResult.getMultipartParameters()); |
|
||||||
} |
|
||||||
}; |
|
||||||
} |
|
||||||
else { |
|
||||||
MultipartParsingResult parsingResult = parseRequest(request); |
|
||||||
return new DefaultMultipartHttpServletRequest( |
|
||||||
request, parsingResult.getMultipartFiles(), parsingResult.getMultipartParameters()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Parse the given servlet request, resolving its multipart elements. |
|
||||||
* @param request the request to parse |
|
||||||
* @return the parsing result |
|
||||||
* @throws MultipartException if multipart resolution failed. |
|
||||||
*/ |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException { |
|
||||||
String encoding = determineEncoding(request); |
|
||||||
FileUpload fileUpload = prepareFileUpload(encoding); |
|
||||||
try { |
|
||||||
List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request); |
|
||||||
return parseFileItems(fileItems, encoding); |
|
||||||
} |
|
||||||
catch (FileUploadBase.SizeLimitExceededException ex) { |
|
||||||
throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex); |
|
||||||
} |
|
||||||
catch (FileUploadException ex) { |
|
||||||
throw new MultipartException("Could not parse multipart servlet request", ex); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Determine the encoding for the given request. |
|
||||||
* Can be overridden in subclasses. |
|
||||||
* <p>The default implementation checks the request encoding, |
|
||||||
* falling back to the default encoding specified for this resolver. |
|
||||||
* @param request current HTTP request |
|
||||||
* @return the encoding for the request (never <code>null</code>) |
|
||||||
* @see javax.servlet.ServletRequest#getCharacterEncoding |
|
||||||
* @see #setDefaultEncoding |
|
||||||
*/ |
|
||||||
protected String determineEncoding(HttpServletRequest request) { |
|
||||||
String encoding = request.getCharacterEncoding(); |
|
||||||
if (encoding == null) { |
|
||||||
encoding = getDefaultEncoding(); |
|
||||||
} |
|
||||||
return encoding; |
|
||||||
} |
|
||||||
|
|
||||||
public void cleanupMultipart(MultipartHttpServletRequest request) { |
|
||||||
if (request != null) { |
|
||||||
try { |
|
||||||
cleanupFileItems(request.getFileMap().values()); |
|
||||||
} |
|
||||||
catch (Throwable ex) { |
|
||||||
logger.warn("Failed to perform multipart cleanup for servlet request", ex); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,9 +0,0 @@ |
|||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* MultipartResolver implementation for |
|
||||||
* <a href="http://jakarta.apache.org/commons/fileupload">Jakarta Commons FileUpload</a>. |
|
||||||
* |
|
||||||
*/ |
|
||||||
package org.springframework.web.multipart.commons; |
|
||||||
|
|
||||||
@ -1,11 +0,0 @@ |
|||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* Multipart resolution framework for handling file uploads. |
|
||||||
* Provides a MultipartResolver strategy interface, |
|
||||||
* and a generic extension of the HttpServletRequest interface
|
|
||||||
* for accessing multipart files in web application code. |
|
||||||
* |
|
||||||
*/ |
|
||||||
package org.springframework.web.multipart; |
|
||||||
|
|
||||||
@ -1,92 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.multipart.support; |
|
||||||
|
|
||||||
import java.util.Collections; |
|
||||||
import java.util.Iterator; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest; |
|
||||||
import javax.servlet.http.HttpServletRequestWrapper; |
|
||||||
|
|
||||||
import org.springframework.web.multipart.MultipartFile; |
|
||||||
import org.springframework.web.multipart.MultipartHttpServletRequest; |
|
||||||
|
|
||||||
/** |
|
||||||
* Abstract base implementation of the MultipartHttpServletRequest interface. |
|
||||||
* Provides management of pre-generated MultipartFile instances. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 06.10.2003 |
|
||||||
*/ |
|
||||||
public abstract class AbstractMultipartHttpServletRequest extends HttpServletRequestWrapper |
|
||||||
implements MultipartHttpServletRequest { |
|
||||||
|
|
||||||
private Map<String, MultipartFile> multipartFiles; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Wrap the given HttpServletRequest in a MultipartHttpServletRequest. |
|
||||||
* @param request the request to wrap |
|
||||||
*/ |
|
||||||
protected AbstractMultipartHttpServletRequest(HttpServletRequest request) { |
|
||||||
super(request); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public Iterator<String> getFileNames() { |
|
||||||
return getMultipartFiles().keySet().iterator(); |
|
||||||
} |
|
||||||
|
|
||||||
public MultipartFile getFile(String name) { |
|
||||||
return getMultipartFiles().get(name); |
|
||||||
} |
|
||||||
|
|
||||||
public Map<String, MultipartFile> getFileMap() { |
|
||||||
return getMultipartFiles(); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set a Map with parameter names as keys and MultipartFile objects as values. |
|
||||||
* To be invoked by subclasses on initialization. |
|
||||||
*/ |
|
||||||
protected final void setMultipartFiles(Map<String, MultipartFile> multipartFiles) { |
|
||||||
this.multipartFiles = Collections.unmodifiableMap(multipartFiles); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain the MultipartFile Map for retrieval, |
|
||||||
* lazily initializing it if necessary. |
|
||||||
* @see #initializeMultipart() |
|
||||||
*/ |
|
||||||
protected Map<String, MultipartFile> getMultipartFiles() { |
|
||||||
if (this.multipartFiles == null) { |
|
||||||
initializeMultipart(); |
|
||||||
} |
|
||||||
return this.multipartFiles; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Lazily initialize the multipart request, if possible. |
|
||||||
* Only called if not already eagerly initialized. |
|
||||||
*/ |
|
||||||
protected void initializeMultipart() { |
|
||||||
throw new IllegalStateException("Multipart request not initialized"); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,58 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.multipart.support; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
import org.springframework.beans.propertyeditors.ByteArrayPropertyEditor; |
|
||||||
import org.springframework.web.multipart.MultipartFile; |
|
||||||
|
|
||||||
/** |
|
||||||
* Custom {@link java.beans.PropertyEditor} for converting |
|
||||||
* {@link MultipartFile MultipartFiles} to byte arrays. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 13.10.2003 |
|
||||||
*/ |
|
||||||
public class ByteArrayMultipartFileEditor extends ByteArrayPropertyEditor { |
|
||||||
|
|
||||||
@Override |
|
||||||
public void setValue(Object value) { |
|
||||||
if (value instanceof MultipartFile) { |
|
||||||
MultipartFile multipartFile = (MultipartFile) value; |
|
||||||
try { |
|
||||||
super.setValue(multipartFile.getBytes()); |
|
||||||
} |
|
||||||
catch (IOException ex) { |
|
||||||
throw new IllegalArgumentException("Cannot read contents of multipart file", ex); |
|
||||||
} |
|
||||||
} |
|
||||||
else if (value instanceof byte[]) { |
|
||||||
super.setValue(value); |
|
||||||
} |
|
||||||
else { |
|
||||||
super.setValue(value != null ? value.toString().getBytes() : null); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String getAsText() { |
|
||||||
byte[] value = (byte[]) getValue(); |
|
||||||
return (value != null ? new String(value) : ""); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,127 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.multipart.support; |
|
||||||
|
|
||||||
import java.util.Collections; |
|
||||||
import java.util.Enumeration; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.HashSet; |
|
||||||
import java.util.Map; |
|
||||||
import java.util.Set; |
|
||||||
import javax.servlet.http.HttpServletRequest; |
|
||||||
|
|
||||||
import org.springframework.web.multipart.MultipartFile; |
|
||||||
|
|
||||||
/** |
|
||||||
* Default implementation of the |
|
||||||
* {@link org.springframework.web.multipart.MultipartHttpServletRequest} |
|
||||||
* interface. Provides management of pre-generated parameter values. |
|
||||||
* |
|
||||||
* @author Trevor D. Cook |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 29.09.2003 |
|
||||||
* @see org.springframework.web.multipart.MultipartResolver |
|
||||||
*/ |
|
||||||
public class DefaultMultipartHttpServletRequest extends AbstractMultipartHttpServletRequest { |
|
||||||
|
|
||||||
private Map<String, String[]> multipartParameters; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Wrap the given HttpServletRequest in a MultipartHttpServletRequest. |
|
||||||
* @param request the servlet request to wrap |
|
||||||
* @param mpFiles a map of the multipart files |
|
||||||
* @param mpParams a map of the parameters to expose, |
|
||||||
* with Strings as keys and String arrays as values |
|
||||||
*/ |
|
||||||
public DefaultMultipartHttpServletRequest( |
|
||||||
HttpServletRequest request, Map<String, MultipartFile> mpFiles, Map<String, String[]> mpParams) { |
|
||||||
|
|
||||||
super(request); |
|
||||||
setMultipartFiles(mpFiles); |
|
||||||
setMultipartParameters(mpParams); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Wrap the given HttpServletRequest in a MultipartHttpServletRequest. |
|
||||||
* @param request the servlet request to wrap |
|
||||||
*/ |
|
||||||
public DefaultMultipartHttpServletRequest(HttpServletRequest request) { |
|
||||||
super(request); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public Enumeration<String> getParameterNames() { |
|
||||||
Set<String> paramNames = new HashSet<String>(); |
|
||||||
Enumeration paramEnum = super.getParameterNames(); |
|
||||||
while (paramEnum.hasMoreElements()) { |
|
||||||
paramNames.add((String) paramEnum.nextElement()); |
|
||||||
} |
|
||||||
paramNames.addAll(getMultipartParameters().keySet()); |
|
||||||
return Collections.enumeration(paramNames); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String getParameter(String name) { |
|
||||||
String[] values = getMultipartParameters().get(name); |
|
||||||
if (values != null) { |
|
||||||
return (values.length > 0 ? values[0] : null); |
|
||||||
} |
|
||||||
return super.getParameter(name); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String[] getParameterValues(String name) { |
|
||||||
String[] values = getMultipartParameters().get(name); |
|
||||||
if (values != null) { |
|
||||||
return values; |
|
||||||
} |
|
||||||
return super.getParameterValues(name); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
@SuppressWarnings("unchecked") |
|
||||||
public Map<String, String[]> getParameterMap() { |
|
||||||
Map<String, String[]> paramMap = new HashMap<String, String[]>(); |
|
||||||
paramMap.putAll(super.getParameterMap()); |
|
||||||
paramMap.putAll(getMultipartParameters()); |
|
||||||
return paramMap; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set a Map with parameter names as keys and String array objects as values. |
|
||||||
* To be invoked by subclasses on initialization. |
|
||||||
*/ |
|
||||||
protected final void setMultipartParameters(Map<String, String[]> multipartParameters) { |
|
||||||
this.multipartParameters = multipartParameters; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Obtain the multipart parameter Map for retrieval, |
|
||||||
* lazily initializing it if necessary. |
|
||||||
* @see #initializeMultipart() |
|
||||||
*/ |
|
||||||
protected Map<String, String[]> getMultipartParameters() { |
|
||||||
if (this.multipartParameters == null) { |
|
||||||
initializeMultipart(); |
|
||||||
} |
|
||||||
return this.multipartParameters; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,151 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2006 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.multipart.support; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
import javax.servlet.FilterChain; |
|
||||||
import javax.servlet.ServletException; |
|
||||||
import javax.servlet.http.HttpServletRequest; |
|
||||||
import javax.servlet.http.HttpServletResponse; |
|
||||||
|
|
||||||
import org.springframework.web.context.WebApplicationContext; |
|
||||||
import org.springframework.web.context.support.WebApplicationContextUtils; |
|
||||||
import org.springframework.web.filter.OncePerRequestFilter; |
|
||||||
import org.springframework.web.multipart.MultipartHttpServletRequest; |
|
||||||
import org.springframework.web.multipart.MultipartResolver; |
|
||||||
|
|
||||||
/** |
|
||||||
* Servlet 2.3 Filter that resolves multipart requests via a MultipartResolver. |
|
||||||
* in the root web application context. |
|
||||||
* |
|
||||||
* <p>Looks up the MultipartResolver in Spring's root web application context. |
|
||||||
* Supports a "multipartResolverBeanName" filter init-param in <code>web.xml</code>; |
|
||||||
* the default bean name is "filterMultipartResolver". Looks up the MultipartResolver |
|
||||||
* on each request, to avoid initialization order issues (when using ContextLoaderServlet, |
|
||||||
* the root application context will get initialized <i>after</i> this filter). |
|
||||||
* |
|
||||||
* <p>MultipartResolver lookup is customizable: Override this filter's |
|
||||||
* <code>lookupMultipartResolver</code> method to use a custom MultipartResolver |
|
||||||
* instance, for example if not using a Spring web application context. |
|
||||||
* Note that the lookup method should not create a new MultipartResolver instance |
|
||||||
* for each call but rather return a reference to a pre-built instance. |
|
||||||
* |
|
||||||
* <p>Note: This filter is an <b>alternative</b> to using DispatcherServlet's |
|
||||||
* MultipartResolver support, for example for web applications with custom |
|
||||||
* web views that do not use Spring's web MVC. It should not be combined with |
|
||||||
* servlet-specific multipart resolution. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 08.10.2003 |
|
||||||
* @see #setMultipartResolverBeanName |
|
||||||
* @see #lookupMultipartResolver |
|
||||||
* @see org.springframework.web.multipart.MultipartResolver |
|
||||||
* @see org.springframework.web.servlet.DispatcherServlet |
|
||||||
*/ |
|
||||||
public class MultipartFilter extends OncePerRequestFilter { |
|
||||||
|
|
||||||
public static final String DEFAULT_MULTIPART_RESOLVER_BEAN_NAME = "filterMultipartResolver"; |
|
||||||
|
|
||||||
private String multipartResolverBeanName = DEFAULT_MULTIPART_RESOLVER_BEAN_NAME; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Set the bean name of the MultipartResolver to fetch from Spring's |
|
||||||
* root application context. Default is "filterMultipartResolver". |
|
||||||
*/ |
|
||||||
public void setMultipartResolverBeanName(String multipartResolverBeanName) { |
|
||||||
this.multipartResolverBeanName = multipartResolverBeanName; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the bean name of the MultipartResolver to fetch from Spring's |
|
||||||
* root application context. |
|
||||||
*/ |
|
||||||
protected String getMultipartResolverBeanName() { |
|
||||||
return multipartResolverBeanName; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Check for a multipart request via this filter's MultipartResolver, |
|
||||||
* and wrap the original request with a MultipartHttpServletRequest if appropriate. |
|
||||||
* <p>All later elements in the filter chain, most importantly servlets, benefit |
|
||||||
* from proper parameter extraction in the multipart case, and are able to cast to |
|
||||||
* MultipartHttpServletRequest if they need to. |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
protected void doFilterInternal( |
|
||||||
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) |
|
||||||
throws ServletException, IOException { |
|
||||||
|
|
||||||
MultipartResolver multipartResolver = lookupMultipartResolver(request); |
|
||||||
|
|
||||||
HttpServletRequest processedRequest = request; |
|
||||||
if (multipartResolver.isMultipart(processedRequest)) { |
|
||||||
if (logger.isDebugEnabled()) { |
|
||||||
logger.debug("Resolving multipart request [" + processedRequest.getRequestURI() + |
|
||||||
"] with MultipartFilter"); |
|
||||||
} |
|
||||||
processedRequest = multipartResolver.resolveMultipart(processedRequest); |
|
||||||
} |
|
||||||
else { |
|
||||||
if (logger.isDebugEnabled()) { |
|
||||||
logger.debug("Request [" + processedRequest.getRequestURI() + "] is not a multipart request"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
filterChain.doFilter(processedRequest, response); |
|
||||||
} |
|
||||||
finally { |
|
||||||
if (processedRequest instanceof MultipartHttpServletRequest) { |
|
||||||
multipartResolver.cleanupMultipart((MultipartHttpServletRequest) processedRequest); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Look up the MultipartResolver that this filter should use, |
|
||||||
* taking the current HTTP request as argument. |
|
||||||
* <p>Default implementation delegates to the <code>lookupMultipartResolver</code> |
|
||||||
* without arguments. |
|
||||||
* @return the MultipartResolver to use |
|
||||||
* @see #lookupMultipartResolver() |
|
||||||
*/ |
|
||||||
protected MultipartResolver lookupMultipartResolver(HttpServletRequest request) { |
|
||||||
return lookupMultipartResolver(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Look for a MultipartResolver bean in the root web application context. |
|
||||||
* Supports a "multipartResolverBeanName" filter init param; the default |
|
||||||
* bean name is "filterMultipartResolver". |
|
||||||
* <p>This can be overridden to use a custom MultipartResolver instance, |
|
||||||
* for example if not using a Spring web application context. |
|
||||||
* @return the MultipartResolver instance, or <code>null</code> if none found |
|
||||||
*/ |
|
||||||
protected MultipartResolver lookupMultipartResolver() { |
|
||||||
if (logger.isDebugEnabled()) { |
|
||||||
logger.debug("Using MultipartResolver '" + getMultipartResolverBeanName() + "' for MultipartFilter"); |
|
||||||
} |
|
||||||
WebApplicationContext wac = |
|
||||||
WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()); |
|
||||||
return (MultipartResolver) wac.getBean(getMultipartResolverBeanName(), MultipartResolver.class); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,78 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.multipart.support; |
|
||||||
|
|
||||||
import java.beans.PropertyEditorSupport; |
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
import org.springframework.web.multipart.MultipartFile; |
|
||||||
|
|
||||||
/** |
|
||||||
* Custom {@link java.beans.PropertyEditor} for converting |
|
||||||
* {@link MultipartFile MultipartFiles} to Strings. |
|
||||||
* |
|
||||||
* <p>Allows one to specify the charset to use. |
|
||||||
* |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 13.10.2003 |
|
||||||
*/ |
|
||||||
public class StringMultipartFileEditor extends PropertyEditorSupport { |
|
||||||
|
|
||||||
private final String charsetName; |
|
||||||
|
|
||||||
|
|
||||||
/** |
|
||||||
* Create a new {@link StringMultipartFileEditor}, using the default charset. |
|
||||||
*/ |
|
||||||
public StringMultipartFileEditor() { |
|
||||||
this.charsetName = null; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a new {@link StringMultipartFileEditor}, using the given charset. |
|
||||||
* @param charsetName valid charset name |
|
||||||
* @see java.lang.String#String(byte[],String) |
|
||||||
*/ |
|
||||||
public StringMultipartFileEditor(String charsetName) { |
|
||||||
this.charsetName = charsetName; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
@Override |
|
||||||
public void setAsText(String text) { |
|
||||||
setValue(text); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void setValue(Object value) { |
|
||||||
if (value instanceof MultipartFile) { |
|
||||||
MultipartFile multipartFile = (MultipartFile) value; |
|
||||||
try { |
|
||||||
super.setValue(this.charsetName != null ? |
|
||||||
new String(multipartFile.getBytes(), this.charsetName) : |
|
||||||
new String(multipartFile.getBytes())); |
|
||||||
} |
|
||||||
catch (IOException ex) { |
|
||||||
throw new IllegalArgumentException("Cannot read contents of multipart file", ex); |
|
||||||
} |
|
||||||
} |
|
||||||
else { |
|
||||||
super.setValue(value); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,10 +0,0 @@ |
|||||||
|
|
||||||
/** |
|
||||||
* |
|
||||||
* Support classes for the multipart resolution framework. |
|
||||||
* Contains property editors for multipart files, and a |
|
||||||
* servlet filter for multipart handling without Spring's web MVC. |
|
||||||
* |
|
||||||
*/ |
|
||||||
package org.springframework.web.multipart.support; |
|
||||||
|
|
||||||
@ -1,65 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2004-2009 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.support; |
|
||||||
|
|
||||||
import javax.servlet.ServletRequest; |
|
||||||
|
|
||||||
import org.springframework.model.ui.PresentationModelFactory; |
|
||||||
import org.springframework.model.ui.support.DefaultPresentationModelFactory; |
|
||||||
import org.springframework.web.context.request.WebRequest; |
|
||||||
|
|
||||||
/** |
|
||||||
* Utilities for working with the <code>model.ui</code> PresentationModel system. |
|
||||||
* @author Keith Donald |
|
||||||
*/ |
|
||||||
public final class PresentationModelUtils { |
|
||||||
|
|
||||||
private static final String PRESENTATION_MODEL_FACTORY_ATTRIBUTE = "presentationModelFactory"; |
|
||||||
|
|
||||||
private PresentationModelUtils() { |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get the PresentationModelFactory for the current web request. |
|
||||||
* Will create a new one and cache it as a request attribute if one does not exist. |
|
||||||
* @param request the web request |
|
||||||
* @return the presentation model factory |
|
||||||
*/ |
|
||||||
public static PresentationModelFactory getPresentationModelFactory(WebRequest request) { |
|
||||||
PresentationModelFactory factory = (PresentationModelFactory) request.getAttribute(PRESENTATION_MODEL_FACTORY_ATTRIBUTE, WebRequest.SCOPE_REQUEST); |
|
||||||
if (factory == null) { |
|
||||||
factory = new DefaultPresentationModelFactory(); |
|
||||||
request.setAttribute(PRESENTATION_MODEL_FACTORY_ATTRIBUTE, factory, WebRequest.SCOPE_REQUEST); |
|
||||||
} |
|
||||||
return factory; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get the PresentationModelFactory for the current servlet request. |
|
||||||
* Will create a new one and cache it as a request attribute if one does not exist. |
|
||||||
* @param request the servlet |
|
||||||
* @return the presentation model factory |
|
||||||
*/ |
|
||||||
public static PresentationModelFactory getPresentationModelFactory(ServletRequest request) { |
|
||||||
PresentationModelFactory factory = (PresentationModelFactory) request.getAttribute(PRESENTATION_MODEL_FACTORY_ATTRIBUTE); |
|
||||||
if (factory == null) { |
|
||||||
factory = new DefaultPresentationModelFactory(); |
|
||||||
request.setAttribute(PRESENTATION_MODEL_FACTORY_ATTRIBUTE, factory); |
|
||||||
} |
|
||||||
return factory; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,90 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2006 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.bind; |
|
||||||
|
|
||||||
import junit.framework.TestCase; |
|
||||||
|
|
||||||
import org.springframework.beans.TestBean; |
|
||||||
import org.springframework.validation.BindException; |
|
||||||
import org.springframework.validation.Errors; |
|
||||||
import org.springframework.validation.FieldError; |
|
||||||
import org.springframework.validation.ObjectError; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 02.05.2003 |
|
||||||
*/ |
|
||||||
public class EscapedErrorsTests extends TestCase { |
|
||||||
|
|
||||||
public void testEscapedErrors() { |
|
||||||
TestBean tb = new TestBean(); |
|
||||||
tb.setName("empty &"); |
|
||||||
|
|
||||||
Errors errors = new EscapedErrors(new BindException(tb, "tb")); |
|
||||||
errors.rejectValue("name", "NAME_EMPTY &", null, "message: &"); |
|
||||||
errors.rejectValue("age", "AGE_NOT_SET <tag>", null, "message: <tag>"); |
|
||||||
errors.rejectValue("age", "AGE_NOT_32 <tag>", null, "message: <tag>"); |
|
||||||
errors.reject("GENERAL_ERROR \" '", null, "message: \" '"); |
|
||||||
|
|
||||||
assertTrue("Correct errors flag", errors.hasErrors()); |
|
||||||
assertTrue("Correct number of errors", errors.getErrorCount() == 4); |
|
||||||
assertTrue("Correct object name", "tb".equals(errors.getObjectName())); |
|
||||||
|
|
||||||
assertTrue("Correct global errors flag", errors.hasGlobalErrors()); |
|
||||||
assertTrue("Correct number of global errors", errors.getGlobalErrorCount() == 1); |
|
||||||
ObjectError globalError = errors.getGlobalError(); |
|
||||||
assertTrue("Global error message escaped", "message: " '".equals(globalError.getDefaultMessage())); |
|
||||||
assertTrue("Global error code not escaped", "GENERAL_ERROR \" '".equals(globalError.getCode())); |
|
||||||
ObjectError globalErrorInList = (ObjectError) errors.getGlobalErrors().get(0); |
|
||||||
assertTrue("Same global error in list", globalError.getDefaultMessage().equals(globalErrorInList.getDefaultMessage())); |
|
||||||
ObjectError globalErrorInAllList = (ObjectError) errors.getAllErrors().get(3); |
|
||||||
assertTrue("Same global error in list", globalError.getDefaultMessage().equals(globalErrorInAllList.getDefaultMessage())); |
|
||||||
|
|
||||||
assertTrue("Correct field errors flag", errors.hasFieldErrors()); |
|
||||||
assertTrue("Correct number of field errors", errors.getFieldErrorCount() == 3); |
|
||||||
assertTrue("Correct number of field errors in list", errors.getFieldErrors().size() == 3); |
|
||||||
FieldError fieldError = errors.getFieldError(); |
|
||||||
assertTrue("Field error code not escaped", "NAME_EMPTY &".equals(fieldError.getCode())); |
|
||||||
assertTrue("Field value escaped", "empty &".equals(errors.getFieldValue("name"))); |
|
||||||
FieldError fieldErrorInList = (FieldError) errors.getFieldErrors().get(0); |
|
||||||
assertTrue("Same field error in list", fieldError.getDefaultMessage().equals(fieldErrorInList.getDefaultMessage())); |
|
||||||
|
|
||||||
assertTrue("Correct name errors flag", errors.hasFieldErrors("name")); |
|
||||||
assertTrue("Correct number of name errors", errors.getFieldErrorCount("name") == 1); |
|
||||||
assertTrue("Correct number of name errors in list", errors.getFieldErrors("name").size() == 1); |
|
||||||
FieldError nameError = errors.getFieldError("name"); |
|
||||||
assertTrue("Name error message escaped", "message: &".equals(nameError.getDefaultMessage())); |
|
||||||
assertTrue("Name error code not escaped", "NAME_EMPTY &".equals(nameError.getCode())); |
|
||||||
assertTrue("Name value escaped", "empty &".equals(errors.getFieldValue("name"))); |
|
||||||
FieldError nameErrorInList = (FieldError) errors.getFieldErrors("name").get(0); |
|
||||||
assertTrue("Same name error in list", nameError.getDefaultMessage().equals(nameErrorInList.getDefaultMessage())); |
|
||||||
|
|
||||||
assertTrue("Correct age errors flag", errors.hasFieldErrors("age")); |
|
||||||
assertTrue("Correct number of age errors", errors.getFieldErrorCount("age") == 2); |
|
||||||
assertTrue("Correct number of age errors in list", errors.getFieldErrors("age").size() == 2); |
|
||||||
FieldError ageError = errors.getFieldError("age"); |
|
||||||
assertTrue("Age error message escaped", "message: <tag>".equals(ageError.getDefaultMessage())); |
|
||||||
assertTrue("Age error code not escaped", "AGE_NOT_SET <tag>".equals(ageError.getCode())); |
|
||||||
assertTrue("Age value not escaped", (new Integer(0)).equals(errors.getFieldValue("age"))); |
|
||||||
FieldError ageErrorInList = (FieldError) errors.getFieldErrors("age").get(0); |
|
||||||
assertTrue("Same name error in list", ageError.getDefaultMessage().equals(ageErrorInList.getDefaultMessage())); |
|
||||||
FieldError ageError2 = (FieldError) errors.getFieldErrors("age").get(1); |
|
||||||
assertTrue("Age error 2 message escaped", "message: <tag>".equals(ageError2.getDefaultMessage())); |
|
||||||
assertTrue("Age error 2 code not escaped", "AGE_NOT_32 <tag>".equals(ageError2.getCode())); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,256 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2006 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.bind; |
|
||||||
|
|
||||||
import static org.junit.Assert.*; |
|
||||||
|
|
||||||
import java.beans.PropertyEditorSupport; |
|
||||||
import java.util.Arrays; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.Map; |
|
||||||
|
|
||||||
import org.junit.Test; |
|
||||||
import org.springframework.beans.ITestBean; |
|
||||||
import org.springframework.beans.PropertyValue; |
|
||||||
import org.springframework.beans.PropertyValues; |
|
||||||
import org.springframework.beans.TestBean; |
|
||||||
import org.springframework.mock.web.MockHttpServletRequest; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author Rod Johnson |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @author Chris Beams |
|
||||||
* @author Scott Andrews |
|
||||||
*/ |
|
||||||
public class ServletRequestDataBinderTests { |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testBindingWithNestedObjectCreation() throws Exception { |
|
||||||
TestBean tb = new TestBean(); |
|
||||||
|
|
||||||
ServletRequestDataBinder binder = new ServletRequestDataBinder(tb, "person"); |
|
||||||
binder.registerCustomEditor(ITestBean.class, new PropertyEditorSupport() { |
|
||||||
public void setAsText(String text) throws IllegalArgumentException { |
|
||||||
setValue(new TestBean()); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("spouse", "someValue"); |
|
||||||
request.addParameter("spouse.name", "test"); |
|
||||||
binder.bind(request); |
|
||||||
|
|
||||||
assertNotNull(tb.getSpouse()); |
|
||||||
assertEquals("test", tb.getSpouse().getName()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testFieldPrefixCausesFieldReset() throws Exception { |
|
||||||
TestBean target = new TestBean(); |
|
||||||
ServletRequestDataBinder binder = new ServletRequestDataBinder(target); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("_postProcessed", "visible"); |
|
||||||
request.addParameter("postProcessed", "on"); |
|
||||||
binder.bind(request); |
|
||||||
assertTrue(target.isPostProcessed()); |
|
||||||
|
|
||||||
request.removeParameter("postProcessed"); |
|
||||||
binder.bind(request); |
|
||||||
assertFalse(target.isPostProcessed()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testFieldPrefixCausesFieldResetWithIgnoreUnknownFields() throws Exception { |
|
||||||
TestBean target = new TestBean(); |
|
||||||
ServletRequestDataBinder binder = new ServletRequestDataBinder(target); |
|
||||||
binder.setIgnoreUnknownFields(false); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("_postProcessed", "visible"); |
|
||||||
request.addParameter("postProcessed", "on"); |
|
||||||
binder.bind(request); |
|
||||||
assertTrue(target.isPostProcessed()); |
|
||||||
|
|
||||||
request.removeParameter("postProcessed"); |
|
||||||
binder.bind(request); |
|
||||||
assertFalse(target.isPostProcessed()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testFieldDefault() throws Exception { |
|
||||||
TestBean target = new TestBean(); |
|
||||||
ServletRequestDataBinder binder = new ServletRequestDataBinder(target); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("!postProcessed", "off"); |
|
||||||
request.addParameter("postProcessed", "on"); |
|
||||||
binder.bind(request); |
|
||||||
assertTrue(target.isPostProcessed()); |
|
||||||
|
|
||||||
request.removeParameter("postProcessed"); |
|
||||||
binder.bind(request); |
|
||||||
assertFalse(target.isPostProcessed()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testFieldDefaultPreemptsFieldMarker() throws Exception { |
|
||||||
TestBean target = new TestBean(); |
|
||||||
ServletRequestDataBinder binder = new ServletRequestDataBinder(target); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("!postProcessed", "on"); |
|
||||||
request.addParameter("_postProcessed", "visible"); |
|
||||||
request.addParameter("postProcessed", "on"); |
|
||||||
binder.bind(request); |
|
||||||
assertTrue(target.isPostProcessed()); |
|
||||||
|
|
||||||
request.removeParameter("postProcessed"); |
|
||||||
binder.bind(request); |
|
||||||
assertTrue(target.isPostProcessed()); |
|
||||||
|
|
||||||
request.removeParameter("!postProcessed"); |
|
||||||
binder.bind(request); |
|
||||||
assertFalse(target.isPostProcessed()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testFieldDefaultNonBoolean() throws Exception { |
|
||||||
TestBean target = new TestBean(); |
|
||||||
ServletRequestDataBinder binder = new ServletRequestDataBinder(target); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("!name", "anonymous"); |
|
||||||
request.addParameter("name", "Scott"); |
|
||||||
binder.bind(request); |
|
||||||
assertEquals("Scott", target.getName()); |
|
||||||
|
|
||||||
request.removeParameter("name"); |
|
||||||
binder.bind(request); |
|
||||||
assertEquals("anonymous", target.getName()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testWithCommaSeparatedStringArray() throws Exception { |
|
||||||
TestBean target = new TestBean(); |
|
||||||
ServletRequestDataBinder binder = new ServletRequestDataBinder(target); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("stringArray", "bar"); |
|
||||||
request.addParameter("stringArray", "abc"); |
|
||||||
request.addParameter("stringArray", "123,def"); |
|
||||||
binder.bind(request); |
|
||||||
assertEquals("Expected all three items to be bound", 3, target.getStringArray().length); |
|
||||||
|
|
||||||
request.removeParameter("stringArray"); |
|
||||||
request.addParameter("stringArray", "123,def"); |
|
||||||
binder.bind(request); |
|
||||||
assertEquals("Expected only 1 item to be bound", 1, target.getStringArray().length); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testBindingWithNestedObjectCreationAndWrongOrder() throws Exception { |
|
||||||
TestBean tb = new TestBean(); |
|
||||||
|
|
||||||
ServletRequestDataBinder binder = new ServletRequestDataBinder(tb, "person"); |
|
||||||
binder.registerCustomEditor(ITestBean.class, new PropertyEditorSupport() { |
|
||||||
public void setAsText(String text) throws IllegalArgumentException { |
|
||||||
setValue(new TestBean()); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("spouse.name", "test"); |
|
||||||
request.addParameter("spouse", "someValue"); |
|
||||||
binder.bind(request); |
|
||||||
|
|
||||||
assertNotNull(tb.getSpouse()); |
|
||||||
assertEquals("test", tb.getSpouse().getName()); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testNoPrefix() throws Exception { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("forname", "Tony"); |
|
||||||
request.addParameter("surname", "Blair"); |
|
||||||
request.addParameter("age", "" + 50); |
|
||||||
|
|
||||||
ServletRequestParameterPropertyValues pvs = new ServletRequestParameterPropertyValues(request); |
|
||||||
doTestTony(pvs); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testPrefix() throws Exception { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("test_forname", "Tony"); |
|
||||||
request.addParameter("test_surname", "Blair"); |
|
||||||
request.addParameter("test_age", "" + 50); |
|
||||||
|
|
||||||
ServletRequestParameterPropertyValues pvs = new ServletRequestParameterPropertyValues(request); |
|
||||||
assertTrue("Didn't fidn normal when given prefix", !pvs.contains("forname")); |
|
||||||
assertTrue("Did treat prefix as normal when not given prefix", pvs.contains("test_forname")); |
|
||||||
|
|
||||||
pvs = new ServletRequestParameterPropertyValues(request, "test"); |
|
||||||
doTestTony(pvs); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testNoParameters() throws Exception { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
ServletRequestParameterPropertyValues pvs = new ServletRequestParameterPropertyValues(request); |
|
||||||
assertTrue("Found no parameters", pvs.getPropertyValues().length == 0); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testMultipleValuesForParameter() throws Exception { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
String[] original = new String[] {"Tony", "Rod"}; |
|
||||||
request.addParameter("forname", original); |
|
||||||
|
|
||||||
ServletRequestParameterPropertyValues pvs = new ServletRequestParameterPropertyValues(request); |
|
||||||
assertTrue("Found 1 parameter", pvs.getPropertyValues().length == 1); |
|
||||||
assertTrue("Found array value", pvs.getPropertyValue("forname").getValue() instanceof String[]); |
|
||||||
String[] values = (String[]) pvs.getPropertyValue("forname").getValue(); |
|
||||||
assertEquals("Correct values", Arrays.asList(values), Arrays.asList(original)); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Must contain: forname=Tony surname=Blair age=50 |
|
||||||
*/ |
|
||||||
protected void doTestTony(PropertyValues pvs) throws Exception { |
|
||||||
assertTrue("Contains 3", pvs.getPropertyValues().length == 3); |
|
||||||
assertTrue("Contains forname", pvs.contains("forname")); |
|
||||||
assertTrue("Contains surname", pvs.contains("surname")); |
|
||||||
assertTrue("Contains age", pvs.contains("age")); |
|
||||||
assertTrue("Doesn't contain tory", !pvs.contains("tory")); |
|
||||||
|
|
||||||
PropertyValue[] ps = pvs.getPropertyValues(); |
|
||||||
Map<String, String> m = new HashMap<String, String>(); |
|
||||||
m.put("forname", "Tony"); |
|
||||||
m.put("surname", "Blair"); |
|
||||||
m.put("age", "50"); |
|
||||||
for (int i = 0; i < ps.length; i++) { |
|
||||||
Object val = m.get(ps[i].getName()); |
|
||||||
assertTrue("Can't have unexpected value", val != null); |
|
||||||
assertTrue("Val i string", val instanceof String); |
|
||||||
assertTrue("val matches expected", val.equals(ps[i].getValue())); |
|
||||||
m.remove(ps[i].getName()); |
|
||||||
} |
|
||||||
assertTrue("Map size is 0", m.size() == 0); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,465 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2007 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.bind; |
|
||||||
|
|
||||||
import static org.junit.Assert.*; |
|
||||||
|
|
||||||
import org.junit.Test; |
|
||||||
import org.springframework.mock.web.MockHttpServletRequest; |
|
||||||
import org.springframework.util.StopWatch; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @author Chris Beams |
|
||||||
* @since 06.08.2003 |
|
||||||
*/ |
|
||||||
public class ServletRequestUtilsTests { |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testIntParameter() throws ServletRequestBindingException { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("param1", "5"); |
|
||||||
request.addParameter("param2", "e"); |
|
||||||
request.addParameter("paramEmpty", ""); |
|
||||||
|
|
||||||
assertEquals(ServletRequestUtils.getIntParameter(request, "param1"), new Integer(5)); |
|
||||||
assertEquals(ServletRequestUtils.getIntParameter(request, "param1", 6), 5); |
|
||||||
assertEquals(ServletRequestUtils.getRequiredIntParameter(request, "param1"), 5); |
|
||||||
|
|
||||||
assertEquals(ServletRequestUtils.getIntParameter(request, "param2", 6), 6); |
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredIntParameter(request, "param2"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
|
|
||||||
assertEquals(ServletRequestUtils.getIntParameter(request, "param3"), null); |
|
||||||
assertEquals(ServletRequestUtils.getIntParameter(request, "param3", 6), 6); |
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredIntParameter(request, "param3"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredIntParameter(request, "paramEmpty"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testIntParameters() throws ServletRequestBindingException { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("param", new String[] {"1", "2", "3"}); |
|
||||||
|
|
||||||
request.addParameter("param2", "1"); |
|
||||||
request.addParameter("param2", "2"); |
|
||||||
request.addParameter("param2", "bogus"); |
|
||||||
|
|
||||||
int[] array = new int[] {1, 2, 3}; |
|
||||||
int[] values = ServletRequestUtils.getRequiredIntParameters(request, "param"); |
|
||||||
assertEquals(3, values.length); |
|
||||||
for (int i = 0; i < array.length; i++) { |
|
||||||
assertEquals(array[i], values[i]); |
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredIntParameters(request, "param2"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testLongParameter() throws ServletRequestBindingException { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("param1", "5"); |
|
||||||
request.addParameter("param2", "e"); |
|
||||||
request.addParameter("paramEmpty", ""); |
|
||||||
|
|
||||||
assertEquals(ServletRequestUtils.getLongParameter(request, "param1"), new Long(5L)); |
|
||||||
assertEquals(ServletRequestUtils.getLongParameter(request, "param1", 6L), 5L); |
|
||||||
assertEquals(ServletRequestUtils.getRequiredIntParameter(request, "param1"), 5L); |
|
||||||
|
|
||||||
assertEquals(ServletRequestUtils.getLongParameter(request, "param2", 6L), 6L); |
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredLongParameter(request, "param2"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
|
|
||||||
assertEquals(ServletRequestUtils.getLongParameter(request, "param3"), null); |
|
||||||
assertEquals(ServletRequestUtils.getLongParameter(request, "param3", 6L), 6L); |
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredLongParameter(request, "param3"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredLongParameter(request, "paramEmpty"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testLongParameters() throws ServletRequestBindingException { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.setParameter("param", new String[] {"1", "2", "3"}); |
|
||||||
|
|
||||||
request.setParameter("param2", "0"); |
|
||||||
request.setParameter("param2", "1"); |
|
||||||
request.addParameter("param2", "2"); |
|
||||||
request.addParameter("param2", "bogus"); |
|
||||||
|
|
||||||
long[] array = new long[] {1L, 2L, 3L}; |
|
||||||
long[] values = ServletRequestUtils.getRequiredLongParameters(request, "param"); |
|
||||||
assertEquals(3, values.length); |
|
||||||
for (int i = 0; i < array.length; i++) { |
|
||||||
assertEquals(array[i], values[i]); |
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredLongParameters(request, "param2"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
|
|
||||||
request.setParameter("param2", new String[] {"1", "2"}); |
|
||||||
values = ServletRequestUtils.getRequiredLongParameters(request, "param2"); |
|
||||||
assertEquals(2, values.length); |
|
||||||
assertEquals(1, values[0]); |
|
||||||
assertEquals(2, values[1]); |
|
||||||
|
|
||||||
request.removeParameter("param2"); |
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredLongParameters(request, "param2"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testFloatParameter() throws ServletRequestBindingException { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("param1", "5.5"); |
|
||||||
request.addParameter("param2", "e"); |
|
||||||
request.addParameter("paramEmpty", ""); |
|
||||||
|
|
||||||
assertTrue(ServletRequestUtils.getFloatParameter(request, "param1").equals(new Float(5.5f))); |
|
||||||
assertTrue(ServletRequestUtils.getFloatParameter(request, "param1", 6.5f) == 5.5f); |
|
||||||
assertTrue(ServletRequestUtils.getRequiredFloatParameter(request, "param1") == 5.5f); |
|
||||||
|
|
||||||
assertTrue(ServletRequestUtils.getFloatParameter(request, "param2", 6.5f) == 6.5f); |
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredFloatParameter(request, "param2"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
|
|
||||||
assertTrue(ServletRequestUtils.getFloatParameter(request, "param3") == null); |
|
||||||
assertTrue(ServletRequestUtils.getFloatParameter(request, "param3", 6.5f) == 6.5f); |
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredFloatParameter(request, "param3"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredFloatParameter(request, "paramEmpty"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testFloatParameters() throws ServletRequestBindingException { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("param", new String[] {"1.5", "2.5", "3"}); |
|
||||||
|
|
||||||
request.addParameter("param2", "1.5"); |
|
||||||
request.addParameter("param2", "2"); |
|
||||||
request.addParameter("param2", "bogus"); |
|
||||||
|
|
||||||
float[] array = new float[] {1.5F, 2.5F, 3}; |
|
||||||
float[] values = ServletRequestUtils.getRequiredFloatParameters(request, "param"); |
|
||||||
assertEquals(3, values.length); |
|
||||||
for (int i = 0; i < array.length; i++) { |
|
||||||
assertEquals(array[i], values[i], 0); |
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredFloatParameters(request, "param2"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testDoubleParameter() throws ServletRequestBindingException { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("param1", "5.5"); |
|
||||||
request.addParameter("param2", "e"); |
|
||||||
request.addParameter("paramEmpty", ""); |
|
||||||
|
|
||||||
assertTrue(ServletRequestUtils.getDoubleParameter(request, "param1").equals(new Double(5.5))); |
|
||||||
assertTrue(ServletRequestUtils.getDoubleParameter(request, "param1", 6.5) == 5.5); |
|
||||||
assertTrue(ServletRequestUtils.getRequiredDoubleParameter(request, "param1") == 5.5); |
|
||||||
|
|
||||||
assertTrue(ServletRequestUtils.getDoubleParameter(request, "param2", 6.5) == 6.5); |
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredDoubleParameter(request, "param2"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
|
|
||||||
assertTrue(ServletRequestUtils.getDoubleParameter(request, "param3") == null); |
|
||||||
assertTrue(ServletRequestUtils.getDoubleParameter(request, "param3", 6.5) == 6.5); |
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredDoubleParameter(request, "param3"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredDoubleParameter(request, "paramEmpty"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testDoubleParameters() throws ServletRequestBindingException { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("param", new String[] {"1.5", "2.5", "3"}); |
|
||||||
|
|
||||||
request.addParameter("param2", "1.5"); |
|
||||||
request.addParameter("param2", "2"); |
|
||||||
request.addParameter("param2", "bogus"); |
|
||||||
|
|
||||||
double[] array = new double[] {1.5, 2.5, 3}; |
|
||||||
double[] values = ServletRequestUtils.getRequiredDoubleParameters(request, "param"); |
|
||||||
assertEquals(3, values.length); |
|
||||||
for (int i = 0; i < array.length; i++) { |
|
||||||
assertEquals(array[i], values[i], 0); |
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredDoubleParameters(request, "param2"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testBooleanParameter() throws ServletRequestBindingException { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("param1", "true"); |
|
||||||
request.addParameter("param2", "e"); |
|
||||||
request.addParameter("param4", "yes"); |
|
||||||
request.addParameter("param5", "1"); |
|
||||||
request.addParameter("paramEmpty", ""); |
|
||||||
|
|
||||||
assertTrue(ServletRequestUtils.getBooleanParameter(request, "param1").equals(Boolean.TRUE)); |
|
||||||
assertTrue(ServletRequestUtils.getBooleanParameter(request, "param1", false)); |
|
||||||
assertTrue(ServletRequestUtils.getRequiredBooleanParameter(request, "param1")); |
|
||||||
|
|
||||||
assertFalse(ServletRequestUtils.getBooleanParameter(request, "param2", true)); |
|
||||||
assertFalse(ServletRequestUtils.getRequiredBooleanParameter(request, "param2")); |
|
||||||
|
|
||||||
assertTrue(ServletRequestUtils.getBooleanParameter(request, "param3") == null); |
|
||||||
assertTrue(ServletRequestUtils.getBooleanParameter(request, "param3", true)); |
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredBooleanParameter(request, "param3"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
|
|
||||||
assertTrue(ServletRequestUtils.getBooleanParameter(request, "param4", false)); |
|
||||||
assertTrue(ServletRequestUtils.getRequiredBooleanParameter(request, "param4")); |
|
||||||
|
|
||||||
assertTrue(ServletRequestUtils.getBooleanParameter(request, "param5", false)); |
|
||||||
assertTrue(ServletRequestUtils.getRequiredBooleanParameter(request, "param5")); |
|
||||||
assertFalse(ServletRequestUtils.getRequiredBooleanParameter(request, "paramEmpty")); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testBooleanParameters() throws ServletRequestBindingException { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("param", new String[] {"true", "yes", "off", "1", "bogus"}); |
|
||||||
|
|
||||||
request.addParameter("param2", "false"); |
|
||||||
request.addParameter("param2", "true"); |
|
||||||
request.addParameter("param2", ""); |
|
||||||
|
|
||||||
boolean[] array = new boolean[] {true, true, false, true, false}; |
|
||||||
boolean[] values = ServletRequestUtils.getRequiredBooleanParameters(request, "param"); |
|
||||||
assertEquals(array.length, values.length); |
|
||||||
for (int i = 0; i < array.length; i++) { |
|
||||||
assertEquals(array[i], values[i]); |
|
||||||
} |
|
||||||
|
|
||||||
array = new boolean[] {false, true, false}; |
|
||||||
values = ServletRequestUtils.getRequiredBooleanParameters(request, "param2"); |
|
||||||
assertEquals(array.length, values.length); |
|
||||||
for (int i = 0; i < array.length; i++) { |
|
||||||
assertEquals(array[i], values[i]); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testStringParameter() throws ServletRequestBindingException { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
request.addParameter("param1", "str"); |
|
||||||
request.addParameter("paramEmpty", ""); |
|
||||||
|
|
||||||
assertEquals("str", ServletRequestUtils.getStringParameter(request, "param1")); |
|
||||||
assertEquals("str", ServletRequestUtils.getStringParameter(request, "param1", "string")); |
|
||||||
assertEquals("str", ServletRequestUtils.getRequiredStringParameter(request, "param1")); |
|
||||||
|
|
||||||
assertEquals(null, ServletRequestUtils.getStringParameter(request, "param3")); |
|
||||||
assertEquals("string", ServletRequestUtils.getStringParameter(request, "param3", "string")); |
|
||||||
assertNull(ServletRequestUtils.getStringParameter(request, "param3", null)); |
|
||||||
try { |
|
||||||
ServletRequestUtils.getRequiredStringParameter(request, "param3"); |
|
||||||
fail("Should have thrown ServletRequestBindingException"); |
|
||||||
} |
|
||||||
catch (ServletRequestBindingException ex) { |
|
||||||
// expected
|
|
||||||
} |
|
||||||
|
|
||||||
assertEquals("", ServletRequestUtils.getStringParameter(request, "paramEmpty")); |
|
||||||
assertEquals("", ServletRequestUtils.getRequiredStringParameter(request, "paramEmpty")); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testGetIntParameterWithDefaultValueHandlingIsFastEnough() { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
StopWatch sw = new StopWatch(); |
|
||||||
sw.start(); |
|
||||||
for (int i = 0; i < 1000000; i++) { |
|
||||||
ServletRequestUtils.getIntParameter(request, "nonExistingParam", 0); |
|
||||||
} |
|
||||||
sw.stop(); |
|
||||||
System.out.println(sw.getTotalTimeMillis()); |
|
||||||
assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testGetLongParameterWithDefaultValueHandlingIsFastEnough() { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
StopWatch sw = new StopWatch(); |
|
||||||
sw.start(); |
|
||||||
for (int i = 0; i < 1000000; i++) { |
|
||||||
ServletRequestUtils.getLongParameter(request, "nonExistingParam", 0); |
|
||||||
} |
|
||||||
sw.stop(); |
|
||||||
System.out.println(sw.getTotalTimeMillis()); |
|
||||||
assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testGetFloatParameterWithDefaultValueHandlingIsFastEnough() { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
StopWatch sw = new StopWatch(); |
|
||||||
sw.start(); |
|
||||||
for (int i = 0; i < 1000000; i++) { |
|
||||||
ServletRequestUtils.getFloatParameter(request, "nonExistingParam", 0f); |
|
||||||
} |
|
||||||
sw.stop(); |
|
||||||
System.out.println(sw.getTotalTimeMillis()); |
|
||||||
assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testGetDoubleParameterWithDefaultValueHandlingIsFastEnough() { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
StopWatch sw = new StopWatch(); |
|
||||||
sw.start(); |
|
||||||
for (int i = 0; i < 1000000; i++) { |
|
||||||
ServletRequestUtils.getDoubleParameter(request, "nonExistingParam", 0d); |
|
||||||
} |
|
||||||
sw.stop(); |
|
||||||
System.out.println(sw.getTotalTimeMillis()); |
|
||||||
assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testGetBooleanParameterWithDefaultValueHandlingIsFastEnough() { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
StopWatch sw = new StopWatch(); |
|
||||||
sw.start(); |
|
||||||
for (int i = 0; i < 1000000; i++) { |
|
||||||
ServletRequestUtils.getBooleanParameter(request, "nonExistingParam", false); |
|
||||||
} |
|
||||||
sw.stop(); |
|
||||||
System.out.println(sw.getTotalTimeMillis()); |
|
||||||
assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250); |
|
||||||
} |
|
||||||
|
|
||||||
@Test |
|
||||||
public void testGetStringParameterWithDefaultValueHandlingIsFastEnough() { |
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest(); |
|
||||||
StopWatch sw = new StopWatch(); |
|
||||||
sw.start(); |
|
||||||
for (int i = 0; i < 1000000; i++) { |
|
||||||
ServletRequestUtils.getStringParameter(request, "nonExistingParam", "defaultValue"); |
|
||||||
} |
|
||||||
sw.stop(); |
|
||||||
System.out.println(sw.getTotalTimeMillis()); |
|
||||||
assertTrue("getStringParameter took too long: " + sw.getTotalTimeMillis(), sw.getTotalTimeMillis() < 250); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,485 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2008 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.multipart.commons; |
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream; |
|
||||||
import java.io.File; |
|
||||||
import java.io.IOException; |
|
||||||
import java.io.InputStream; |
|
||||||
import java.io.OutputStream; |
|
||||||
import java.io.UnsupportedEncodingException; |
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.Arrays; |
|
||||||
import java.util.Enumeration; |
|
||||||
import java.util.HashSet; |
|
||||||
import java.util.Iterator; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Map; |
|
||||||
import java.util.Set; |
|
||||||
|
|
||||||
import javax.servlet.FilterChain; |
|
||||||
import javax.servlet.ServletException; |
|
||||||
import javax.servlet.ServletRequest; |
|
||||||
import javax.servlet.ServletResponse; |
|
||||||
import javax.servlet.http.HttpServletRequest; |
|
||||||
import javax.servlet.http.HttpServletResponse; |
|
||||||
|
|
||||||
import junit.framework.TestCase; |
|
||||||
import org.apache.commons.fileupload.FileItem; |
|
||||||
import org.apache.commons.fileupload.FileItemFactory; |
|
||||||
import org.apache.commons.fileupload.FileUpload; |
|
||||||
import org.apache.commons.fileupload.servlet.ServletFileUpload; |
|
||||||
|
|
||||||
import org.springframework.beans.MutablePropertyValues; |
|
||||||
import org.springframework.mock.web.MockFilterConfig; |
|
||||||
import org.springframework.mock.web.MockHttpServletRequest; |
|
||||||
import org.springframework.mock.web.MockHttpServletResponse; |
|
||||||
import org.springframework.mock.web.MockServletContext; |
|
||||||
import org.springframework.mock.web.PassThroughFilterChain; |
|
||||||
import org.springframework.web.bind.ServletRequestDataBinder; |
|
||||||
import org.springframework.web.context.WebApplicationContext; |
|
||||||
import org.springframework.web.context.support.StaticWebApplicationContext; |
|
||||||
import org.springframework.web.multipart.MultipartFile; |
|
||||||
import org.springframework.web.multipart.MultipartHttpServletRequest; |
|
||||||
import org.springframework.web.multipart.support.ByteArrayMultipartFileEditor; |
|
||||||
import org.springframework.web.multipart.support.MultipartFilter; |
|
||||||
import org.springframework.web.multipart.support.StringMultipartFileEditor; |
|
||||||
import org.springframework.web.util.WebUtils; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author Juergen Hoeller |
|
||||||
* @since 08.10.2003 |
|
||||||
*/ |
|
||||||
public class CommonsMultipartResolverTests extends TestCase { |
|
||||||
|
|
||||||
public void testWithApplicationContext() throws Exception { |
|
||||||
doTestWithApplicationContext(false); |
|
||||||
} |
|
||||||
|
|
||||||
public void testWithApplicationContextAndLazyResolution() throws Exception { |
|
||||||
doTestWithApplicationContext(true); |
|
||||||
} |
|
||||||
|
|
||||||
private void doTestWithApplicationContext(boolean lazy) throws Exception { |
|
||||||
StaticWebApplicationContext wac = new StaticWebApplicationContext(); |
|
||||||
wac.setServletContext(new MockServletContext()); |
|
||||||
wac.getServletContext().setAttribute(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE, new File("mytemp")); |
|
||||||
wac.refresh(); |
|
||||||
MockCommonsMultipartResolver resolver = new MockCommonsMultipartResolver(); |
|
||||||
resolver.setMaxUploadSize(1000); |
|
||||||
resolver.setMaxInMemorySize(100); |
|
||||||
resolver.setDefaultEncoding("enc"); |
|
||||||
if (lazy) { |
|
||||||
resolver.setResolveLazily(false); |
|
||||||
} |
|
||||||
resolver.setServletContext(wac.getServletContext()); |
|
||||||
assertEquals(1000, resolver.getFileUpload().getSizeMax()); |
|
||||||
assertEquals(100, resolver.getFileItemFactory().getSizeThreshold()); |
|
||||||
assertEquals("enc", resolver.getFileUpload().getHeaderEncoding()); |
|
||||||
assertTrue(resolver.getFileItemFactory().getRepository().getAbsolutePath().endsWith("mytemp")); |
|
||||||
|
|
||||||
MockHttpServletRequest originalRequest = new MockHttpServletRequest(); |
|
||||||
originalRequest.setMethod("POST"); |
|
||||||
originalRequest.setContentType("multipart/form-data"); |
|
||||||
originalRequest.addHeader("Content-type", "multipart/form-data"); |
|
||||||
originalRequest.addParameter("getField", "getValue"); |
|
||||||
assertTrue(resolver.isMultipart(originalRequest)); |
|
||||||
MultipartHttpServletRequest request = resolver.resolveMultipart(originalRequest); |
|
||||||
|
|
||||||
Set parameterNames = new HashSet(); |
|
||||||
Enumeration parameterEnum = request.getParameterNames(); |
|
||||||
while (parameterEnum.hasMoreElements()) { |
|
||||||
parameterNames.add(parameterEnum.nextElement()); |
|
||||||
} |
|
||||||
assertEquals(3, parameterNames.size()); |
|
||||||
assertTrue(parameterNames.contains("field3")); |
|
||||||
assertTrue(parameterNames.contains("field4")); |
|
||||||
assertTrue(parameterNames.contains("getField")); |
|
||||||
assertEquals("value3", request.getParameter("field3")); |
|
||||||
List parameterValues = Arrays.asList(request.getParameterValues("field3")); |
|
||||||
assertEquals(1, parameterValues.size()); |
|
||||||
assertTrue(parameterValues.contains("value3")); |
|
||||||
assertEquals("value4", request.getParameter("field4")); |
|
||||||
parameterValues = Arrays.asList(request.getParameterValues("field4")); |
|
||||||
assertEquals(2, parameterValues.size()); |
|
||||||
assertTrue(parameterValues.contains("value4")); |
|
||||||
assertTrue(parameterValues.contains("value5")); |
|
||||||
assertEquals("value4", request.getParameter("field4")); |
|
||||||
assertEquals("getValue", request.getParameter("getField")); |
|
||||||
|
|
||||||
List parameterMapKeys = new ArrayList(); |
|
||||||
List parameterMapValues = new ArrayList(); |
|
||||||
for (Iterator parameterMapIter = request.getParameterMap().keySet().iterator(); parameterMapIter.hasNext();) { |
|
||||||
String key = (String) parameterMapIter.next(); |
|
||||||
parameterMapKeys.add(key); |
|
||||||
parameterMapValues.add(request.getParameterMap().get(key)); |
|
||||||
} |
|
||||||
assertEquals(3, parameterMapKeys.size()); |
|
||||||
assertEquals(3, parameterMapValues.size()); |
|
||||||
int field3Index = parameterMapKeys.indexOf("field3"); |
|
||||||
int field4Index = parameterMapKeys.indexOf("field4"); |
|
||||||
int getFieldIndex = parameterMapKeys.indexOf("getField"); |
|
||||||
assertTrue(field3Index != -1); |
|
||||||
assertTrue(field4Index != -1); |
|
||||||
assertTrue(getFieldIndex != -1); |
|
||||||
parameterValues = Arrays.asList((String[]) parameterMapValues.get(field3Index)); |
|
||||||
assertEquals(1, parameterValues.size()); |
|
||||||
assertTrue(parameterValues.contains("value3")); |
|
||||||
parameterValues = Arrays.asList((String[]) parameterMapValues.get(field4Index)); |
|
||||||
assertEquals(2, parameterValues.size()); |
|
||||||
assertTrue(parameterValues.contains("value4")); |
|
||||||
assertTrue(parameterValues.contains("value5")); |
|
||||||
parameterValues = Arrays.asList((String[]) parameterMapValues.get(getFieldIndex)); |
|
||||||
assertEquals(1, parameterValues.size()); |
|
||||||
assertTrue(parameterValues.contains("getValue")); |
|
||||||
|
|
||||||
Set fileNames = new HashSet(); |
|
||||||
Iterator fileIter = request.getFileNames(); |
|
||||||
while (fileIter.hasNext()) { |
|
||||||
fileNames.add(fileIter.next()); |
|
||||||
} |
|
||||||
assertEquals(3, fileNames.size()); |
|
||||||
assertTrue(fileNames.contains("field1")); |
|
||||||
assertTrue(fileNames.contains("field2")); |
|
||||||
assertTrue(fileNames.contains("field2x")); |
|
||||||
CommonsMultipartFile file1 = (CommonsMultipartFile) request.getFile("field1"); |
|
||||||
CommonsMultipartFile file2 = (CommonsMultipartFile) request.getFile("field2"); |
|
||||||
CommonsMultipartFile file2x = (CommonsMultipartFile) request.getFile("field2x"); |
|
||||||
Map fileMap = request.getFileMap(); |
|
||||||
assertEquals(3, fileMap.size()); |
|
||||||
assertTrue(fileMap.containsKey("field1")); |
|
||||||
assertTrue(fileMap.containsKey("field2")); |
|
||||||
assertTrue(fileMap.containsKey("field2x")); |
|
||||||
assertEquals(file1, fileMap.get("field1")); |
|
||||||
assertEquals(file2, fileMap.get("field2")); |
|
||||||
assertEquals(file2x, fileMap.get("field2x")); |
|
||||||
|
|
||||||
assertEquals("type1", file1.getContentType()); |
|
||||||
assertEquals("type2", file2.getContentType()); |
|
||||||
assertEquals("type2", file2x.getContentType()); |
|
||||||
assertEquals("field1.txt", file1.getOriginalFilename()); |
|
||||||
assertEquals("field2.txt", file2.getOriginalFilename()); |
|
||||||
assertEquals("field2x.txt", file2x.getOriginalFilename()); |
|
||||||
assertEquals("text1", new String(file1.getBytes())); |
|
||||||
assertEquals("text2", new String(file2.getBytes())); |
|
||||||
assertEquals(5, file1.getSize()); |
|
||||||
assertEquals(5, file2.getSize()); |
|
||||||
assertTrue(file1.getInputStream() instanceof ByteArrayInputStream); |
|
||||||
assertTrue(file2.getInputStream() instanceof ByteArrayInputStream); |
|
||||||
File transfer1 = new File("C:/transfer1"); |
|
||||||
File transfer2 = new File("C:/transfer2"); |
|
||||||
file1.transferTo(transfer1); |
|
||||||
file2.transferTo(transfer2); |
|
||||||
assertEquals(transfer1, ((MockFileItem) file1.getFileItem()).writtenFile); |
|
||||||
assertEquals(transfer2, ((MockFileItem) file2.getFileItem()).writtenFile); |
|
||||||
|
|
||||||
MultipartTestBean1 mtb1 = new MultipartTestBean1(); |
|
||||||
assertEquals(null, mtb1.getField1()); |
|
||||||
assertEquals(null, mtb1.getField2()); |
|
||||||
ServletRequestDataBinder binder = new ServletRequestDataBinder(mtb1, "mybean"); |
|
||||||
binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor()); |
|
||||||
binder.bind(request); |
|
||||||
assertEquals(file1, mtb1.getField1()); |
|
||||||
assertEquals(new String(file2.getBytes()), new String(mtb1.getField2())); |
|
||||||
|
|
||||||
MultipartTestBean2 mtb2 = new MultipartTestBean2(); |
|
||||||
assertEquals(null, mtb2.getField1()); |
|
||||||
assertEquals(null, mtb2.getField2()); |
|
||||||
binder = new ServletRequestDataBinder(mtb2, "mybean"); |
|
||||||
binder.registerCustomEditor(String.class, "field1", new StringMultipartFileEditor()); |
|
||||||
binder.registerCustomEditor(String.class, "field2", new StringMultipartFileEditor("UTF-16")); |
|
||||||
binder.bind(request); |
|
||||||
assertEquals(new String(file1.getBytes()), mtb2.getField1()); |
|
||||||
assertEquals(new String(file2.getBytes(), "UTF-16"), mtb2.getField2()); |
|
||||||
|
|
||||||
resolver.cleanupMultipart(request); |
|
||||||
assertTrue(((MockFileItem) file1.getFileItem()).deleted); |
|
||||||
assertTrue(((MockFileItem) file2.getFileItem()).deleted); |
|
||||||
|
|
||||||
resolver.setEmpty(true); |
|
||||||
request = resolver.resolveMultipart(originalRequest); |
|
||||||
binder.setBindEmptyMultipartFiles(false); |
|
||||||
String firstBound = mtb2.getField1(); |
|
||||||
binder.bind(request); |
|
||||||
assertTrue(mtb2.getField1().length() > 0); |
|
||||||
assertEquals(firstBound, mtb2.getField1()); |
|
||||||
|
|
||||||
request = resolver.resolveMultipart(originalRequest); |
|
||||||
binder.setBindEmptyMultipartFiles(true); |
|
||||||
binder.bind(request); |
|
||||||
assertTrue(mtb2.getField1().length() == 0); |
|
||||||
} |
|
||||||
|
|
||||||
public void testWithServletContextAndFilter() throws Exception { |
|
||||||
StaticWebApplicationContext wac = new StaticWebApplicationContext(); |
|
||||||
wac.setServletContext(new MockServletContext()); |
|
||||||
wac.registerSingleton("filterMultipartResolver", MockCommonsMultipartResolver.class, new MutablePropertyValues()); |
|
||||||
wac.getServletContext().setAttribute(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE, new File("mytemp")); |
|
||||||
wac.refresh(); |
|
||||||
wac.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac); |
|
||||||
CommonsMultipartResolver resolver = new CommonsMultipartResolver(wac.getServletContext()); |
|
||||||
assertTrue(resolver.getFileItemFactory().getRepository().getAbsolutePath().endsWith("mytemp")); |
|
||||||
|
|
||||||
MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter"); |
|
||||||
filterConfig.addInitParameter("class", "notWritable"); |
|
||||||
filterConfig.addInitParameter("unknownParam", "someValue"); |
|
||||||
final MultipartFilter filter = new MultipartFilter(); |
|
||||||
filter.init(filterConfig); |
|
||||||
|
|
||||||
final List files = new ArrayList(); |
|
||||||
final FilterChain filterChain = new FilterChain() { |
|
||||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) { |
|
||||||
MultipartHttpServletRequest request = (MultipartHttpServletRequest) servletRequest; |
|
||||||
files.addAll(request.getFileMap().values()); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
FilterChain filterChain2 = new PassThroughFilterChain(filter, filterChain); |
|
||||||
|
|
||||||
MockHttpServletRequest originalRequest = new MockHttpServletRequest(); |
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse(); |
|
||||||
originalRequest.setMethod("POST"); |
|
||||||
originalRequest.setContentType("multipart/form-data"); |
|
||||||
originalRequest.addHeader("Content-type", "multipart/form-data"); |
|
||||||
filter.doFilter(originalRequest, response, filterChain2); |
|
||||||
|
|
||||||
CommonsMultipartFile file1 = (CommonsMultipartFile) files.get(0); |
|
||||||
CommonsMultipartFile file2 = (CommonsMultipartFile) files.get(1); |
|
||||||
assertTrue(((MockFileItem) file1.getFileItem()).deleted); |
|
||||||
assertTrue(((MockFileItem) file2.getFileItem()).deleted); |
|
||||||
} |
|
||||||
|
|
||||||
public void testWithServletContextAndFilterWithCustomBeanName() throws Exception { |
|
||||||
StaticWebApplicationContext wac = new StaticWebApplicationContext(); |
|
||||||
wac.setServletContext(new MockServletContext()); |
|
||||||
wac.refresh(); |
|
||||||
wac.registerSingleton("myMultipartResolver", MockCommonsMultipartResolver.class, new MutablePropertyValues()); |
|
||||||
wac.getServletContext().setAttribute(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE, new File("mytemp")); |
|
||||||
wac.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac); |
|
||||||
CommonsMultipartResolver resolver = new CommonsMultipartResolver(wac.getServletContext()); |
|
||||||
assertTrue(resolver.getFileItemFactory().getRepository().getAbsolutePath().endsWith("mytemp")); |
|
||||||
|
|
||||||
MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter"); |
|
||||||
filterConfig.addInitParameter("multipartResolverBeanName", "myMultipartResolver"); |
|
||||||
|
|
||||||
final List files = new ArrayList(); |
|
||||||
FilterChain filterChain = new FilterChain() { |
|
||||||
public void doFilter(ServletRequest originalRequest, ServletResponse response) { |
|
||||||
if (originalRequest instanceof MultipartHttpServletRequest) { |
|
||||||
MultipartHttpServletRequest request = (MultipartHttpServletRequest) originalRequest; |
|
||||||
files.addAll(request.getFileMap().values()); |
|
||||||
} |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
MultipartFilter filter = new MultipartFilter() { |
|
||||||
private boolean invoked = false; |
|
||||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, |
|
||||||
FilterChain filterChain) throws ServletException, IOException { |
|
||||||
super.doFilterInternal(request, response, filterChain); |
|
||||||
super.doFilterInternal(request, response, filterChain); |
|
||||||
if (invoked) { |
|
||||||
throw new ServletException("Should not have been invoked twice"); |
|
||||||
} |
|
||||||
invoked = true; |
|
||||||
} |
|
||||||
}; |
|
||||||
filter.init(filterConfig); |
|
||||||
|
|
||||||
MockHttpServletRequest originalRequest = new MockHttpServletRequest(); |
|
||||||
originalRequest.setMethod("POST"); |
|
||||||
originalRequest.setContentType("multipart/form-data"); |
|
||||||
originalRequest.addHeader("Content-type", "multipart/form-data"); |
|
||||||
HttpServletResponse response = new MockHttpServletResponse(); |
|
||||||
filter.doFilter(originalRequest, response, filterChain); |
|
||||||
CommonsMultipartFile file1 = (CommonsMultipartFile) files.get(0); |
|
||||||
CommonsMultipartFile file2 = (CommonsMultipartFile) files.get(1); |
|
||||||
assertTrue(((MockFileItem) file1.getFileItem()).deleted); |
|
||||||
assertTrue(((MockFileItem) file2.getFileItem()).deleted); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public static class MockCommonsMultipartResolver extends CommonsMultipartResolver { |
|
||||||
|
|
||||||
private boolean empty; |
|
||||||
|
|
||||||
protected void setEmpty(boolean empty) { |
|
||||||
this.empty = empty; |
|
||||||
} |
|
||||||
|
|
||||||
protected FileUpload newFileUpload(FileItemFactory fileItemFactory) { |
|
||||||
return new ServletFileUpload() { |
|
||||||
public List parseRequest(HttpServletRequest request) { |
|
||||||
if (request instanceof MultipartHttpServletRequest) { |
|
||||||
throw new IllegalStateException("Already a multipart request"); |
|
||||||
} |
|
||||||
List fileItems = new ArrayList(); |
|
||||||
MockFileItem fileItem1 = new MockFileItem( |
|
||||||
"field1", "type1", empty ? "" : "field1.txt", empty ? "" : "text1"); |
|
||||||
MockFileItem fileItem2 = new MockFileItem( |
|
||||||
"field2", "type2", empty ? "" : "C:/field2.txt", empty ? "" : "text2"); |
|
||||||
MockFileItem fileItem2x = new MockFileItem( |
|
||||||
"field2x", "type2", empty ? "" : "C:\\field2x.txt", empty ? "" : "text2"); |
|
||||||
MockFileItem fileItem3 = new MockFileItem("field3", null, null, "value3"); |
|
||||||
MockFileItem fileItem4 = new MockFileItem("field4", null, null, "value4"); |
|
||||||
MockFileItem fileItem5 = new MockFileItem("field4", null, null, "value5"); |
|
||||||
fileItems.add(fileItem1); |
|
||||||
fileItems.add(fileItem2); |
|
||||||
fileItems.add(fileItem2x); |
|
||||||
fileItems.add(fileItem3); |
|
||||||
fileItems.add(fileItem4); |
|
||||||
fileItems.add(fileItem5); |
|
||||||
return fileItems; |
|
||||||
} |
|
||||||
}; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
private static class MockFileItem implements FileItem { |
|
||||||
|
|
||||||
private String fieldName; |
|
||||||
private String contentType; |
|
||||||
private String name; |
|
||||||
private String value; |
|
||||||
|
|
||||||
private File writtenFile; |
|
||||||
private boolean deleted; |
|
||||||
|
|
||||||
public MockFileItem(String fieldName, String contentType, String name, String value) { |
|
||||||
this.fieldName = fieldName; |
|
||||||
this.contentType = contentType; |
|
||||||
this.name = name; |
|
||||||
this.value = value; |
|
||||||
} |
|
||||||
|
|
||||||
public InputStream getInputStream() throws IOException { |
|
||||||
return new ByteArrayInputStream(value.getBytes()); |
|
||||||
} |
|
||||||
|
|
||||||
public String getContentType() { |
|
||||||
return contentType; |
|
||||||
} |
|
||||||
|
|
||||||
public String getName() { |
|
||||||
return name; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isInMemory() { |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
public long getSize() { |
|
||||||
return value.length(); |
|
||||||
} |
|
||||||
|
|
||||||
public byte[] get() { |
|
||||||
return value.getBytes(); |
|
||||||
} |
|
||||||
|
|
||||||
public String getString(String encoding) throws UnsupportedEncodingException { |
|
||||||
return new String(get(), encoding); |
|
||||||
} |
|
||||||
|
|
||||||
public String getString() { |
|
||||||
return value; |
|
||||||
} |
|
||||||
|
|
||||||
public void write(File file) throws Exception { |
|
||||||
this.writtenFile = file; |
|
||||||
} |
|
||||||
|
|
||||||
public File getWrittenFile() { |
|
||||||
return writtenFile; |
|
||||||
} |
|
||||||
|
|
||||||
public void delete() { |
|
||||||
this.deleted = true; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isDeleted() { |
|
||||||
return deleted; |
|
||||||
} |
|
||||||
|
|
||||||
public String getFieldName() { |
|
||||||
return fieldName; |
|
||||||
} |
|
||||||
|
|
||||||
public void setFieldName(String s) { |
|
||||||
this.fieldName = s; |
|
||||||
} |
|
||||||
|
|
||||||
public boolean isFormField() { |
|
||||||
return (this.name == null); |
|
||||||
} |
|
||||||
|
|
||||||
public void setFormField(boolean b) { |
|
||||||
throw new UnsupportedOperationException(); |
|
||||||
} |
|
||||||
|
|
||||||
public OutputStream getOutputStream() throws IOException { |
|
||||||
throw new UnsupportedOperationException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public class MultipartTestBean1 { |
|
||||||
|
|
||||||
private MultipartFile field1; |
|
||||||
private byte[] field2; |
|
||||||
|
|
||||||
public void setField1(MultipartFile field1) { |
|
||||||
this.field1 = field1; |
|
||||||
} |
|
||||||
|
|
||||||
public MultipartFile getField1() { |
|
||||||
return field1; |
|
||||||
} |
|
||||||
|
|
||||||
public void setField2(byte[] field2) { |
|
||||||
this.field2 = field2; |
|
||||||
} |
|
||||||
|
|
||||||
public byte[] getField2() { |
|
||||||
return field2; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
public class MultipartTestBean2 { |
|
||||||
|
|
||||||
private String field1; |
|
||||||
private String field2; |
|
||||||
|
|
||||||
public void setField1(String field1) { |
|
||||||
this.field1 = field1; |
|
||||||
} |
|
||||||
|
|
||||||
public String getField1() { |
|
||||||
return field1; |
|
||||||
} |
|
||||||
|
|
||||||
public void setField2(String field2) { |
|
||||||
this.field2 = field2; |
|
||||||
} |
|
||||||
|
|
||||||
public String getField2() { |
|
||||||
return field2; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -1,92 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright 2002-2006 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.multipart.support; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
|
|
||||||
import junit.framework.TestCase; |
|
||||||
import org.easymock.MockControl; |
|
||||||
|
|
||||||
import org.springframework.web.multipart.MultipartFile; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author Rick Evans |
|
||||||
*/ |
|
||||||
public final class ByteArrayMultipartFileEditorTests extends TestCase { |
|
||||||
|
|
||||||
public void testSetValueAsByteArray() throws Exception { |
|
||||||
ByteArrayMultipartFileEditor editor = new ByteArrayMultipartFileEditor(); |
|
||||||
String expectedValue = "Shumwere, shumhow, a shuck ish washing you. - Drunken Far Side"; |
|
||||||
editor.setValue(expectedValue.getBytes()); |
|
||||||
assertEquals(expectedValue, editor.getAsText()); |
|
||||||
} |
|
||||||
|
|
||||||
public void testSetValueAsString() throws Exception { |
|
||||||
ByteArrayMultipartFileEditor editor = new ByteArrayMultipartFileEditor(); |
|
||||||
String expectedValue = "'Green Wing' - classic British comedy"; |
|
||||||
editor.setValue(expectedValue); |
|
||||||
assertEquals(expectedValue, editor.getAsText()); |
|
||||||
} |
|
||||||
|
|
||||||
public void testSetValueAsCustomObjectInvokesToString() throws Exception { |
|
||||||
ByteArrayMultipartFileEditor editor = new ByteArrayMultipartFileEditor(); |
|
||||||
final String expectedValue = "'Green Wing' - classic British comedy"; |
|
||||||
Object object = new Object() { |
|
||||||
public String toString() { |
|
||||||
return expectedValue; |
|
||||||
} |
|
||||||
}; |
|
||||||
editor.setValue(object); |
|
||||||
assertEquals(expectedValue, editor.getAsText()); |
|
||||||
} |
|
||||||
|
|
||||||
public void testSetValueAsNullGetsBackEmptyString() throws Exception { |
|
||||||
ByteArrayMultipartFileEditor editor = new ByteArrayMultipartFileEditor(); |
|
||||||
editor.setValue(null); |
|
||||||
assertEquals("", editor.getAsText()); |
|
||||||
} |
|
||||||
|
|
||||||
public void testSetValueAsMultipartFile() throws Exception { |
|
||||||
String expectedValue = "That is comforting to know"; |
|
||||||
ByteArrayMultipartFileEditor editor = new ByteArrayMultipartFileEditor(); |
|
||||||
MockControl mock = MockControl.createControl(MultipartFile.class); |
|
||||||
MultipartFile file = (MultipartFile) mock.getMock(); |
|
||||||
file.getBytes(); |
|
||||||
mock.setReturnValue(expectedValue.getBytes()); |
|
||||||
mock.replay(); |
|
||||||
editor.setValue(file); |
|
||||||
assertEquals(expectedValue, editor.getAsText()); |
|
||||||
mock.verify(); |
|
||||||
} |
|
||||||
|
|
||||||
public void testSetValueAsMultipartFileWithBadBytes() throws Exception { |
|
||||||
ByteArrayMultipartFileEditor editor = new ByteArrayMultipartFileEditor(); |
|
||||||
MockControl mock = MockControl.createControl(MultipartFile.class); |
|
||||||
MultipartFile file = (MultipartFile) mock.getMock(); |
|
||||||
file.getBytes(); |
|
||||||
mock.setThrowable(new IOException()); |
|
||||||
mock.replay(); |
|
||||||
try { |
|
||||||
editor.setValue(file); |
|
||||||
fail("Must have thrown an IllegalArgumentException: IOException thrown when reading MultipartFile bytes"); |
|
||||||
} |
|
||||||
catch (IllegalArgumentException expected) { |
|
||||||
} |
|
||||||
mock.verify(); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
Loading…
Reference in new issue