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