]> err.no Git - sope/blob - sope-appserver/NGObjWeb/WOFileSessionStore.m
ivar extensions to NGObjWeb core classes, moved SoOFS to separate project
[sope] / sope-appserver / NGObjWeb / WOFileSessionStore.m
1 /*
2   Copyright (C) 2000-2003 SKYRIX Software AG
3
4   This file is part of OGo
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21 // $Id$
22
23 #include <NGObjWeb/WOSessionStore.h>
24
25 /*
26   This store keeps all sessions as archived files inside of a directory.
27   It provides session fail-over, but restoring/saving a session takes some
28   time ...
29
30   Storage format:
31     session-directory/
32       sessionid.session
33       sessionid.session
34
35   The session-directory can be selected using the WOFileSessionPath default.
36
37   Note: it doesn't provide session distribution between instances, since the
38   store doesn't lock the session files.
39 */
40
41 @class NSString, NSFileManager;
42
43 @interface WOFileSessionStore : WOSessionStore
44 {
45   NSFileManager *fileManager;
46   NSString      *snPath;
47 }
48 @end
49
50 #include <NGObjWeb/WOContext.h>
51 #include <NGObjWeb/WOSession.h>
52 #include <NGObjWeb/WOApplication.h>
53 #include "common.h"
54
55 @implementation WOFileSessionStore
56
57 static BOOL logExpire = YES;
58
59 + (int)version {
60   return [super version] + 0;
61 }
62 + (void)initialize {
63   NSAssert2([super version] == 2,
64             @"invalid superclass (%@) version %i !",
65             NSStringFromClass([self superclass]), [super version]);
66 }
67
68 - (id)initWithSessionPath:(NSString *)_path {
69   NSFileManager *fm;
70   BOOL isDir;
71   
72   if ([_path length] == 0) {
73     [self release];
74     return nil;
75   }
76   
77   fm = [NSFileManager defaultManager];
78   if (![fm fileExistsAtPath:_path isDirectory:&isDir]) {
79     if (![fm createDirectoryAtPath:_path attributes:nil]) {
80       NSLog(@"%s: could not create a directory at path: %@",
81             __PRETTY_FUNCTION__, _path);
82       [self release];
83       return nil;
84     }
85   }
86   else if (!isDir) {
87     NSLog(@"%s: not a directory path: %@", __PRETTY_FUNCTION__, _path);
88     [self release];
89     return nil;
90   }
91   
92   if ((self = [super init])) {
93     self->snPath = [_path copy];
94     self->fileManager = [fm retain];
95   }
96   return self;
97 }
98 - (id)init {
99   NSString *p;
100   p = [[NSUserDefaults standardUserDefaults]
101         stringForKey:@"WOFileSessionPath"];
102   return [self initWithSessionPath:p];
103 }
104
105 - (void)dealloc {
106   [self->fileManager release];
107   [self->snPath      release];
108   [super dealloc];
109 }
110
111 /* accessors */
112
113 - (int)activeSessionsCount {
114   return 0;
115   //return [[self->fileManager directoryContentsAtPath:self->snPath] count];
116 }
117
118 /* store */
119
120 - (NSString *)pathForSessionID:(NSString *)_sid {
121   return [self->snPath stringByAppendingPathComponent:_sid];
122 }
123
124 - (void)saveSessionForContext:(WOContext *)_context {
125   WOSession *sn;
126   NSString *snp;
127   
128   if (![_context hasSession])
129     return;
130   
131   sn  = [_context session];
132   snp = [self pathForSessionID:[sn sessionID]];
133   
134   if ([sn isTerminating]) {
135     sn = RETAIN(sn);
136         
137     // TODO: NOT IMPLEMENTED (serialized-session termination)
138     //NSMapRemove(self->idToSession, [sn sessionID]);
139     
140     NSLog(@"session %@ terminated at %@ ..",
141           [sn sessionID], [NSCalendarDate calendarDate]);
142     [sn release];
143   }
144   else {
145     NSData *data;
146     
147     data = [NSArchiver archivedDataWithRootObject:sn];
148     
149     if (data) {
150       if (![data writeToFile:snp atomically:YES]) {
151         [self logWithFormat:
152                 @"could not write data of session %@ to file: '%@'", sn, snp];
153       }
154     }
155     else
156       [self logWithFormat:@"could not archive session: '%@'", sn];
157   }
158 }
159
160 - (WOSession *)restoreSessionWithID:(NSString *)_sid
161   request:(WORequest *)_request
162 {
163   NSAutoreleasePool *pool;
164   NSString *snp;
165   WOSession *session = nil;
166
167   if ([_sid length] == 0)
168     return nil;
169   
170   if (![_sid isKindOfClass:[NSString class]]) {
171     NSLog(@"WARNING(%s): got invalid session id (expected string !): %@",
172           __PRETTY_FUNCTION__, _sid);
173     return nil;
174   }
175   
176   if ([_sid isEqualToString:@"expired"])
177     return nil;
178   
179   pool = [[NSAutoreleasePool alloc] init];
180   {
181     snp = [self pathForSessionID:_sid];
182     
183     if ([self->fileManager fileExistsAtPath:snp]) {
184       NSData *data;
185       
186       if ((data = [self->fileManager contentsAtPath:snp])) {
187         session = [NSUnarchiver unarchiveObjectWithData:data];
188         // NSLog(@"unarchived session: %@", session);
189         
190         if (![session isKindOfClass:[WOSession class]]) {
191           NSLog(@"object unarchived from %@ isn't a WOSession: %@ ...",
192                 snp, session);
193           session = nil;
194         }
195       }
196       else {
197         [self logWithFormat:@"could not read sn file: '%@'", snp];
198         session = nil;
199       }
200     }
201     else {
202       [self logWithFormat:@"session file does not exist: '%@'", snp];
203       session = nil;
204     }
205
206     [session retain];
207   }
208   [pool release];
209   
210   if (logExpire) {
211     if (session == nil)
212       [self logWithFormat:@"session with id %@ expired.", _sid];
213   }
214   
215   return [session autorelease];
216 }
217
218 /* termination */
219
220 - (void)sessionExpired:(NSString *)_sessionID {
221   [self->lock lock];
222   {
223     // TODO: NOT IMPLEMENTED (serialized session expiration)
224     NSLog(@"%@ expired.", _sessionID);
225     // NSMapRemove(self->idToSession, _sessionID);
226   }
227   [self->lock unlock];
228 }
229
230 - (void)sessionTerminated:(WOSession *)_session {
231   _session = RETAIN(_session);
232   [self->lock lock];
233   {
234     // TODO: NOT IMPLEMENTED (serialized session termination)
235     NSLog(@"%@ terminated.", [_session sessionID]);
236     // NSMapRemove(self->idToSession, [_session sessionID]);
237   }
238   [self->lock unlock];
239   RELEASE(_session);
240   
241   [[WOApplication application]
242                   logWithFormat:
243                     @"WOFileSessionStore: session %@ terminated.",
244                     [_session sessionID]];
245 }
246
247 /* description */
248
249 - (NSString *)description {
250   return [NSString stringWithFormat:@"<%@[0x%08X]: path=%@>",
251                      NSStringFromClass([self class]), self, self->snPath];
252 }
253
254 @end /* WOFileSessionStore */