]> err.no Git - sope/blob - sope-appserver/NGObjWeb/WOFileSessionStore.m
increased element nesting depth
[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 - (WOSession *)restoreSessionWithID:(NSString *)_sid
160   request:(WORequest *)_request
161 {
162   NSAutoreleasePool *pool;
163   NSString *snp;
164   WOSession *session = nil;
165
166   if ([_sid length] == 0)
167     return nil;
168   
169   if (![_sid isKindOfClass:[NSString class]]) {
170     [self warnWithFormat:@"%s: got invalid session id (expected string !): %@",
171             __PRETTY_FUNCTION__, _sid];
172     return nil;
173   }
174   
175   if ([_sid isEqualToString:@"expired"])
176     return nil;
177   
178   pool = [[NSAutoreleasePool alloc] init];
179   {
180     snp = [self pathForSessionID:_sid];
181     
182     if ([self->fileManager fileExistsAtPath:snp]) {
183       NSData *data;
184       
185       if ((data = [self->fileManager contentsAtPath:snp])) {
186         session = [NSUnarchiver unarchiveObjectWithData:data];
187         // NSLog(@"unarchived session: %@", session);
188         
189         if (![session isKindOfClass:[WOSession class]]) {
190           NSLog(@"object unarchived from %@ isn't a WOSession: %@ ...",
191                 snp, session);
192           session = nil;
193         }
194       }
195       else {
196         [self logWithFormat:@"could not read sn file: '%@'", snp];
197         session = nil;
198       }
199     }
200     else {
201       [self logWithFormat:@"session file does not exist: '%@'", snp];
202       session = nil;
203     }
204
205     [session retain];
206   }
207   [pool release];
208   
209   if (logExpire) {
210     if (session == nil)
211       [self logWithFormat:@"session with id %@ expired.", _sid];
212   }
213   
214   return [session autorelease];
215 }
216
217 /* termination */
218
219 - (void)sessionExpired:(NSString *)_sessionID {
220   [self->lock lock];
221   {
222     // TODO: NOT IMPLEMENTED (serialized session expiration)
223     NSLog(@"%@ expired.", _sessionID);
224     // NSMapRemove(self->idToSession, _sessionID);
225   }
226   [self->lock unlock];
227 }
228
229 - (void)sessionTerminated:(WOSession *)_session {
230   _session = RETAIN(_session);
231   [self->lock lock];
232   {
233     // TODO: NOT IMPLEMENTED (serialized session termination)
234     NSLog(@"%@ terminated.", [_session sessionID]);
235     // NSMapRemove(self->idToSession, [_session sessionID]);
236   }
237   [self->lock unlock];
238   RELEASE(_session);
239   
240   [[WOApplication application]
241                   logWithFormat:
242                     @"WOFileSessionStore: session %@ terminated.",
243                     [_session sessionID]];
244 }
245
246 /* description */
247
248 - (NSString *)description {
249   return [NSString stringWithFormat:@"<%@[0x%08X]: path=%@>",
250                      NSStringFromClass([self class]), self, self->snPath];
251 }
252
253 @end /* WOFileSessionStore */