Преглед изворни кода

2004-05-05 Gonzalo Paniagua Javier <[email protected]>

	* HttpSessionState.cs: added Clone (), which makes and exact copy but
	with a cloned SessionDictionary. When EnableSessionState is set to
	ReadOnly, we can modify the collection, but changes are not propagated.

	* ISessionHandler.cs: changed signature of UpdateContext().

	* SessionDictionary.cs: added Clone.

	* SessionInProcHandler.cs:
	* SessionSQLServerHandler.cs:
	* SessionStateServerHandler.cs: don't create a new session if the handler
	do not require it. UpdateContext() now returns an HttpSessionState to
	the module.

	* SessionStateModule.cs: removed IsReadOnly as it is now passed as a
	parameter to the session handler. If the session is read-only, clone
	it so that it can be changed but changes are not kept.

	In short, we don't create session objects when not required and we
	honor the ReadOnly sessions.

svn path=/trunk/mcs/; revision=26781
Gonzalo Paniagua Javier пре 21 година
родитељ
комит
36879b3188

+ 23 - 0
mcs/class/System.Web/System.Web.SessionState/ChangeLog

@@ -1,3 +1,26 @@
+2004-05-05  Gonzalo Paniagua Javier <[email protected]>
+
+	* HttpSessionState.cs: added Clone (), which makes and exact copy but
+	with a cloned SessionDictionary. When EnableSessionState is set to
+	ReadOnly, we can modify the collection, but changes are not propagated.
+
+	* ISessionHandler.cs: changed signature of UpdateContext().
+
+	* SessionDictionary.cs: added Clone.
+
+	* SessionInProcHandler.cs:
+	* SessionSQLServerHandler.cs:
+	* SessionStateServerHandler.cs: don't create a new session if the handler
+	do not require it. UpdateContext() now returns an HttpSessionState to
+	the module.
+
+	* SessionStateModule.cs: removed IsReadOnly as it is now passed as a 
+	parameter to the session handler. If the session is read-only, clone
+	it so that it can be changed but changes are not kept.
+
+	In short, we don't create session objects when not required and we
+	honor the ReadOnly sessions.
+
 2004-02-09  Gonzalo Paniagua Javier <[email protected]>
 
 	* SessionInProcHandler.cs:

+ 7 - 0
mcs/class/System.Web/System.Web.SessionState/HttpSessionState.cs

@@ -46,6 +46,13 @@ public sealed class HttpSessionState : ICollection, IEnumerable
 		_isReadonly = isReadonly;
 	}
 
