/* * CacheCollection.m * * $Header$ * * Copyright 2004 Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may * require a specific license from the United States Government. * It is the responsibility of any person or organization contemplating * export to obtain such a license before exporting. * * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and * distribute this software and its documentation for any purpose and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of M.I.T. not be used in advertising or publicity pertaining * to distribution of the software without specific, written prior * permission. Furthermore if you modify this software you must label * your software as modified software and not distribute it in such a * fashion that it might be confused with the original M.I.T. software. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" without express * or implied warranty. */ #import "CacheCollection.h" #import "Cache.h" #import "Credential.h" #import "Utilities.h" #define kCacheCollectionUpdateTimerInterval 5 // --------------------------------------------------------------------------- static int SortCaches (Cache *cache1, Cache *cache2, void *context) { if ([cache1 lastDefaultTime] > [cache2 lastDefaultTime]) { // cache1 has been default more recently return NSOrderedAscending; } else if ([cache1 lastDefaultTime] < [cache2 lastDefaultTime]) { // cache2 has been default more recently return NSOrderedDescending; } else { // Neither has been default (usually) return NSOrderedSame; } } @implementation CacheCollection // --------------------------------------------------------------------------- + (CacheCollection *) sharedCacheCollection { static CacheCollection *sCacheCollection = NULL; if (sCacheCollection == NULL) { sCacheCollection = [[CacheCollection alloc] init]; } return sCacheCollection; } // --------------------------------------------------------------------------- - (id) init { if ((self = [super init])) { cachesArray = NULL; lastChangeTime = 0; updateTimer = NULL; if (![self update]) { [self release]; return NULL; } updateTimer = [[TargetOwnedTimer scheduledTimerWithTimeInterval: kCacheCollectionUpdateTimerInterval target: self selector: @selector (updateTimer:) userInfo: NULL repeats: YES] retain]; } return self; } // --------------------------------------------------------------------------- - (void) dealloc { if (cachesArray != NULL) { [cachesArray release]; } if (updateTimer != NULL) { [updateTimer invalidate]; [updateTimer release]; } [super dealloc]; } // --------------------------------------------------------------------------- - (void) updateTimer: (TargetOwnedTimer *) timer { [self update]; } // --------------------------------------------------------------------------- - (BOOL) update { BOOL updated = NO; cc_int32 err = ccNoError; cc_time_t newLastChangeTime = 0; if (err == ccNoError) { err = KLLastChangedTime (&newLastChangeTime); } if (err == ccNoError) { if (newLastChangeTime > lastChangeTime) { dprintf ("updateTimer got new change time %d", newLastChangeTime); NSMutableArray *newCachesArray = NULL; cc_ccache_t defaultCCache = NULL; cc_context_t context = NULL; cc_ccache_iterator_t iterator = NULL; if (err == ccNoError) { newCachesArray = [[NSMutableArray alloc] init]; if (newCachesArray == NULL) { err = ccErrNoMem; } } if (err == ccNoError) { err = cc_initialize (&context, ccapi_version_4, NULL, NULL); } if (err == ccNoError) { err = cc_context_open_default_ccache (context, &defaultCCache); if (err != ccNoError) { // No caches is okay defaultCCache = NULL; err = ccNoError; } } if (err == ccNoError) { err = cc_context_new_ccache_iterator (context, &iterator); } while (err == ccNoError) { cc_ccache_t ccache = NULL; Cache *cache = NULL; if (err == ccNoError) { err = cc_ccache_iterator_next (iterator, &ccache); } if (err == ccNoError) { cache = [self findCacheForCCache: ccache]; if (cache != NULL) { err = [cache synchronizeWithCCache: ccache defaultCCache: defaultCCache]; } else { cache = [[[Cache alloc] initWithCCache: ccache defaultCCache: defaultCCache] autorelease]; if (cache == NULL) { err = ccErrNoMem; } } } if (err == ccNoError) { [newCachesArray addObject: cache]; cache = NULL; // don't free ccache = NULL; // Cache object takes ownership of ccache } if (cache != NULL) { [cache release]; } if (ccache != NULL) { cc_ccache_release (ccache); } } if (err == ccIteratorEnd) { err = ccNoError; } if (err == ccNoError) { [newCachesArray sortUsingFunction: SortCaches context: NULL]; if (cachesArray != NULL) { [cachesArray release]; } cachesArray = newCachesArray; newCachesArray = NULL; // don't free lastChangeTime = newLastChangeTime; dprintf ("Posting CacheCollectionDidChangeNotification..."); // Post immediately! Otherwise the objects will get out of sync with the table views [[NSNotificationCenter defaultCenter] postNotificationName: CacheCollectionDidChangeNotification object: self]; updated = YES; } if (newCachesArray != NULL) { [newCachesArray release]; } if (iterator != NULL) { cc_ccache_iterator_release (iterator); } if (defaultCCache != NULL) { cc_ccache_release (defaultCCache); } if (context != NULL) { cc_context_release (context); } } } if (err != ccNoError) { dprintf ("updateTimer got error %d (%s)", err, error_message (err)); } return updated; } // --------------------------------------------------------------------------- - (Cache *) findCacheForCCache: (cc_ccache_t) ccache { unsigned int i = 0; for (i = 0; i < [cachesArray count]; i++) { Cache *cache = [cachesArray objectAtIndex: i]; if ([cache isEqualToCCache: ccache]) { return cache; } } return NULL; } // --------------------------------------------------------------------------- - (Cache *) findCacheForName: (NSString *) name { Cache *cache = NULL; cc_context_t context = NULL; cc_ccache_t ccache = NULL; cc_int32 err = cc_initialize (&context, ccapi_version_4, NULL, NULL);; if (err == ccNoError) { err = cc_context_open_ccache (context, [name cString], &ccache); } if (err == ccNoError) { cache = [self findCacheForCCache: ccache]; } if (ccache != NULL) { cc_ccache_release (ccache); } if (context != NULL) { cc_context_release (context); } return cache; } // --------------------------------------------------------------------------- - (Cache *) cacheAtIndex: (unsigned int) cacheIndex { if (cacheIndex < [cachesArray count]) { return [cachesArray objectAtIndex: cacheIndex]; } else { return NULL; } } // --------------------------------------------------------------------------- - (unsigned int) indexOfCache: (Cache *) cache { return [cachesArray indexOfObject: cache]; } // --------------------------------------------------------------------------- - (Cache *) defaultCache { unsigned int i = 0; for (i = 0; i < [cachesArray count]; i++) { Cache *cache = [cachesArray objectAtIndex: i]; if ([cache isDefault]) { return cache; } } return NULL; } // --------------------------------------------------------------------------- - (NSAttributedString *) stringValueForTicketColumnAtIndex: (int) rowIndex { return [[cachesArray objectAtIndex: rowIndex] stringValueForTicketColumn]; } // --------------------------------------------------------------------------- - (NSAttributedString *) stringValueForLifetimeColumnAtIndex: (int) rowIndex { return [[cachesArray objectAtIndex: rowIndex] stringValueForLifetimeColumn]; } // --------------------------------------------------------------------------- - (NSArray *) caches { return cachesArray; } // --------------------------------------------------------------------------- - (int) numberOfCaches { return [cachesArray count]; } @end