diff --git a/org.springframework.test/src/main/java/org/springframework/mock/web/HeaderValueHolder.java b/org.springframework.test/src/main/java/org/springframework/mock/web/HeaderValueHolder.java index fe5a0bc23fc..afe74ad8f0f 100644 --- a/org.springframework.test/src/main/java/org/springframework/mock/web/HeaderValueHolder.java +++ b/org.springframework.test/src/main/java/org/springframework/mock/web/HeaderValueHolder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2011 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. @@ -71,6 +71,10 @@ class HeaderValueHolder { return (!this.values.isEmpty() ? this.values.get(0) : null); } + public String getStringValue() { + return (!this.values.isEmpty() ? this.values.get(0).toString() : null); + } + /** * Find a HeaderValueHolder by name, ignoring casing. diff --git a/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java b/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java index c19cbc67b86..c340d838092 100644 --- a/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java +++ b/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 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. @@ -18,6 +18,7 @@ package org.springframework.mock.web; import java.io.BufferedReader; import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; @@ -35,24 +36,24 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.Vector; - import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; +import javax.servlet.ServletException; import javax.servlet.ServletInputStream; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.util.Assert; import org.springframework.util.LinkedCaseInsensitiveMap; /** - * Mock implementation of the {@link javax.servlet.http.HttpServletRequest} - * interface. Supports the Servlet 2.5 API level. - *

- * Used for testing the web framework; also useful for testing application - * controllers. - * + * Mock implementation of the {@link javax.servlet.http.HttpServletRequest} interface. + * + *

Compatible with Servlet 2.5 and partially with Servlet 3.0 (notable exceptions: + * the getPart(s) and startAsync families of methods). + * * @author Juergen Hoeller * @author Rod Johnson * @author Rick Evans @@ -93,6 +94,7 @@ public class MockHttpServletRequest implements HttpServletRequest { private boolean active = true; + // --------------------------------------------------------------------- // ServletRequest properties // --------------------------------------------------------------------- @@ -134,6 +136,7 @@ public class MockHttpServletRequest implements HttpServletRequest { private int localPort = DEFAULT_SERVER_PORT; + // --------------------------------------------------------------------- // HttpServletRequest properties // --------------------------------------------------------------------- @@ -180,7 +183,6 @@ public class MockHttpServletRequest implements HttpServletRequest { /** * Create a new MockHttpServletRequest with a default * {@link MockServletContext}. - * * @see MockServletContext */ public MockHttpServletRequest() { @@ -190,7 +192,6 @@ public class MockHttpServletRequest implements HttpServletRequest { /** * Create a new MockHttpServletRequest with a default * {@link MockServletContext}. - * * @param method the request method (may be null) * @param requestURI the request URI (may be null) * @see #setMethod @@ -203,7 +204,6 @@ public class MockHttpServletRequest implements HttpServletRequest { /** * Create a new MockHttpServletRequest. - * * @param servletContext the ServletContext that the request runs in (may be * null to use a default MockServletContext) * @see MockServletContext @@ -214,7 +214,6 @@ public class MockHttpServletRequest implements HttpServletRequest { /** * Create a new MockHttpServletRequest. - * * @param servletContext the ServletContext that the request runs in (may be * null to use a default MockServletContext) * @param method the request method (may be null) @@ -230,6 +229,7 @@ public class MockHttpServletRequest implements HttpServletRequest { this.locales.add(Locale.ENGLISH); } + // --------------------------------------------------------------------- // Lifecycle methods // --------------------------------------------------------------------- @@ -274,6 +274,7 @@ public class MockHttpServletRequest implements HttpServletRequest { } } + // --------------------------------------------------------------------- // ServletRequest interface // --------------------------------------------------------------------- @@ -603,6 +604,7 @@ public class MockHttpServletRequest implements HttpServletRequest { return this.localPort; } + // --------------------------------------------------------------------- // HttpServletRequest interface // --------------------------------------------------------------------- @@ -625,18 +627,15 @@ public class MockHttpServletRequest implements HttpServletRequest { /** * Add a header entry for the given name. - *

- * If there was no entry for that header name before, the value will be used + *

If there was no entry for that header name before, the value will be used * as-is. In case of an existing entry, a String array will be created, * adding the given value (more specifically, its toString representation) * as further element. - *

- * Multiple values can only be stored as list of Strings, following the + *

Multiple values can only be stored as list of Strings, following the * Servlet spec (see getHeaders accessor). As alternative to * repeated addHeader calls for individual elements, you can * use a single call with an entire array or Collection of values as * parameter. - * * @see #getHeaderNames * @see #getHeader * @see #getHeaders @@ -680,20 +679,6 @@ public class MockHttpServletRequest implements HttpServletRequest { } } - public String getHeader(String name) { - HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); - return (header != null ? header.getValue().toString() : null); - } - - public Enumeration getHeaders(String name) { - HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); - return Collections.enumeration(header != null ? header.getStringValues() : new LinkedList()); - } - - public Enumeration getHeaderNames() { - return Collections.enumeration(this.headers.keySet()); - } - public int getIntHeader(String name) { HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); Object value = (header != null ? header.getValue() : null); @@ -711,6 +696,20 @@ public class MockHttpServletRequest implements HttpServletRequest { } } + public String getHeader(String name) { + HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); + return (header != null ? header.getStringValue() : null); + } + + public Enumeration getHeaders(String name) { + HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); + return Collections.enumeration(header != null ? header.getStringValues() : new LinkedList()); + } + + public Enumeration getHeaderNames() { + return Collections.enumeration(this.headers.keySet()); + } + public void setMethod(String method) { this.method = method; } @@ -760,7 +759,8 @@ public class MockHttpServletRequest implements HttpServletRequest { } public boolean isUserInRole(String role) { - return this.userRoles.contains(role); + return (this.userRoles.contains(role) || (this.servletContext instanceof MockServletContext && + ((MockServletContext) this.servletContext).getDeclaredRoles().contains(role))); } public void setUserPrincipal(Principal userPrincipal) { @@ -855,4 +855,18 @@ public class MockHttpServletRequest implements HttpServletRequest { return isRequestedSessionIdFromURL(); } + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { + return (this.userPrincipal != null && this.remoteUser != null && this.authType != null); + } + + public void login(String username, String password) throws ServletException { + throw new ServletException("Username-password authentication not supported - override the login method"); + } + + public void logout() throws ServletException { + this.userPrincipal = null; + this.remoteUser = null; + this.authType = null; + } + } diff --git a/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java b/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java index 6d220572665..2c84f96b8ab 100644 --- a/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java +++ b/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 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. @@ -38,11 +38,9 @@ import org.springframework.util.LinkedCaseInsensitiveMap; import org.springframework.web.util.WebUtils; /** - * Mock implementation of the {@link javax.servlet.http.HttpServletResponse} - * interface. Supports the Servlet 2.5 API level. + * Mock implementation of the {@link javax.servlet.http.HttpServletResponse} interface. * - *

Used for testing the web framework; also useful for testing - * application controllers. + *

Compatible with Servlet 2.5 as well as Servlet 3.0. * * @author Juergen Hoeller * @author Rod Johnson @@ -50,8 +48,6 @@ import org.springframework.web.util.WebUtils; */ public class MockHttpServletResponse implements HttpServletResponse { - public static final int DEFAULT_SERVER_PORT = 80; - private static final String CHARSET_PREFIX = "charset="; @@ -280,19 +276,52 @@ public class MockHttpServletResponse implements HttpServletResponse { /** * Return the names of all specified headers as a Set of Strings. + *

As of Servlet 3.0, this method is also defined HttpServletResponse. * @return the Set of header name Strings, or an empty Set if none */ public Set getHeaderNames() { return this.headers.keySet(); } + /** + * Return the primary value for the given header as a String, if any. + * Will return the first value in case of multiple values. + *

As of Servlet 3.0, this method is also defined HttpServletResponse. + * As of Spring 3.1, it returns a stringified value for Servlet 3.0 compatibility. + * Consider using {@link #getHeaderValue(String)} for raw Object access. + * @param name the name of the header + * @return the associated header value, or null if none + */ + public String getHeader(String name) { + HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); + return (header != null ? header.getStringValue() : null); + } + + /** + * Return all values for the given header as a List of Strings. + *

As of Servlet 3.0, this method is also defined HttpServletResponse. + * As of Spring 3.1, it returns a List of stringified values for Servlet 3.0 compatibility. + * Consider using {@link #getHeaderValues(String)} for raw Object access. + * @param name the name of the header + * @return the associated header values, or an empty List if none + */ + public List getHeaders(String name) { + HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); + if (header != null) { + return header.getStringValues(); + } + else { + return Collections.emptyList(); + } + } + /** * Return the primary value for the given header, if any. *

Will return the first value in case of multiple values. * @param name the name of the header * @return the associated header value, or null if none */ - public Object getHeader(String name) { + public Object getHeaderValue(String name) { HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); return (header != null ? header.getValue() : null); } @@ -302,9 +331,14 @@ public class MockHttpServletResponse implements HttpServletResponse { * @param name the name of the header * @return the associated header values, or an empty List if none */ - public List getHeaders(String name) { + public List getHeaderValues(String name) { HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); - return (header != null ? header.getValues() : Collections.emptyList()); + if (header != null) { + return header.getValues(); + } + else { + return Collections.emptyList(); + } } /** diff --git a/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpSession.java b/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpSession.java index dc8a913a346..3b30a83e32b 100644 --- a/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpSession.java +++ b/org.springframework.test/src/main/java/org/springframework/mock/web/MockHttpSession.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 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. @@ -23,7 +23,6 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Vector; - import javax.servlet.ServletContext; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionBindingEvent; @@ -34,11 +33,9 @@ import org.springframework.util.Assert; /** * Mock implementation of the {@link javax.servlet.http.HttpSession} interface. - * Supports the Servlet 2.4 API level. - *

- * Used for testing the web framework; also useful for testing application - * controllers. - * + * + *

Compatible with Servlet 2.5 as well as Servlet 3.0. + * * @author Juergen Hoeller * @author Rod Johnson * @author Mark Fisher @@ -47,8 +44,6 @@ import org.springframework.util.Assert; @SuppressWarnings("deprecation") public class MockHttpSession implements HttpSession { - public static final String SESSION_COOKIE_NAME = "JSESSION"; - private static int nextId = 1; private final String id; diff --git a/org.springframework.test/src/main/java/org/springframework/mock/web/MockServletContext.java b/org.springframework.test/src/main/java/org/springframework/mock/web/MockServletContext.java index 59956a3d9be..e829e5708f8 100644 --- a/org.springframework.test/src/main/java/org/springframework/mock/web/MockServletContext.java +++ b/org.springframework.test/src/main/java/org/springframework/mock/web/MockServletContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 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. @@ -42,12 +42,20 @@ import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; import org.springframework.web.util.WebUtils; /** * Mock implementation of the {@link javax.servlet.ServletContext} interface. * + *

Compatible with Servlet 2.5 and partially with Servlet 3.0. Can be configured to + * expose a specific version through {@link #setMajorVersion}/{@link #setMinorVersion}; + * default is 2.5. Note that Servlet 3.0 support is limited: servlet, filter and listener + * registration methods are not supported; neither is cookie or JSP configuration. + * We generally do not recommend to unit-test your ServletContainerInitializers and + * WebApplicationInitializers which is where those registration methods would be used. + * *

Used for testing the Spring web framework; only rarely necessary for testing * application controllers. As long as application components don't explicitly * access the ServletContext, ClassPathXmlApplicationContext or @@ -90,8 +98,14 @@ public class MockServletContext implements ServletContext { private String contextPath = ""; + private int majorVersion = 2; + private int minorVersion = 5; + private int effectiveMajorVersion = 2; + + private int effectiveMinorVersion = 5; + private final Map contexts = new HashMap(); private final Map initParameters = new LinkedHashMap(); @@ -100,6 +114,8 @@ public class MockServletContext implements ServletContext { private String servletContextName = "MockServletContext"; + private final Set declaredRoles = new HashSet(); + /** * Create a new MockServletContext, using no base path and a @@ -179,14 +195,15 @@ public class MockServletContext implements ServletContext { return this.contexts.get(contextPath); } + public void setMajorVersion(int majorVersion) { + this.majorVersion = majorVersion; + } + public int getMajorVersion() { - return 2; + return this.majorVersion; } public void setMinorVersion(int minorVersion) { - if (minorVersion < 3 || minorVersion > 5) { - throw new IllegalArgumentException("Only Servlet minor versions between 3 and 5 are supported"); - } this.minorVersion = minorVersion; } @@ -194,6 +211,22 @@ public class MockServletContext implements ServletContext { return this.minorVersion; } + public void setEffectiveMajorVersion(int effectiveMajorVersion) { + this.effectiveMajorVersion = effectiveMajorVersion; + } + + public int getEffectiveMajorVersion() { + return this.effectiveMajorVersion; + } + + public void setEffectiveMinorVersion(int effectiveMinorVersion) { + this.effectiveMinorVersion = effectiveMinorVersion; + } + + public int getEffectiveMinorVersion() { + return this.effectiveMinorVersion; + } + public String getMimeType(String filePath) { return MimeTypeResolver.getMimeType(filePath); } @@ -309,15 +342,24 @@ public class MockServletContext implements ServletContext { return this.initParameters.get(name); } + public Enumeration getInitParameterNames() { + return Collections.enumeration(this.initParameters.keySet()); + } + + public boolean setInitParameter(String name, String value) { + Assert.notNull(name, "Parameter name must not be null"); + if (this.initParameters.containsKey(name)) { + return false; + } + this.initParameters.put(name, value); + return true; + } + public void addInitParameter(String name, String value) { Assert.notNull(name, "Parameter name must not be null"); this.initParameters.put(name, value); } - public Enumeration getInitParameterNames() { - return Collections.enumeration(this.initParameters.keySet()); - } - public Object getAttribute(String name) { Assert.notNull(name, "Attribute name must not be null"); return this.attributes.get(name); @@ -350,6 +392,22 @@ public class MockServletContext implements ServletContext { return this.servletContextName; } + public ClassLoader getClassLoader() { + return ClassUtils.getDefaultClassLoader(); + } + + public void declareRoles(String... roleNames) { + Assert.notNull(roleNames, "Role names array must not be null"); + for (String roleName : roleNames) { + Assert.hasLength(roleName, "Role name must not be empty"); + this.declaredRoles.add(roleName); + } + } + + public Set getDeclaredRoles() { + return Collections.unmodifiableSet(this.declaredRoles); + } + /** * Inner factory class used to just introduce a Java Activation Framework