// // AccountManager.m // OpenStack // // Created by Mike Mayo on 10/21/10. // The OpenStack project is provided under the Apache 2.0 license. // #import "AccountManager.h" #import "OpenStackAccount.h" #import "OpenStackRequest.h" #import "Provider.h" #import "Container.h" #import "Folder.h" #import "StorageObject.h" #import "GetContainersRequest.h" #import "GetObjectsRequest.h" #import "ASINetworkQueue.h" #import "APICallback.h" #import "JSON.h" #import "OpenStackAppDelegate.h" @implementation AccountManager @synthesize account, queue; #pragma mark - Callbacks - (APICallback *)callbackWithRequest:(id)request success:(APIResponseBlock)success failure:(APIResponseBlock)failure { APICallback *callback = [[[APICallback alloc] initWithAccount:self.account request:request] autorelease]; ((OpenStackRequest *)request).delegate = self; ((OpenStackRequest *)request).callback = callback; [request setCompletionBlock:^{ if ([request isSuccess]) { success(request); [request notify]; } else { failure(request); [request notify]; } }]; [request setFailedBlock:^{ failure(request); [request notify]; }]; [request startAsynchronous]; return callback; } - (APICallback *)callbackWithRequest:(id)request success:(APIResponseBlock)success { return [self callbackWithRequest:request success:success failure:^(OpenStackRequest *request){}]; } - (APICallback *)callbackWithRequest:(id)request { return [self callbackWithRequest:request success:^(OpenStackRequest *request){} failure:^(OpenStackRequest *request){}]; } #pragma mark - Notification - (NSString *)notificationName:(NSString *)key identifier:(NSString *)identifier { return [NSString stringWithFormat:@"%@-%@-%@", key, self.account.uuid, identifier]; } - (void)requestFinished:(OpenStackRequest *)request { NSString *notificationName = [request.userInfo objectForKey:@"notificationName"]; if (!notificationName) return; id notificationObject = [request.userInfo objectForKey:@"notificationObject"]; if ([request isSuccess]) { NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Succeeded", notificationName] object:notificationObject]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } else { NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Failed", notificationName] object:notificationObject userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } } - (void)requestFailed:(OpenStackRequest *)request { NSString *notificationName = [request.userInfo objectForKey:@"notificationName"]; if (!notificationName) return; id notificationObject = [request.userInfo objectForKey:@"notificationObject"]; NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Failed", notificationName] object:notificationObject userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } - (void)notify:(NSString *)name request:(OpenStackRequest *)request { NSNotification *notification = [NSNotification notificationWithName:name object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } - (void)notify:(NSString *)name request:(OpenStackRequest *)request object:(id)object { NSNotification *notification = [NSNotification notificationWithName:name object:object userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } #pragma mark - API Calls #pragma mark Object Storage - (APICallback *)getStorageAccountInfo { __block OpenStackRequest *request = [OpenStackRequest getStorageAccountInfoRequest:self.account]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { self.account.containerCount = [[[request responseHeaders] objectForKey:@"X-Account-Container-Count"] intValue]; NSString *bytesUsedString = [request.responseHeaders objectForKey:@"X-Account-Bytes-Used"]; self.account.bytesUsed = (bytesUsedString ? [NSNumber numberWithUnsignedLongLong:strtoull([bytesUsedString UTF8String], NULL, 0)] : nil); NSString *policyQuotaString = [request.responseHeaders objectForKey:@"X-Account-Policy-Quota"]; self.account.policyQuota = (policyQuotaString ? [NSNumber numberWithUnsignedLongLong:strtoull([policyQuotaString UTF8String], NULL, 0)] : nil); [self.account persist]; self.account.containerCount = [self.account.containers count]; }]; } - (APICallback *)getSharingAccounts { __block OpenStackRequest *request = [OpenStackRequest getSharingAccountsRequest:self.account]; return [self callbackWithRequest:request]; } - (APICallback *)getContainers { __block OpenStackRequest *request = [OpenStackRequest filesRequest:self.account method:@"GET" path:@""]; return [self callbackWithRequest:request]; } - (APICallback *)createContainer:(Container *)container { __block OpenStackRequest *request = [OpenStackRequest createContainerRequest:self.account container:container]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { [self.account.containers setObject:container forKey:container.name]; [self.account persist]; self.account.containerCount = [self.account.containers count]; }]; } - (APICallback *)deleteContainer:(Container *)container { __block OpenStackRequest *request = [OpenStackRequest deleteContainerRequest:self.account container:container]; return [self callbackWithRequest:request]; } - (void)getObjects:(Container *)container { [self getObjects:container afterMarker:nil objectsBuffer:nil]; } - (void)getObjects:(Container *)container afterMarker:(NSString *)marker objectsBuffer:(NSMutableDictionary *)objectsBuffer { if (![self queue]) { [self setQueue:(ASINetworkQueue *)[[[NSOperationQueue alloc] init] autorelease]]; } GetObjectsRequest *request = [GetObjectsRequest request:self.account container:container marker:marker objectsBuffer:objectsBuffer]; [queue addOperation:request]; } - (void)getObjectsSucceeded:(OpenStackRequest *)request { if ([request isSuccess]) { Container *container = [request.userInfo objectForKey:@"container"]; NSMutableDictionary *objects = [request objects]; container.rootFolder = [Folder folder]; container.rootFolder.objects = objects; [self.account persist]; NSNotification *notification = [NSNotification notificationWithName:@"getObjectsSucceeded" object:self.account userInfo:[NSDictionary dictionaryWithObject:container forKey:@"container"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } else { NSNotification *notification = [NSNotification notificationWithName:@"getObjectsFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } } - (void)getObjectsFailed:(OpenStackRequest *)request { NSNotification *notification = [NSNotification notificationWithName:@"getObjectsFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; [[NSNotificationCenter defaultCenter] postNotification:notification]; } - (APICallback *)getContainerInfo:(Container *)container { __block OpenStackRequest *request = [OpenStackRequest getContainerInfoRequest:self.account container:container]; return [self callbackWithRequest:request]; } - (APICallback *)getObjectInfo:(Container *)container object:(StorageObject *)object { __block OpenStackRequest *request = [OpenStackRequest getObjectInfoRequest:self.account container:container object:object]; return [self callbackWithRequest:request]; } - (APICallback *)getObjectInfo:(Container *)container object:(StorageObject *)object version:(NSString *)version { if (!version) return [self getObjectInfo:container object:object]; __block OpenStackRequest *request = [OpenStackRequest getObjectInfoRequest:self.account container:container object:object version:version]; return [self callbackWithRequest:request]; } - (APICallback *)getObjectVersionsList:(Container *)container object:(StorageObject *)object { __block OpenStackRequest *request = [OpenStackRequest getObjectVersionsRequest:account container:container object:object]; return [self callbackWithRequest:request]; } - (APICallback *)getObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate { return [self getObject:container object:object downloadProgressDelegate:downloadProgressDelegate requestUserInfo:nil]; } - (APICallback *)getObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate requestUserInfo:(NSDictionary *)requestUserInfo { return [self getObject:container object:object downloadProgressDelegate:downloadProgressDelegate requestUserInfo:requestUserInfo version:nil]; } - (APICallback *)getObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate requestUserInfo:(NSDictionary *)requestUserInfo version:(NSString *)version{ __block OpenStackRequest *request = [OpenStackRequest getObjectRequest:self.account container:container object:object version:version]; request.delegate = self; request.downloadProgressDelegate = downloadProgressDelegate; request.showAccurateProgress = YES; if (requestUserInfo) { request.userInfo = requestUserInfo; } OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate]; [app setObjectDownloadRequest:request forAccount:account container:container object:object]; return [self callbackWithRequest:request success:^(OpenStackRequest *request) { if (!object.hash) object.hash = [request.responseHeaders objectForKey:@"X-Object-Hash"]; OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate]; NSString *filePath = [app.cacheDirectoryPath stringByAppendingFormat:@"/%@.%@", object.hash, object.name.pathExtension]; [[request responseData] writeToFile:filePath atomically:YES]; [app setCacheFilePath:filePath forHash:object.hash]; [app removeObjectDownloadRequestForAccount:account container:container object:object]; } failure:^(OpenStackRequest *request) { OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate]; [app removeObjectDownloadRequestForAccount:account container:container object:object]; }]; } - (APICallback *)writeObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate { __block OpenStackRequest *request = [OpenStackRequest writeObjectRequest:self.account container:container object:object]; request.delegate = self; request.uploadProgressDelegate = downloadProgressDelegate; request.showAccurateProgress = YES; return [self callbackWithRequest:request]; } - (APICallback *)deleteObject:(Container *)container object:(StorageObject *)object { __block OpenStackRequest *request = [OpenStackRequest deleteObjectRequest:self.account container:container object:object]; return [self callbackWithRequest:request]; } - (APICallback *)writeObjectMetadata:(Container *)container object:(StorageObject *)object { __block OpenStackRequest *request = [OpenStackRequest writeObjectMetadataRequest:self.account container:container object:object]; return [self callbackWithRequest:request]; } - (APICallback *)writeAccountMetadata:(NSDictionary *)accountInfo { __block OpenStackRequest *request = [OpenStackRequest writeAccountMetadataRequest:self.account withAccountInfo:accountInfo]; return [self callbackWithRequest:request]; } - (APICallback *)writeContainerPolicy:(Container *)container { __block OpenStackRequest *request = [OpenStackRequest writeContainerPolicyRequest:self.account container:container]; return [self callbackWithRequest:request]; } #pragma mark - Memory Management - (void)dealloc { [super dealloc]; } @end