New tests, message update
[mono.git] / mcs / class / System.Web / System.Web.SessionState_2.0 / SessionStateServerHandler.cs
1 //
2 // System.Web.Compilation.SessionStateItemCollection
3 //
4 // Authors:
5 //   Marek Habersack (grendello@gmail.com)
6 //
7 // (C) 2006 Marek Habersack
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 #if NET_2_0
31 using System.Collections.Specialized;
32 using System.IO;
33 using System.Web;
34 using System.Web.Configuration;
35 using System.Runtime.Remoting;
36
37 namespace System.Web.SessionState 
38 {
39         internal class SessionStateServerHandler : SessionStateStoreProviderBase
40         {
41                 private const Int32 lockAcquireTimeout = 30000;
42                 
43                 SessionStateSection config;
44                 RemoteStateServer stateServer;
45
46                 public override SessionStateStoreData CreateNewStoreData (HttpContext context, int timeout)
47                 {
48                         return new SessionStateStoreData (new SessionStateItemCollection (),
49                                                           HttpApplicationFactory.ApplicationState.SessionObjects,
50                                                           timeout);
51                 }
52                 
53                 public override void CreateUninitializedItem (HttpContext context, string id, int timeout)
54                 {
55                         EnsureGoodId (id, true);
56                         stateServer.CreateUninitializedItem (id, timeout);
57                 }
58                 
59                 public override void Dispose ()
60                 {
61                 }
62                 
63                 public override void EndRequest (HttpContext context)
64                 {
65                 }
66
67                 SessionStateStoreData GetItemInternal (HttpContext context,
68                                                        string id,
69                                                        out bool locked,
70                                                        out TimeSpan lockAge,
71                                                        out object lockId,
72                                                        out SessionStateActions actions,
73                                                        bool exclusive)
74                 {
75 #if TRACE
76                         Console.WriteLine ("SessionStateServerHandler.GetItemInternal");
77                         Console.WriteLine ("\tid == {0}", id);
78                         Console.WriteLine ("\tpath == {0}", context.Request.FilePath);
79 #endif
80                         locked = false;
81                         lockAge = TimeSpan.MinValue;
82                         lockId = Int32.MinValue;
83                         actions = SessionStateActions.None;
84
85                         if (id == null)
86                                 return null;
87                         
88                         StateServerItem item = stateServer.GetItem (id,
89                                                                     out locked,
90                                                                     out lockAge,
91                                                                     out lockId,
92                                                                     out actions,
93                                                                     exclusive);
94                         
95                         if (item == null) {
96 #if TRACE
97                                 Console.WriteLine ("\titem is null (locked == {0}, actions == {1})", locked, actions);
98 #endif
99                                 return null;
100                         }
101                         if (actions == SessionStateActions.InitializeItem) {
102 #if TRACE
103                                 Console.WriteLine ("\titem needs initialization");
104 #endif
105                                 return CreateNewStoreData (context, item.Timeout);
106                         }
107                         SessionStateItemCollection items = null;
108                         HttpStaticObjectsCollection sobjs = null;
109                         MemoryStream stream = null;
110                         BinaryReader reader = null;
111                         try {
112                                 if (item.CollectionData != null && item.CollectionData.Length > 0) {
113                                         stream = new MemoryStream (item.CollectionData);
114                                         reader = new BinaryReader (stream);
115                                         items = SessionStateItemCollection.Deserialize (reader);
116                                 } else
117                                         items = new SessionStateItemCollection ();
118                                 if (item.StaticObjectsData != null && item.StaticObjectsData.Length > 0)
119                                         sobjs = HttpStaticObjectsCollection.FromByteArray (item.StaticObjectsData);
120                                 else
121                                         sobjs = new HttpStaticObjectsCollection ();
122                         } catch (Exception ex) {
123                                 throw new HttpException ("Failed to retrieve session state.", ex);
124                         } finally {
125                                 if (reader != null)
126                                         reader.Close ();
127                         }
128                                 
129                         return new SessionStateStoreData (items,
130                                                           sobjs,
131                                                           item.Timeout);
132                 }
133                 
134                 public override SessionStateStoreData GetItem (HttpContext context,
135                                                                string id,
136                                                                out bool locked,
137                                                                out TimeSpan lockAge,
138                                                                out object lockId,
139                                                                out SessionStateActions actions)
140                 {
141                         EnsureGoodId (id, false);
142                         return GetItemInternal (context, id, out locked, out lockAge, out lockId, out actions, false);
143                 }
144                 
145                 public override SessionStateStoreData GetItemExclusive (HttpContext context,
146                                                                         string id,
147                                                                         out bool locked,
148                                                                         out TimeSpan lockAge,
149                                                                         out object lockId,
150                                                                         out SessionStateActions actions)
151                 {
152                         EnsureGoodId (id, false);
153                         return GetItemInternal (context, id, out locked, out lockAge, out lockId, out actions, true);
154                 }
155
156                 public override void Initialize (string name, NameValueCollection config)
157                 {
158 #if TRACE
159                         Console.WriteLine ("SessionStateServerHandler.Initialize");
160 #endif
161                         this.config = (SessionStateSection) WebConfigurationManager.GetSection ("system.web/sessionState");
162                         if (String.IsNullOrEmpty (name))
163                                 name = "Session Server handler";
164                         RemotingConfiguration.Configure (null);
165                         string cons = null, proto = null, server = null, port = null;
166                         GetConData (out proto, out server, out port);
167                         cons = String.Format ("{0}://{1}:{2}/StateServer", proto, server, port);
168                         stateServer = Activator.GetObject (typeof (RemoteStateServer), cons) as RemoteStateServer;
169
170                         base.Initialize (name, config);
171                 }
172                 
173                 public override void InitializeRequest (HttpContext context)
174                 {
175                         // nothing to do here
176                 }
177                 
178                 public override void ReleaseItemExclusive (HttpContext context,
179                                                            string id,
180                                                            object lockId)
181                 {
182                         EnsureGoodId (id, true);
183                         stateServer.ReleaseItemExclusive (id, lockId);
184                 }
185                 
186                 public override void RemoveItem (HttpContext context,
187                                                  string id,
188                                                  object lockId,
189                                                  SessionStateStoreData item)
190                 {
191                         EnsureGoodId (id, true);
192                         stateServer.Remove (id, lockId);
193                 }
194                 
195                 public override void ResetItemTimeout (HttpContext context, string id)
196                 {
197                         EnsureGoodId (id, true);
198                         stateServer.ResetItemTimeout (id);
199                 }
200                 
201                 public override void SetAndReleaseItemExclusive (HttpContext context,
202                                                                  string id,
203                                                                  SessionStateStoreData item,
204                                                                  object lockId,
205                                                                  bool newItem)
206                 {
207                         EnsureGoodId (id, true);
208                         byte[] collection_data = null;
209                         byte[] sobjs_data = null;
210                         MemoryStream stream = null;
211                         BinaryWriter writer = null;
212                         
213                         try {
214                                 SessionStateItemCollection items = item.Items as SessionStateItemCollection;
215                                 if (items != null && items.Count > 0) {
216                                         stream = new MemoryStream ();
217                                         writer = new BinaryWriter (stream);
218                                         items.Serialize (writer);
219                                         collection_data = stream.GetBuffer ();
220                                 }
221                                 HttpStaticObjectsCollection sobjs = item.StaticObjects;
222                                 if (sobjs != null && sobjs.Count > 0)
223                                         sobjs_data = sobjs.ToByteArray ();
224                         } catch (Exception ex) {
225                                 throw new HttpException ("Failed to store session data.", ex);
226                         } finally {
227                                 if (writer != null)
228                                         writer.Close ();
229                         }
230                         
231                         stateServer.SetAndReleaseItemExclusive (id, collection_data, sobjs_data, lockId, item.Timeout, newItem);
232                 }
233                 
234                 public override bool SetItemExpireCallback (SessionStateItemExpireCallback expireCallback)
235                 {
236                         return false;
237                 }
238
239                 void EnsureGoodId (string id, bool throwOnNull)
240                 {
241                         if (id == null)
242                                 if (throwOnNull)
243                                         throw new HttpException ("Session ID is invalid");
244                                 else
245                                         return;
246                         
247                         if (id.Length > SessionIDManager.SessionIDMaxLength)
248                                 throw new HttpException ("Session ID too long");
249                 }
250
251                 void GetConData (out string proto, out string server, out string port)
252                 {
253                         string cons = config.StateConnectionString;
254                         int ei = cons.IndexOf ('=');
255                         int ci = cons.IndexOf (':');
256
257                         if (ei < 0 || ci < 0)
258                                 throw new HttpException ("Invalid StateConnectionString");
259                         
260                         proto = cons.Substring (0, ei);
261                         server = cons.Substring (ei+1, ci - ei - 1);
262                         port = cons.Substring (ci+1, cons.Length - ci - 1);
263                         
264                         if (proto == "tcpip")
265                                 proto = "tcp";
266                 }
267         }
268 }
269 #endif