+	internal HttpSessionState Clone ()
+	{
+		return new HttpSessionState (_id, _dict.Clone (), _staticObjects, _timeout, _newSession,
+					     _isCookieless, _mode, _isReadonly);
+
+	}
+
 	public int CodePage {
 		get {
 			HttpContext current = HttpContext.Current;

+ 6 - 4
mcs/class/System.Web/System.Web.SessionState/ISessionHandler.cs

@@ -12,10 +12,12 @@ namespace System.Web.SessionState
 {
 	internal interface ISessionHandler
 	{
-	      void Dispose ();
-	      void Init (HttpApplication context, SessionConfig config);
-	      bool UpdateContext (HttpContext context, SessionStateModule module);
-	      void UpdateHandler (HttpContext context, SessionStateModule module);
+		void Dispose ();
+		void Init (HttpApplication context, SessionConfig config);
+		HttpSessionState UpdateContext (HttpContext context, SessionStateModule module, bool required,
+						bool read_only, ref bool isNew);
+
+		void UpdateHandler (HttpContext context, SessionStateModule module);
 	}
 }
 

+ 12 - 0
mcs/class/System.Web/System.Web.SessionState/SessionDictionary.cs

@@ -21,6 +21,18 @@ internal class SessionDictionary : NameObjectCollectionBase
 	{
 	}
 
+	internal SessionDictionary Clone ()
+	{
+		SessionDictionary sess = new SessionDictionary ();
+		int last = sess.Count;
+		for (int i = 0; i < last; i++) {
+			string key = GetKey (i);
+			sess [key] = this [key];
+		}
+
+		return sess;
+	}
+	
 	internal void Clear ()
 	{
 		_dirty = true;

+ 26 - 24
mcs/class/System.Web/System.Web.SessionState/SessionInProcHandler.cs

@@ -79,7 +79,8 @@ namespace System.Web.SessionState
 		}
 
 		//this is the code that actually do stuff.
-		public bool UpdateContext (HttpContext context, SessionStateModule module)
+		public HttpSessionState UpdateContext (HttpContext context, SessionStateModule module,
+							bool required, bool read_only, ref bool isNew)
 		{
 			SessionContainer container = null;
 			string id = SessionId.Lookup (context.Request, config.CookieLess);
@@ -90,39 +91,40 @@ namespace System.Web.SessionState
 				container = (SessionContainer) _sessionTable [id];
 
 				// if we have a session, and it is not expired, set isNew to false and return it.
-				if (container!=null && container.SessionState!=null && !container.SessionState.IsAbandoned) {
-					// Can we do this? It feels safe, but what do I know.
-					container.SessionState.SetNewSession (false);
+				if (container != null && container.SessionState != null && 
+				    !container.SessionState.IsAbandoned) {
+					if (required)
+						container.SessionState.SetNewSession (false);
 					// update the timestamp.
 					container.Touch ();
-					 // Can we do this? It feels safe, but what do I know.
-					context.SetSession (container.SessionState);
-					return false; // and we're done
-				} else if(container!=null) {
+					if (required)
+						return container.SessionState;
+
+					return null;
+				} else if (container!=null) {
 					_sessionTable.Remove (id);
 				}
 			}
 
+			if (!required)
+				return null;
+
 			// else we create a new session.
 			string sessionID = SessionId.Create (module.Rng);
-			container = new SessionContainer (new HttpSessionState (sessionID, // unique identifier
-										new SessionDictionary(), // dictionary
-										HttpApplicationFactory.ApplicationState.SessionObjects,
-										SESSION_LIFETIME, //lifetime befor death.
-										true, //new session
-										false, // is cookieless
-										SessionStateMode.InProc,
-										module.IsReadOnly)); //readonly
-			// puts it in the table.
+			HttpSessionState state = new HttpSessionState (sessionID, // unique identifier
+							new SessionDictionary(), // dictionary
+							HttpApplicationFactory.ApplicationState.SessionObjects,
+							SESSION_LIFETIME, //lifetime before death.
+							true, //new session
+							false, // is cookieless
+							SessionStateMode.InProc,
+							read_only); //readonly
+
+			container = new SessionContainer (state);
 			_sessionTable [sessionID]=container;
 			AppDomain.CurrentDomain.SetData (".MonoSessionInProc", _sessionTable);
-
-			// and returns it.
-			context.SetSession (container.SessionState);
-			context.Session.SetNewSession (true);
-
-			// And we're done!
-			return true;
+			isNew = true;
+			return container.SessionState;
 		}
 	}
 }

+ 13 - 12
mcs/class/System.Web/System.Web.SessionState/SessionSQLServerHandler.cs

