/*
 * Copyright 2004-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.codehaus.groovy.grails.web.metaclass;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.*;
/**
 * A dynamic property that adds a "session" map to a controller for accessing the Http Session
 * 
 * @author Graeme Rocher
 * @since Oct 24, 2005
 */
public class GetSessionDynamicProperty extends AbstractDynamicControllerProperty {

	public static final String PROPERTY_NAME = "session";
	private HttpSessionMap sessionMap;

	public GetSessionDynamicProperty(HttpServletRequest request, HttpServletResponse response) {
		super(PROPERTY_NAME, request, response);
		this.sessionMap = new HttpSessionMap();
	}

	public Object get(Object object) {
		return this.sessionMap;
	}

	public void set(Object object, Object newValue) {
		throw new UnsupportedOperationException("Property '" + PROPERTY_NAME + "' of class '"+object.getClass()+"' is read-only!" );
	}
	
	/**
	 * Wraps the HttpSessoin in a map
	 * 
	 * @author Graeme Rocher
	 * @since Oct 24, 2005
	 */
	private class HttpSessionMap implements Map {
				
		HttpSession session = null;
		
		public int size() {
			if(session == null || session.isNew())
				return 0;			
			// count as there is no way to access size from the session directly
			int count = 0;
			for(Enumeration e = session.getAttributeNames();e.hasMoreElements();count++) {}
			return count;
		}

		public boolean isEmpty() {
			if(session == null || session.isNew())
				return true;
			else
				return false;			
		}

		public boolean containsKey(Object key) {
			if(!(key instanceof String))
				throw new IllegalArgumentException("The 'session' property key '"+key+"' must be a string value");
			
			if(session == null || session.isNew())
				return false;
			
			Object attr = session.getAttribute((String)key);
			if(attr == null)
				return false;
			else
				return true;
		}

		public boolean containsValue(Object value) {
			if(session == null || session.isNew())
				return false;
			
			for(Enumeration e = session.getAttributeNames();e.hasMoreElements();) {
				String currentKey = (String)e.nextElement();
				Object current = session.getAttribute(currentKey);
				if(current.equals(value))
					return true;
			}			
			return false;
		}

		public Object get(Object key) {
			if(!(key instanceof String))
				throw new IllegalArgumentException("The 'session' property key '"+key+"' must be a string value");
			
			if(session == null || session.isNew())
				return null;
			
			return session.getAttribute((String)key);
		}

		public Object put(Object key, Object value) {
			if(!(key instanceof String))
				throw new IllegalArgumentException("The 'session' property key '"+key+"' must be a string value");
			
			if(session == null || session.isNew())
				session = request.getSession();
			
			session.setAttribute((String)key, value);
			return value;
		}

		public Object remove(Object key) {
			if(!(key instanceof String))
				throw new IllegalArgumentException("The 'session' property key '"+key+"' must be a string value");

			if(session == null || session.isNew())
				return null;
			
			Object value = session.getAttribute((String)key);
			if(value != null)
				session.removeAttribute((String)key);
			
			return value;
		}

		public void putAll(Map sessionMap) {
			for (Iterator i = sessionMap.keySet().iterator(); i.hasNext();) {
				String currentKey = (String) i.next();
				put(currentKey,sessionMap.get(currentKey));			
			}
		}

		public void clear() {
			if(session == null || session.isNew())
				return;
			
			for(Enumeration e = session.getAttributeNames();e.hasMoreElements();) {
				String current = (String)e.nextElement();
				session.removeAttribute(current);
			}
		}

		public Set keySet() {
			if(session == null || session.isNew())
				return Collections.EMPTY_SET;
			
			Set keySet = new HashSet();
			for(Enumeration e = session.getAttributeNames();e.hasMoreElements();) {
				String current = (String)e.nextElement();
				keySet.add(current);
			}			
			return keySet;
		}

		public Collection values() {
			throw new UnsupportedOperationException("Method 'values()' is not support by session Map." );
		}

		public Set entrySet() {
			throw new UnsupportedOperationException("Method 'entrySet()' is not support by session Map." );
		}		
	}
}

@@ -1811,37 +1811,18 @@
  == null
- %7C%7C session.isNew()
 )%0A
+
 %09%09%09%09retu
@@ -2050,27 +2050,36 @@
 isEmpty() %7B%0A
-%09%09%09
+            
 if(session =
@@ -2088,77 +2088,142 @@
 null
- %7C%7C session.isNew())%0A%09%09%09%09return true;%0A%09%09%09else%0A%09%09%09%09return false;%09%09%09%0A%09%09
+)%0A               return true;%0A%0A           Enumeration e = session.getAttributeNames();%0A           return !e.hasMoreElements();%0A       
 %7D%0A%0A%09
@@ -2655,35 +2655,16 @@
  == null
- %7C%7C session.isNew()
 )%0A%09%09%09%09re
@@ -3101,35 +3101,44 @@
 ng value%22);%0A%09%09%09%0A
-%09%09%09
+%0A           
 if(session == nu
@@ -3143,33 +3143,108 @@
 null
- %7C%7C session.isNew())%0A%09%09%09%09
+)%0A               session = request.getSession(false);%0A           if(session == null)%0A               
 retu
@@ -3248,27 +3248,24 @@
 eturn null;%0A
-%09%09%09
 %0A%09%09%09return s
@@ -3511,35 +3511,16 @@
  == null
- %7C%7C session.isNew()
 )%0A%09%09%09%09se
@@ -3814,35 +3814,16 @@
  == null
- %7C%7C session.isNew()
 )%0A%09%09%09%09re
@@ -4211,24 +4211,24 @@
 d clear() %7B%0A
+
 %09%09%09if(sessio
@@ -4236,35 +4236,16 @@
  == null
- %7C%7C session.isNew()
 )%0A%09%09%09%09re

Update to grails session handling as there were some mistakes in the way the session was being retrieved/interpreted