See ChangeLog

Monotone-Parent: f5359c59c0bb008203154487db17e1ecdd274c0d
Monotone-Revision: 7c78ba28d583536196a1acf34df5c96f40db238e

Monotone-Author: ludovic@Sophos.ca
Monotone-Date: 2010-12-28T17:42:50
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
Ludovic Marcotte
2010-12-28 17:42:50 +00:00
parent 7ffe6ee26a
commit f46ebda105
22 changed files with 738 additions and 53 deletions
+4 -1
View File
@@ -32,7 +32,7 @@
*/
@class NSString, NSArray, NSURL, NSDictionary, NSException;
@class GCSChannelManager, GCSAlarmsFolder, GCSFolder, GCSFolderType;
@class GCSChannelManager, GCSAlarmsFolder, GCSFolder, GCSFolderType, GCSSessionsFolder;
@interface GCSFolderManager : NSObject
{
@@ -73,6 +73,9 @@
/* alarms */
- (GCSAlarmsFolder *)alarmsFolder;
/* sessions */
- (GCSSessionsFolder *)sessionsFolder;
/* folder types */
- (GCSFolderType *)folderTypeWithName:(NSString *)_name;
+11 -4
View File
@@ -1,14 +1,15 @@
/*
Copyright (C) 2006-2011 Inverse inc.
Copyright (C) 2004-2007 SKYRIX Software AG
This file is part of OpenGroupware.org.
This file is part of SOGo.
OGo is free software; you can redistribute it and/or modify it under
SOGo is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
OGo is distributed in the hope that it will be useful, but WITHOUT ANY
SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
@@ -42,6 +43,7 @@
#import "GCSAlarmsFolder.h"
#import "GCSFolder.h"
#import "GCSFolderType.h"
#import "GCSSessionsFolder.h"
#import "GCSSpecialQueries.h"
#import "NSURL+GCS.h"
@@ -330,7 +332,12 @@ static NSCharacterSet *asciiAlphaNumericCS = nil;
return [GCSAlarmsFolder alarmsFolderWithFolderManager: self];
}
/* path SQL */
/* sessions */
- (GCSSessionsFolder *)sessionsFolder
{
return [GCSSessionsFolder sessionsFolderWithFolderManager: self];
}
- (NSString *)generateSQLWhereForInternalNames:(NSArray *)_names
exactMatch:(BOOL)_beExact orDirectSubfolderMatch:(BOOL)_directSubs
+56
View File
@@ -0,0 +1,56 @@
/* GCSSessionsFolder.h - this file is part of SOGo
*
* Copyright (C) 2010-2011 Inverse inc.
*
* Author: Ludovic Marcotte <lmarcotte@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef GCSSESSIONSFOLDER_H
#define GCSSESSIONSFOLDER_H
#import <Foundation/NSObject.h>
@class NSCalendarDate;
@class NSException;
@class NSNumber;
@class NSString;
@class GCSFolderManager;
@interface GCSSessionsFolder : NSObject
{
GCSFolderManager *folderManager;
}
+ (id) sessionsFolderWithFolderManager: (GCSFolderManager *) newFolderManager;
- (void) setFolderManager: (GCSFolderManager *) newFolderManager;
/* operations */
- (void) createFolderIfNotExists;
- (BOOL) canConnectStore;
- (NSDictionary *) recordForEntryWithID: (NSString *) theID;
- (void) deleteRecordForEntryWithID: (NSString *) theID;
- (void) writeRecordForEntryWithID: (NSString *) theID
value: (NSString *) theValue
creationDate: (NSCalendarDate *) theCreationDate
lastSeenDate: (NSCalendarDate *) theLastSeenDate;
@end
#endif /* GCSSESSIONSFOLDER_H */
+357
View File
@@ -0,0 +1,357 @@
/* GCSSessionsFolder.m - this file is part of SOGo
*
* Copyright (C) 2010-2011 Inverse inc.
*
* Author: Ludovic Marcotte <lmarcotte@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSURL.h>
#import <Foundation/NSUserDefaults.h>
#import <Foundation/NSValue.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSNull+misc.h>
#import <GDLAccess/EOAdaptorChannel.h>
#import <GDLAccess/EOAdaptorContext.h>
#import <GDLAccess/EOAttribute.h>
#import <GDLAccess/EOEntity.h>
#import <GDLAccess/EOSQLQualifier.h>
#import "EOQualifier+GCS.h"
#import "GCSChannelManager.h"
#import "GCSFolderManager.h"
#import "GCSSpecialQueries.h"
#import "GCSStringFormatter.h"
#import "NSURL+GCS.h"
#import "GCSSessionsFolder.h"
static NSString *sessionsFolderURLString = nil;
#warning GCSSessionsFolder should share a common ancestor with GCSFolder
@implementation GCSSessionsFolder
+ (void) initialize
{
NSUserDefaults *ud;
if (!sessionsFolderURLString)
{
ud = [NSUserDefaults standardUserDefaults];
ASSIGN(sessionsFolderURLString, [ud stringForKey: @"OCSSessionsFolderURL"]);
}
}
+ (id) sessionsFolderWithFolderManager: (GCSFolderManager *) newFolderManager
{
GCSAlarmsFolder *newFolder;
if (sessionsFolderURLString)
{
newFolder = [self new];
[newFolder autorelease];
[newFolder setFolderManager: newFolderManager];
}
else
{
[self errorWithFormat: @"'OCSSessionsFolderURL' is not set"];
newFolder = nil;
}
return newFolder;
}
- (void) setFolderManager: (GCSFolderManager *) newFolderManager
{
ASSIGN (folderManager, newFolderManager);
}
/* accessors */
- (NSURL *) _location
{
NSURL *location;
if (sessionsFolderURLString)
location = [NSURL URLWithString: sessionsFolderURLString];
else
{
[self warnWithFormat: @"'OCSSessionsFolderURL' is not set"];
location = nil;
}
return location;
}
- (GCSChannelManager *) _channelManager
{
return [folderManager channelManager];
}
- (NSString *) _storeTableName
{
return [[self _location] gcsTableName];
}
- (EOEntity *) _storeTableEntityForChannel: (EOAdaptorChannel *) tc
{
static EOEntity *entity = nil;
EOAttribute *attribute;
NSString *tableName;
NSString *columns[] = { @"c_id", @"c_value", @"c_creationdate",
@"c_lastseen", nil };
NSString **column;
NSMutableArray *keys;
NSDictionary *types;
if (!entity)
{
entity = [EOEntity new];
tableName = [self _storeTableName];
[entity setName: tableName];
[entity setExternalName: tableName];
types = [[tc specialQueries] sessionsAttributeTypes];
column = columns;
while (*column)
{
attribute = [EOAttribute new];
[attribute setName: *column];
[attribute setColumnName: *column];
[attribute setExternalType: [types objectForKey: *column]];
[entity addAttribute: attribute];
[attribute release];
column++;
}
keys = [NSMutableArray arrayWithCapacity: 1];
[keys addObject: [entity attributeNamed: @"c_id"]];
[entity setPrimaryKeyAttributes: keys];
keys = [NSMutableArray arrayWithCapacity: 3];
[keys addObject: [entity attributeNamed: @"c_value"]];
[keys addObject: [entity attributeNamed: @"c_creationdate"]];
[keys addObject: [entity attributeNamed: @"c_lastseen"]];
[entity setClassProperties: keys];
[entity setAttributesUsedForLocking: [NSArray array]];
}
return entity;
}
/* connection */
- (EOAdaptorChannel *) _acquireStoreChannel
{
return [[self _channelManager] acquireOpenChannelForURL: [self _location]];
}
- (void) _releaseChannel: (EOAdaptorChannel *) _channel
{
[[self _channelManager] releaseChannel:_channel];
}
- (BOOL) canConnectStore
{
return [[self _channelManager] canConnect:[self _location]];
}
- (void) createFolderIfNotExists
{
EOAdaptorChannel *tc;
NSString *sql, *tableName;
GCSSpecialQueries *queries;
tc = [self _acquireStoreChannel];
tableName = [self _storeTableName];
queries = [tc specialQueries];
sql = [NSString stringWithFormat: @"SELECT count(*) FROM %@",
[self _storeTableName]];
if ([tc evaluateExpressionX: sql])
{
sql = [queries createSessionsFolderWithName: tableName];
if (![tc evaluateExpressionX: sql])
[self logWithFormat:
@"sessions folder table '%@' successfully created!",
tableName];
}
else
[tc cancelFetch];
[self _releaseChannel: tc];
}
/* operations */
- (NSDictionary *) recordForEntryWithID: (NSString *) theID
{
EOAdaptorChannel *tc;
EOAdaptorContext *context;
NSString *tableName;
NSException *error;
NSArray *attrs;
NSDictionary *record;
EOEntity *entity;
EOSQLQualifier *qualifier;
tableName = [self _storeTableName];
record = nil;
tc = [self _acquireStoreChannel];
if (tc)
{
context = [tc adaptorContext];
entity = [self _storeTableEntityForChannel: tc];
qualifier = [[EOSQLQualifier alloc] initWithEntity: entity
qualifierFormat:
@"c_id='%@'",
theID];
[qualifier autorelease];
[context beginTransaction];
error = [tc selectAttributesX: [entity attributesUsedForFetch]
describedByQualifier: qualifier
fetchOrder: nil
lock: NO];
if (error)
[self errorWithFormat:@"%s: cannot execute fetch: %@",
__PRETTY_FUNCTION__, error];
else
{
attrs = [tc describeResults: NO];
record = [tc fetchAttributes: attrs withZone: NULL];
[tc cancelFetch];
}
[context rollbackTransaction];
[self _releaseChannel: tc];
}
return record;
}
- (NSDictionary *) _newRecordWithID: (NSString *) theID
value: (NSString *) theValue
creationDate: (NSCalendarDate *) theCreationDate
lastSeenDate: (NSCalendarDate *) theLastSeenDate
{
NSNumber *cd, *ls;
// We check if recId and alarmDate are nil prior calling -timeIntervalSince1970
// Weird gcc optimizations can cause issue here.
cd = [NSNumber numberWithInt: (theCreationDate ? (int)[theCreationDate timeIntervalSince1970] : 0)];
ls = [NSNumber numberWithInt: (theLastSeenDate ? (int)[theLastSeenDate timeIntervalSince1970] : 0)];
return [NSDictionary dictionaryWithObjectsAndKeys: theID, @"c_id",
theValue, @"c_value",
cd, @"c_creationdate",
ls, @"c_lastseen",
nil];
}
- (void) writeRecordForEntryWithID: (NSString *) theID
value: (NSString *) theValue
creationDate: (NSCalendarDate *) theCreationDate
lastSeenDate: (NSCalendarDate *) theLastSeenDate
{
NSDictionary *record, *newRecord;
NSException *error;
EOAdaptorChannel *tc;
EOAdaptorContext *context;
EOEntity *entity;
EOSQLQualifier *qualifier;
tc = [self _acquireStoreChannel];
if (tc)
{
context = [tc adaptorContext];
newRecord = [self _newRecordWithID: theID
value: theValue
creationDate: theCreationDate
lastSeenDate: theLastSeenDate];
record = [self recordForEntryWithID: theID];
entity = [self _storeTableEntityForChannel: tc];
[context beginTransaction];
if (record)
{
qualifier = [[EOSQLQualifier alloc] initWithEntity: entity
qualifierFormat:
@"c_id='%@'",
theID];
[qualifier autorelease];
error = [tc updateRowX: newRecord describedByQualifier: qualifier];
}
else
error = [tc insertRowX: newRecord forEntity: entity];
if (error)
{
[context rollbackTransaction];
[self errorWithFormat:@"%s: cannot write record: %@",
__PRETTY_FUNCTION__, error];
}
else
[context commitTransaction];
[self _releaseChannel: tc];
}
}
- (void) deleteRecordForEntryWithID: (NSString *) theID
{
EOAdaptorChannel *tc;
EOAdaptorContext *context;
EOEntity *entity;
EOSQLQualifier *qualifier;
NSException *error;
tc = [self _acquireStoreChannel];
if (tc)
{
context = [tc adaptorContext];
entity = [self _storeTableEntityForChannel: tc];
qualifier = [[EOSQLQualifier alloc] initWithEntity: entity
qualifierFormat:
@"c_id='%@'",
theID];
[qualifier autorelease];
[context beginTransaction];
error = [tc deleteRowsDescribedByQualifierX: qualifier];
if (error)
{
[context rollbackTransaction];
[self errorWithFormat:@"%s: cannot delete record: %@",
__PRETTY_FUNCTION__, error];
}
else
[context commitTransaction];
[self _releaseChannel: tc];
}
}
@end
+3
View File
@@ -37,6 +37,9 @@
- (NSString *) createFolderTableWithName: (NSString *) tableName;
- (NSString *) createFolderACLTableWithName: (NSString *) tableName;
- (NSString *) createSessionsFolderWithName: (NSString *) tableName;
- (NSDictionary *) sessionsAttributeTypes;
@end
@interface EOAdaptorChannel (GCSSpecialQueries)
+108
View File
@@ -105,8 +105,26 @@
return nil;
}
- (NSString *) createSessionsFolderWithName: (NSString *) tableName
{
[self subclassResponsibility: _cmd];
return nil;
}
- (NSDictionary *) sessionsAttributeTypes
{
[self subclassResponsibility: _cmd];
return nil;
}
@end
//
// PostgreSQL database
//
@implementation GCSPostgreSQLSpecialQueries
- (NSString *) createEMailAlarmsFolderWithName: (NSString *) tableName
@@ -168,8 +186,39 @@
return [NSString stringWithFormat: sqlFolderACLFormat, tableName];
}
- (NSString *) createSessionsFolderWithName: (NSString *) tableName
{
static NSString *sqlFolderFormat
= (@"CREATE TABLE %@ ("
@" c_id VARCHAR(255) NOT NULL,"
@" c_value VARCHAR(255) NOT NULL,"
@" c_creationdate INT4 NOT NULL,"
@" c_lastseen INT4 NOT NULL)");
return [NSString stringWithFormat: sqlFolderFormat, tableName];
}
- (NSDictionary *) sessionsAttributeTypes
{
static NSMutableDictionary *types = nil;
if (!types)
{
types = [NSMutableDictionary new];
[types setObject: @"varchar" forKey: @"c_id"];
[types setObject: @"varchar" forKey: @"c_value"];
[types setObject: @"int" forKey: @"c_creationdate"];
[types setObject: @"int" forKey: @"c_lastseen"];
}
return types;
}
@end
//
// MySQL database
//
@implementation GCSMySQLSpecialQueries
- (NSString *) createEMailAlarmsFolderWithName: (NSString *) tableName
@@ -231,8 +280,39 @@
return [NSString stringWithFormat: sqlFolderACLFormat, tableName];
}
- (NSString *) createSessionsFolderWithName: (NSString *) tableName
{
static NSString *sqlFolderFormat
= (@"CREATE TABLE %@ ("
@" c_id VARCHAR(255) NOT NULL,"
@" c_value VARCHAR(255) NOT NULL,"
@" c_creationdate INT NOT NULL,"
@" c_lastseen INT NOT NULL)");
return [NSString stringWithFormat: sqlFolderFormat, tableName];
}
- (NSDictionary *) sessionsAttributeTypes
{
static NSMutableDictionary *types = nil;
if (!types)
{
types = [NSMutableDictionary new];
[types setObject: @"varchar" forKey: @"c_id"];
[types setObject: @"varchar" forKey: @"c_value"];
[types setObject: @"int" forKey: @"c_creationdate"];
[types setObject: @"int" forKey: @"c_lastseen"];
}
return types;
}
@end
//
// Oracle database
//
@implementation GCSOracleSpecialQueries
- (NSString *) createEMailAlarmsFolderWithName: (NSString *) tableName
@@ -293,4 +373,32 @@
return [NSString stringWithFormat: sqlFolderACLFormat, tableName];
}
- (NSString *) createSessionsFolderWithName: (NSString *) tableName
{
static NSString *sqlFolderFormat
= (@"CREATE TABLE %@ ("
@" c_id VARCHAR2(255) NOT NULL,"
@" c_value VARCHAR2(255) NOT NULL,"
@" c_creationdate INTEGER NOT NULL,"
@" c_lastseen INTEGER NOT NULL)");
return [NSString stringWithFormat: sqlFolderFormat, tableName];
}
- (NSDictionary *) sessionsAttributeTypes
{
static NSMutableDictionary *types = nil;
if (!types)
{
types = [NSMutableDictionary new];
[types setObject: @"varchar2" forKey: @"c_id"];
[types setObject: @"varchar2" forKey: @"c_value"];
[types setObject: @"integer" forKey: @"c_creationdate"];
[types setObject: @"integer" forKey: @"c_lastseen"];
}
return types;
}
@end
+2
View File
@@ -32,6 +32,7 @@ libGDLContentStore_HEADER_FILES += \
GCSFolderType.h \
GCSChannelManager.h \
GCSFieldExtractor.h \
GCSSessionsFolder.h \
GCSSpecialQueries.h \
GCSStringFormatter.h \
@@ -48,6 +49,7 @@ libGDLContentStore_OBJC_FILES += \
GCSFolderType.m \
GCSChannelManager.m \
GCSFieldExtractor.m \
GCSSessionsFolder.m \
GCSSpecialQueries.m \
GCSStringFormatter.m \