@@ -62,7 +62,7 @@ namespace System.Web.SessionState {
 
 		public void UpdateHandler (HttpContext context, SessionStateModule module)
 		{
-			if (context.Session == null)
+			if (context.Session == null || context.Session.IsReadOnly)
 				return;
 
 			string id = context.Session.SessionID;
@@ -71,28 +71,29 @@ namespace System.Web.SessionState {
 			UpdateSession (id, dict);
 		}
 
-		public bool UpdateContext (HttpContext context, SessionStateModule module)
+		public HttpSessionState UpdateContext (HttpContext context, SessionStateModule module,
+							bool required, bool read_only, ref bool isNew)
 		{
+			if (!required)
+				return null;
+
 			HttpSessionState session = null;
 			string id = SessionId.Lookup (context.Request, config.CookieLess);
 
 			if (id != null) {
-				session = SelectSession (id, module.IsReadOnly);
-				if (session != null) {
-					context.SetSession (session);
-					return false;
-				}
+				session = SelectSession (id, read_only);
+				if (session != null)
+					return session;
 			}
 
 			id = SessionId.Create (module.Rng);
 			session = new HttpSessionState (id, new SessionDictionary (),
-					HttpApplicationFactory.ApplicationState.SessionObjects, config.Timeout, true,
-					config.CookieLess, SessionStateMode.SQLServer, module.IsReadOnly);
+					HttpApplicationFactory.ApplicationState.SessionObjects, config.Timeout,
+					true, config.CookieLess, SessionStateMode.SQLServer, read_only);
 
 			InsertSession (session, config.Timeout);
-			context.SetSession (session);
-
-			return true;
+			isNew = true;
+			return session;
 		}
 
 		private void GetConnectionData (out string providerAssembly,

+ 25 - 21
mcs/class/System.Web/System.Web.SessionState/SessionStateModule.cs

@@ -15,7 +15,6 @@ using System.Security.Cryptography;
 
 namespace System.Web.SessionState
 {
-	[MonoTODO]
 	public sealed class SessionStateModule : IHttpModule
 	{
 		internal static readonly string CookieName = "ASPSESSION";
@@ -24,7 +23,6 @@ namespace System.Web.SessionState
 		static SessionConfig config;
 		static Type handlerType;
 		ISessionHandler handler;
-		bool read_only;
 		
 		private RandomNumberGenerator rng;
 		
@@ -37,18 +35,12 @@ namespace System.Web.SessionState
 			get { return rng; }
 		}
 
-		internal bool IsReadOnly
-		{
-			get { return read_only; }
-		}
-		
 		public void Dispose ()
 		{
 		    if (handler!=null)
 			handler.Dispose();
 		}
 
-		[MonoTODO]
 		public void Init (HttpApplication app)
 		{
 			if (config == null) {
@@ -119,22 +111,34 @@ namespace System.Web.SessionState
 			HttpApplication application = (HttpApplication) o;
 			HttpContext context = application.Context;
 
-			read_only = (context.Handler is IReadOnlySessionState);
+			bool required = (context.Handler is IRequiresSessionState);
+			bool read_only = (context.Handler is IReadOnlySessionState);
 			
 			bool isNew = false;
+			HttpSessionState session = null;
 			if (handler != null)
-			    isNew = handler.UpdateContext (context, this);
-
-			if (isNew && config.CookieLess) {
-				string id = context.Session.SessionID;
-				context.Request.SetHeader (HeaderName, id);
-				context.Response.Redirect (UrlUtils.InsertSessionId (id,
-						context.Request.FilePath));
-			} else if (isNew) {
-				string id = context.Session.SessionID;
-				HttpCookie cookie = new HttpCookie (CookieName, id);
-				cookie.Path = UrlUtils.GetDirectory (context.Request.Path);
-				context.Response.AppendCookie (cookie);
+				session = handler.UpdateContext (context, this, required, read_only, ref isNew);
+
+			if (session != null) {
+				if (isNew)
+					session.SetNewSession (true);
+
+				if (read_only)
+					session = session.Clone ();
+					
+				context.SetSession (session);
+
+				if (isNew && config.CookieLess) {
+					string id = context.Session.SessionID;
+					context.Request.SetHeader (HeaderName, id);
+					context.Response.Redirect (UrlUtils.InsertSessionId (id,
+								   context.Request.FilePath));
+				} else if (isNew) {
+					string id = context.Session.SessionID;
+					HttpCookie cookie = new HttpCookie (CookieName, id);
+					cookie.Path = UrlUtils.GetDirectory (context.Request.Path);
+					context.Response.AppendCookie (cookie);
+				}
 			}
 			
 			// In the future, we might want to move the Async stuff down to

+ 16 - 11
mcs/class/System.Web/System.Web.SessionState/SessionStateServerHandler.cs

@@ -40,7 +40,7 @@ namespace System.Web.SessionState {
 
 		public void UpdateHandler (HttpContext context, SessionStateModule module)
 		{
-			if (context.Session == null)
+			if (context.Session == null || context.Session.IsReadOnly)
 				return;
 			
 			string id = context.Session.SessionID;
@@ -49,8 +49,12 @@ namespace System.Web.SessionState {
 			state_server.Update (id, dict.ToByteArray (), sobjs.ToByteArray ());
 		}
 
-		public bool UpdateContext (HttpContext context, SessionStateModule module)
+		public HttpSessionState UpdateContext (HttpContext context, SessionStateModule module,
+							bool required, bool read_only, ref bool isNew)
 		{
+			if (!required)
+				return null;
+
 			StateServerItem item = null;
 			HttpSessionState session = null;
 			SessionDictionary dict = null;
@@ -62,11 +66,12 @@ namespace System.Web.SessionState {
 				if (item != null) {
 					dict = SessionDictionary.FromByteArray (item.DictionaryData);
 					sobjs = HttpStaticObjectsCollection.FromByteArray (item.StaticObjectsData);
-					session = new HttpSessionState (id, dict, HttpApplicationFactory.ApplicationState.SessionObjects,
+					session = new HttpSessionState (id, dict,
+							HttpApplicationFactory.ApplicationState.SessionObjects,
 							config.Timeout, false, config.CookieLess,
-							SessionStateMode.StateServer, module.IsReadOnly);
-					context.SetSession (session);
-					return false;
+							SessionStateMode.StateServer, read_only);
+
+					return session;
 				}
 			}
 			
@@ -77,12 +82,12 @@ namespace System.Web.SessionState {
 			
 			state_server.Insert (id, item);
 
-			session = new HttpSessionState (id, dict, sobjs, config.Timeout,
-					true, config.CookieLess, SessionStateMode.StateServer, module.IsReadOnly);
-			
-			context.SetSession (session);
+			session = new HttpSessionState (id, dict, sobjs, config.Timeout, true,
+							config.CookieLess, SessionStateMode.StateServer,
+							read_only);
 			
-			return true;
+			isNew = true;
+			return session;
 		}
 
 		private string GetId (HttpContext context)