1 /* 2 * Copyright 2002-2009 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.mock.web; 18 19 import java.io.Serializable; 20 import java.util.Collections; 21 import java.util.Enumeration; 22 import java.util.HashMap; 23 import java.util.Iterator; 24 import java.util.LinkedHashMap; 25 import java.util.Map; 26 import javax.servlet.ServletContext; 27 import javax.servlet.http.HttpSession; 28 import javax.servlet.http.HttpSessionBindingEvent; 29 import javax.servlet.http.HttpSessionBindingListener; 30 import javax.servlet.http.HttpSessionContext; 31 32 import org.springframework.util.Assert; 33 34 /** 35 * Mock implementation of the {@link javax.servlet.http.HttpSession} interface. 36 * Supports the Servlet 2.4 API level. 37 * 38 * <p>Used for testing the web framework; also useful for testing 39 * application controllers. 40 * 41 * @author Juergen Hoeller 42 * @author Rod Johnson 43 * @author Mark Fisher 44 * @since 1.0.2 45 */ 46 public class MockHttpSession implements HttpSession { 47 48 public static final String SESSION_COOKIE_NAME = "JSESSION"; 49 50 private static int nextId = 1; 51 52 53 private final String id; 54 55 private final long creationTime = System.currentTimeMillis(); 56 57 private int maxInactiveInterval; 58 59 private long lastAccessedTime = System.currentTimeMillis(); 60 61 private final ServletContext servletContext; 62 63 private final Map<String, Object> attributes = new LinkedHashMap<String, Object>(); 64 65 private boolean invalid = false; 66 67 private boolean isNew = true; 68 69 70 /** 71 * Create a new MockHttpSession with a default {@link org.springframework.mock.web.MockServletContext}. 72 * @see org.springframework.mock.web.MockServletContext 73 */ MockHttpSession()74 public MockHttpSession() { 75 this(null); 76 } 77 78 /** 79 * Create a new MockHttpSession. 80 * @param servletContext the ServletContext that the session runs in 81 */ MockHttpSession(ServletContext servletContext)82 public MockHttpSession(ServletContext servletContext) { 83 this(servletContext, null); 84 } 85 86 /** 87 * Create a new MockHttpSession. 88 * @param servletContext the ServletContext that the session runs in 89 * @param id a unique identifier for this session 90 */ MockHttpSession(ServletContext servletContext, String id)91 public MockHttpSession(ServletContext servletContext, String id) { 92 this.servletContext = (servletContext != null ? servletContext : new MockServletContext()); 93 this.id = (id != null ? id : Integer.toString(nextId++)); 94 } 95 96 getCreationTime()97 public long getCreationTime() { 98 return this.creationTime; 99 } 100 getId()101 public String getId() { 102 return this.id; 103 } 104 access()105 public void access() { 106 this.lastAccessedTime = System.currentTimeMillis(); 107 this.isNew = false; 108 } 109 getLastAccessedTime()110 public long getLastAccessedTime() { 111 return this.lastAccessedTime; 112 } 113 getServletContext()114 public ServletContext getServletContext() { 115 return this.servletContext; 116 } 117 setMaxInactiveInterval(int interval)118 public void setMaxInactiveInterval(int interval) { 119 this.maxInactiveInterval = interval; 120 } 121 getMaxInactiveInterval()122 public int getMaxInactiveInterval() { 123 return this.maxInactiveInterval; 124 } 125 getSessionContext()126 public HttpSessionContext getSessionContext() { 127 throw new UnsupportedOperationException("getSessionContext"); 128 } 129 getAttribute(String name)130 public Object getAttribute(String name) { 131 Assert.notNull(name, "Attribute name must not be null"); 132 return this.attributes.get(name); 133 } 134 getValue(String name)135 public Object getValue(String name) { 136 return getAttribute(name); 137 } 138 getAttributeNames()139 public Enumeration<String> getAttributeNames() { 140 return Collections.enumeration(this.attributes.keySet()); 141 } 142 getValueNames()143 public String[] getValueNames() { 144 return this.attributes.keySet().toArray(new String[this.attributes.size()]); 145 } 146 setAttribute(String name, Object value)147 public void setAttribute(String name, Object value) { 148 Assert.notNull(name, "Attribute name must not be null"); 149 if (value != null) { 150 this.attributes.put(name, value); 151 if (value instanceof HttpSessionBindingListener) { 152 ((HttpSessionBindingListener) value).valueBound(new HttpSessionBindingEvent(this, name, value)); 153 } 154 } 155 else { 156 removeAttribute(name); 157 } 158 } 159 putValue(String name, Object value)160 public void putValue(String name, Object value) { 161 setAttribute(name, value); 162 } 163 removeAttribute(String name)164 public void removeAttribute(String name) { 165 Assert.notNull(name, "Attribute name must not be null"); 166 Object value = this.attributes.remove(name); 167 if (value instanceof HttpSessionBindingListener) { 168 ((HttpSessionBindingListener) value).valueUnbound(new HttpSessionBindingEvent(this, name, value)); 169 } 170 } 171 removeValue(String name)172 public void removeValue(String name) { 173 removeAttribute(name); 174 } 175 176 /** 177 * Clear all of this session's attributes. 178 */ clearAttributes()179 public void clearAttributes() { 180 for (Iterator<Map.Entry<String, Object>> it = this.attributes.entrySet().iterator(); it.hasNext();) { 181 Map.Entry<String, Object> entry = it.next(); 182 String name = entry.getKey(); 183 Object value = entry.getValue(); 184 it.remove(); 185 if (value instanceof HttpSessionBindingListener) { 186 ((HttpSessionBindingListener) value).valueUnbound(new HttpSessionBindingEvent(this, name, value)); 187 } 188 } 189 } 190 invalidate()191 public void invalidate() { 192 this.invalid = true; 193 clearAttributes(); 194 } 195 isInvalid()196 public boolean isInvalid() { 197 return this.invalid; 198 } 199 setNew(boolean value)200 public void setNew(boolean value) { 201 this.isNew = value; 202 } 203 isNew()204 public boolean isNew() { 205 return this.isNew; 206 } 207 208 209 /** 210 * Serialize the attributes of this session into an object that can 211 * be turned into a byte array with standard Java serialization. 212 * @return a representation of this session's serialized state 213 */ serializeState()214 public Serializable serializeState() { 215 HashMap<String, Serializable> state = new HashMap<String, Serializable>(); 216 for (Iterator<Map.Entry<String, Object>> it = this.attributes.entrySet().iterator(); it.hasNext();) { 217 Map.Entry<String, Object> entry = it.next(); 218 String name = entry.getKey(); 219 Object value = entry.getValue(); 220 it.remove(); 221 if (value instanceof Serializable) { 222 state.put(name, (Serializable) value); 223 } 224 else { 225 // Not serializable... Servlet containers usually automatically 226 // unbind the attribute in this case. 227 if (value instanceof HttpSessionBindingListener) { 228 ((HttpSessionBindingListener) value).valueUnbound(new HttpSessionBindingEvent(this, name, value)); 229 } 230 } 231 } 232 return state; 233 } 234 235 /** 236 * Deserialize the attributes of this session from a state object 237 * created by {@link #serializeState()}. 238 * @param state a representation of this session's serialized state 239 */ 240 @SuppressWarnings("unchecked") deserializeState(Serializable state)241 public void deserializeState(Serializable state) { 242 Assert.isTrue(state instanceof Map, "Serialized state needs to be of type [java.util.Map]"); 243 this.attributes.putAll((Map<String, Object>) state); 244 } 245 246 } 247