root / Classes / AccountManager.m @ 62ea6d49
History | View | Annotate | Download (23.7 kB)
1 |
// |
---|---|
2 |
// AccountManager.m |
3 |
// OpenStack |
4 |
// |
5 |
// Created by Mike Mayo on 10/21/10. |
6 |
// The OpenStack project is provided under the Apache 2.0 license. |
7 |
// |
8 |
|
9 |
#import "AccountManager.h" |
10 |
#import "OpenStackAccount.h" |
11 |
#import "OpenStackRequest.h" |
12 |
#import "Provider.h" |
13 |
#import "Container.h" |
14 |
#import "Folder.h" |
15 |
#import "StorageObject.h" |
16 |
#import "ASINetworkQueue.h" |
17 |
#import "APICallback.h" |
18 |
#import "JSON.h" |
19 |
#import "OpenStackAppDelegate.h" |
20 |
#import "NSString+Conveniences.h" |
21 |
|
22 |
@interface AccountManager() |
23 |
- (void)start:(OpenStackRequest *)request success:(APIResponseBlock)success failure:(APIResponseBlock)failure; |
24 |
- (void)retryWithUpdatedURL:(OpenStackRequest *)request success:(APIResponseBlock)success failure:(APIResponseBlock)failure; |
25 |
@end |
26 |
|
27 |
@implementation AccountManager |
28 |
|
29 |
@synthesize account, queue; |
30 |
|
31 |
#pragma mark - Callbacks |
32 |
|
33 |
- (void)start:(OpenStackRequest *)request success:(APIResponseBlock)success failure:(APIResponseBlock)failure { |
34 |
[request setCompletionBlock:^{ |
35 |
if ([request isSuccess]) { |
36 |
if (request.followUpSelectorString) { |
37 |
OpenStackRequest *followUpRequest = [self performSelector:NSSelectorFromString(request.followUpSelectorString) |
38 |
withObject:request]; |
39 |
if (followUpRequest) { |
40 |
[self start:followUpRequest success:success failure:failure]; |
41 |
return; |
42 |
} |
43 |
} |
44 |
success(request); |
45 |
[request notify]; |
46 |
} else if (request.retryWithUpdatedURL && |
47 |
((request.responseStatusCode == 401) || (request.responseStatusCode == 404) || (request.responseStatusCode == 0))) { |
48 |
[self retryWithUpdatedURL:request success:success failure:failure]; |
49 |
} else { |
50 |
failure(request); |
51 |
[request notify]; |
52 |
} |
53 |
}]; |
54 |
[request setFailedBlock:^{ |
55 |
if (request.retryWithUpdatedURL && |
56 |
((request.responseStatusCode == 401) || (request.responseStatusCode == 404) || (request.responseStatusCode == 0))) { |
57 |
[self retryWithUpdatedURL:request success:success failure:failure]; |
58 |
} else { |
59 |
failure(request); |
60 |
[request notify]; |
61 |
} |
62 |
}]; |
63 |
[request startAsynchronous]; |
64 |
} |
65 |
|
66 |
- (void)retryWithUpdatedURL:(OpenStackRequest *)request success:(APIResponseBlock)success failure:(APIResponseBlock)failure { |
67 |
[[self serviceCatalog] success:^(OpenStackRequest *serviceRequest) { |
68 |
OpenStackRequest *newRequest = [[request copy] autorelease]; |
69 |
if (newRequest.retryType == OpenStackRequestTypeAuthEndpoint) { |
70 |
NSString *urlPrefix = [account.provider.authEndpointURL description]; |
71 |
if (![urlPrefix hasSuffix:@"/"]) |
72 |
urlPrefix = [urlPrefix stringByAppendingString:@"/"]; |
73 |
NSString *urlSuffix = [[newRequest.url description] substringFromIndex:[[newRequest.retryBaseURL description] length]]; |
74 |
while ([urlSuffix hasPrefix:@"/"]) |
75 |
urlSuffix = [urlSuffix substringFromIndex:1]; |
76 |
newRequest.url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", urlPrefix, urlSuffix]]; |
77 |
} else if (newRequest.retryType == OpenStackRequestTypeUserCatalog) { |
78 |
NSString *urlPrefix = [account.provider.userCatalogURL description]; |
79 |
if (![urlPrefix hasSuffix:@"/"]) |
80 |
urlPrefix = [urlPrefix stringByAppendingString:@"/"]; |
81 |
NSString *urlSuffix = [[newRequest.url description] substringFromIndex:[[newRequest.retryBaseURL description] length]]; |
82 |
while ([urlSuffix hasPrefix:@"/"]) |
83 |
urlSuffix = [urlSuffix substringFromIndex:1]; |
84 |
newRequest.url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", urlPrefix, urlSuffix]]; |
85 |
} |
86 |
newRequest.retryWithUpdatedURL = NO; |
87 |
[self start:newRequest success:success failure:failure]; |
88 |
} failure:^(OpenStackRequest *serviceRequest) { |
89 |
failure(request); |
90 |
[request notify]; |
91 |
}]; |
92 |
} |
93 |
|
94 |
- (APICallback *)callbackWithRequest:(OpenStackRequest *)request success:(APIResponseBlock)success failure:(APIResponseBlock)failure { |
95 |
APICallback *callback = [[[APICallback alloc] initWithAccount:self.account request:request] autorelease]; |
96 |
request.delegate = self; |
97 |
request.callback = callback; |
98 |
[self start:request success:success failure:failure]; |
99 |
return callback; |
100 |
} |
101 |
|
102 |
- (APICallback *)callbackWithRequest:(OpenStackRequest *)request success:(APIResponseBlock)success { |
103 |
return [self callbackWithRequest:request success:success failure:^(OpenStackRequest *request){}]; |
104 |
} |
105 |
|
106 |
- (APICallback *)callbackWithRequest:(OpenStackRequest *)request { |
107 |
return [self callbackWithRequest:request success:^(OpenStackRequest *request){} failure:^(OpenStackRequest *request){}]; |
108 |
} |
109 |
|
110 |
#pragma mark - API Calls |
111 |
#pragma mark Service Catalog |
112 |
|
113 |
- (APICallback *)serviceCatalog { |
114 |
__block OpenStackRequest *request = [OpenStackRequest serviceCatalogRequest:self.account]; |
115 |
return [self callbackWithRequest:request success:^(OpenStackRequest *request) { |
116 |
NSURL *pithosObjectStoreURL = nil; |
117 |
NSURL *astakosAccountURL = nil; |
118 |
NSURL *astakosWebloginURL = nil; |
119 |
NSArray *serviceCatalog = [request serviceCatalog]; |
120 |
for (NSDictionary *service in serviceCatalog) { |
121 |
NSString *serviceName = [service objectForKey:@"name"]; |
122 |
if (!pithosObjectStoreURL && [serviceName isEqualToString:@"pithos_object-store"]) { |
123 |
pithosObjectStoreURL = [NSURL URLWithString:[[[service objectForKey:@"endpoints"] |
124 |
objectAtIndex:0] |
125 |
objectForKey:@"publicURL"]]; |
126 |
} else if (!astakosAccountURL && [serviceName isEqualToString:@"astakos_account"]) { |
127 |
astakosAccountURL = [NSURL URLWithString:[[[service objectForKey:@"endpoints"] |
128 |
objectAtIndex:0] |
129 |
objectForKey:@"publicURL"]]; |
130 |
} else if (!astakosWebloginURL && [serviceName isEqualToString:@"astakos_weblogin"]) { |
131 |
astakosWebloginURL = [NSURL URLWithString:[[[service objectForKey:@"endpoints"] |
132 |
objectAtIndex:0] |
133 |
objectForKey:@"SNF:webloginURL"]]; |
134 |
} |
135 |
if (pithosObjectStoreURL && astakosAccountURL && astakosWebloginURL) |
136 |
break; |
137 |
} |
138 |
self.account.provider.pithosObjectStoreURL = pithosObjectStoreURL; |
139 |
self.account.provider.astakosAccountURL = astakosAccountURL; |
140 |
self.account.provider.astakosWebloginURL = astakosWebloginURL; |
141 |
self.account.provider.manual = NO; |
142 |
|
143 |
if (self.account.authToken.length) { |
144 |
NSDictionary *token = [request token]; |
145 |
self.account.authToken = [token objectForKey:@"id"]; |
146 |
self.account.username = [[token objectForKey:@"tenant"] objectForKey:@"id"]; |
147 |
} |
148 |
} failure:^(OpenStackRequest *request) { |
149 |
if (request.responseStatusCode == 404) { |
150 |
self.account.provider.pithosObjectStoreURL = [self.account.provider.authURL URLByAppendingPathComponent:@"v1"]; |
151 |
self.account.provider.astakosAccountURL = [[self.account.provider.authURL copy] autorelease]; |
152 |
self.account.provider.astakosWebloginURL = [[self.account.provider.authURL copy] autorelease]; |
153 |
self.account.provider.manual = YES; |
154 |
} |
155 |
}]; |
156 |
} |
157 |
|
158 |
#pragma mark User Catalog |
159 |
|
160 |
- (APICallback *)userCatalogForDisplaynames:(NSArray *)displaynames UUIDs:(NSArray *)UUIDs { |
161 |
__block OpenStackRequest *request = [OpenStackRequest userCatalogRequest:self.account displaynames:displaynames UUIDs:UUIDs]; |
162 |
return [self callbackWithRequest:request success:^(OpenStackRequest *request) { |
163 |
NSDictionary *catalogs = [request catalogs]; |
164 |
NSDictionary *displaynameCatalog = [catalogs objectForKey:@"displayname_catalog"]; |
165 |
for (NSString *displayname in displaynameCatalog) { |
166 |
[self.account.userCatalog setObject:displayname forKey:[displaynameCatalog objectForKey:displayname]]; |
167 |
} |
168 |
if (UUIDs) { |
169 |
NSDictionary *UUIDCatalog = [catalogs objectForKey:@"uuid_catalog"]; |
170 |
for (NSString *UUID in UUIDs) { |
171 |
NSString *displayname = [UUIDCatalog objectForKey:UUID]; |
172 |
if (displayname) { |
173 |
[self.account.userCatalog setObject:displayname forKey:UUID]; |
174 |
} else { |
175 |
[self.account.userCatalog removeObjectForKey:UUID]; |
176 |
} |
177 |
} |
178 |
} |
179 |
[self.account persist]; |
180 |
}]; |
181 |
} |
182 |
|
183 |
#pragma mark Top |
184 |
|
185 |
- (APICallback *)authenticate { |
186 |
__block OpenStackRequest *request = [OpenStackRequest authenticationRequest:self.account]; |
187 |
return [self callbackWithRequest:request]; |
188 |
} |
189 |
|
190 |
- (APICallback *)getSharingAccounts { |
191 |
__block OpenStackRequest *request = [OpenStackRequest getSharingAccountsRequest:self.account]; |
192 |
request.followUpSelectorString = NSStringFromSelector(@selector(followUpGetSharingAccountsRequest:)); |
193 |
request.notificationURL = request.url; |
194 |
return [self callbackWithRequest:request]; |
195 |
} |
196 |
|
197 |
- (OpenStackRequest *)followUpGetSharingAccountsRequest:(OpenStackRequest *)request { |
198 |
NSArray *jsonSharingAccounts = [request jsonSharingAccounts]; |
199 |
NSMutableDictionary *sharingAccountsBuffer = [request.userInfo objectForKey:@"sharingAccountsBuffer"]; |
200 |
for (NSDictionary *dict in jsonSharingAccounts) { |
201 |
[sharingAccountsBuffer setObject:dict forKey:[dict objectForKey:@"name"]]; |
202 |
} |
203 |
|
204 |
if (jsonSharingAccounts.count < 10000) { |
205 |
return nil; |
206 |
} else { |
207 |
__block OpenStackRequest *followUpRequest = [OpenStackRequest getSharingAccountsRequest:self.account |
208 |
marker:[[jsonSharingAccounts lastObject] objectForKey:@"name"] |
209 |
sharingAccountsBuffer:sharingAccountsBuffer]; |
210 |
followUpRequest.callback = request.callback; |
211 |
followUpRequest.followUpSelectorString = request.followUpSelectorString; |
212 |
followUpRequest.notificationURL = request.notificationURL; |
213 |
return followUpRequest; |
214 |
} |
215 |
} |
216 |
|
217 |
#pragma mark Account |
218 |
|
219 |
- (APICallback *)getStorageAccountInfo { |
220 |
__block OpenStackRequest *request = [OpenStackRequest getStorageAccountInfoRequest:self.account]; |
221 |
return [self callbackWithRequest:request success:^(OpenStackRequest *request) { |
222 |
NSString *bytesUsedString = [request.responseHeaders objectForKey:@"X-Account-Bytes-Used"]; |
223 |
self.account.bytesUsed = (bytesUsedString ? |
224 |
[NSNumber numberWithUnsignedLongLong:strtoull([bytesUsedString UTF8String], NULL, 0)] : nil); |
225 |
NSString *policyQuotaString = [request.responseHeaders objectForKey:@"X-Account-Policy-Quota"]; |
226 |
self.account.policyQuota = (policyQuotaString ? |
227 |
[NSNumber numberWithUnsignedLongLong:strtoull([policyQuotaString UTF8String], NULL, 0)] : nil); |
228 |
[self.account persist]; |
229 |
}]; |
230 |
} |
231 |
|
232 |
- (APICallback *)getContainers { |
233 |
__block OpenStackRequest *request = [OpenStackRequest getContainersRequest:self.account]; |
234 |
request.followUpSelectorString = NSStringFromSelector(@selector(followUpGetContainersRequest:)); |
235 |
request.notificationURL = request.url; |
236 |
return [self callbackWithRequest:request success:^(OpenStackRequest *request) { |
237 |
NSMutableDictionary *containersBuffer = [request.userInfo objectForKey:@"containersBuffer"]; |
238 |
self.account.containers = (containersBuffer ? containersBuffer : [NSMutableDictionary dictionary]); |
239 |
NSString *bytesUsedString = [request.responseHeaders objectForKey:@"X-Account-Bytes-Used"]; |
240 |
self.account.bytesUsed = (bytesUsedString ? |
241 |
[NSNumber numberWithUnsignedLongLong:strtoull([bytesUsedString UTF8String], NULL, 0)] : nil); |
242 |
NSString *policyQuotaString = [request.responseHeaders objectForKey:@"X-Account-Policy-Quota"]; |
243 |
self.account.policyQuota = (policyQuotaString ? |
244 |
[NSNumber numberWithUnsignedLongLong:strtoull([policyQuotaString UTF8String], NULL, 0)] : nil); |
245 |
[self.account persist]; |
246 |
}]; |
247 |
} |
248 |
|
249 |
- (OpenStackRequest *)followUpGetContainersRequest:(OpenStackRequest *)request { |
250 |
NSArray *jsonContainers = [request jsonContainers]; |
251 |
NSMutableDictionary *containersBuffer = [request.userInfo objectForKey:@"containersBuffer"]; |
252 |
for (NSDictionary *dict in jsonContainers) { |
253 |
Container *container = [Container fromJSON:dict]; |
254 |
[containersBuffer setObject:container forKey:container.name]; |
255 |
} |
256 |
|
257 |
if (jsonContainers.count < 10000) { |
258 |
return nil; |
259 |
} else { |
260 |
__block OpenStackRequest *followUpRequest = [OpenStackRequest getContainersRequest:self.account |
261 |
marker:[[jsonContainers lastObject] objectForKey:@"name"] |
262 |
containersBuffer:containersBuffer]; |
263 |
followUpRequest.callback = request.callback; |
264 |
followUpRequest.followUpSelectorString = request.followUpSelectorString; |
265 |
followUpRequest.notificationURL = request.notificationURL; |
266 |
return followUpRequest; |
267 |
} |
268 |
} |
269 |
|
270 |
- (APICallback *)writeAccountMetadata:(NSDictionary *)accountInfo { |
271 |
__block OpenStackRequest *request = [OpenStackRequest writeAccountMetadataRequest:self.account withAccountInfo:accountInfo]; |
272 |
return [self callbackWithRequest:request]; |
273 |
} |
274 |
|
275 |
#pragma mark Container |
276 |
|
277 |
- (APICallback *)getContainerInfo:(Container *)container { |
278 |
__block OpenStackRequest *request = [OpenStackRequest getContainerInfoRequest:self.account container:container]; |
279 |
return [self callbackWithRequest:request success:^(OpenStackRequest *request) { |
280 |
container.metadata = [NSMutableDictionary dictionary]; |
281 |
for (NSString *headerName in request.responseHeaders) { |
282 |
if ([headerName hasPrefix:@"X-Container-Meta-"]) { |
283 |
[container.metadata setObject:[NSString decodeFromPercentEscape:[request.responseHeaders objectForKey:headerName]] |
284 |
forKey:[NSString decodeFromPercentEscape:[headerName substringFromIndex:17]]]; |
285 |
} |
286 |
} |
287 |
}]; |
288 |
} |
289 |
|
290 |
- (APICallback *)createContainer:(Container *)container { |
291 |
__block OpenStackRequest *request = [OpenStackRequest createContainerRequest:self.account container:container]; |
292 |
return [self callbackWithRequest:request success:^(OpenStackRequest *request) { |
293 |
[self.account.containers setObject:container forKey:container.name]; |
294 |
[self.account persist]; |
295 |
}]; |
296 |
} |
297 |
|
298 |
- (APICallback *)deleteContainer:(Container *)container { |
299 |
__block OpenStackRequest *request = [OpenStackRequest deleteContainerRequest:self.account container:container]; |
300 |
return [self callbackWithRequest:request success:^(OpenStackRequest *request) { |
301 |
}]; |
302 |
} |
303 |
|
304 |
- (APICallback *)getObjects:(Container *)container { |
305 |
__block OpenStackRequest *request = [OpenStackRequest getObjectsRequest:self.account container:container]; |
306 |
request.followUpSelectorString = NSStringFromSelector(@selector(followUpGetObjectsRequest:)); |
307 |
request.notificationURL = request.url; |
308 |
return [self callbackWithRequest:request success:^(OpenStackRequest *request) { |
309 |
NSMutableDictionary *objectsBuffer = [request.userInfo objectForKey:@"objectsBuffer"]; |
310 |
container.rootFolder = [Folder folder]; |
311 |
container.rootFolder.objects = (objectsBuffer ? objectsBuffer : [NSMutableDictionary dictionary]); |
312 |
[self.account persist]; |
313 |
}]; |
314 |
} |
315 |
|
316 |
- (OpenStackRequest *)followUpGetObjectsRequest:(OpenStackRequest *)request { |
317 |
NSArray *jsonObjects = [request jsonObjects]; |
318 |
NSMutableDictionary *objectsBuffer = [request.userInfo objectForKey:@"objectsBuffer"]; |
319 |
for (NSDictionary *dict in jsonObjects) { |
320 |
StorageObject *object = [StorageObject fromJSON:dict]; |
321 |
[objectsBuffer setObject:object forKey:object.name]; |
322 |
} |
323 |
|
324 |
if (jsonObjects.count < 10000) { |
325 |
return nil; |
326 |
} else { |
327 |
__block OpenStackRequest *followUpRequest = [OpenStackRequest getObjectsRequest:self.account |
328 |
container:[request.userInfo objectForKey:@"container"] |
329 |
marker:[[jsonObjects lastObject] objectForKey:@"name"] |
330 |
objectsBuffer:objectsBuffer]; |
331 |
followUpRequest.callback = request.callback; |
332 |
followUpRequest.followUpSelectorString = request.followUpSelectorString; |
333 |
followUpRequest.notificationURL = request.notificationURL; |
334 |
return followUpRequest; |
335 |
} |
336 |
} |
337 |
|
338 |
- (APICallback *)writeContainerPolicy:(Container *)container { |
339 |
__block OpenStackRequest *request = [OpenStackRequest writeContainerPolicyRequest:self.account container:container]; |
340 |
return [self callbackWithRequest:request]; |
341 |
} |
342 |
|
343 |
#pragma mark Storage Object |
344 |
|
345 |
- (APICallback *)getObjectInfo:(Container *)container object:(StorageObject *)object { |
346 |
__block OpenStackRequest *request = [OpenStackRequest getObjectInfoRequest:self.account container:container object:object]; |
347 |
return [self callbackWithRequest:request]; |
348 |
} |
349 |
|
350 |
- (APICallback *)getObjectInfo:(Container *)container object:(StorageObject *)object version:(NSString *)version { |
351 |
if (!version) { |
352 |
return [self getObjectInfo:container object:object]; |
353 |
} |
354 |
|
355 |
__block OpenStackRequest *request = [OpenStackRequest getObjectInfoRequest:self.account container:container object:object version:version]; |
356 |
return [self callbackWithRequest:request]; |
357 |
} |
358 |
|
359 |
- (APICallback *)getObjectVersionsList:(Container *)container object:(StorageObject *)object { |
360 |
__block OpenStackRequest *request = [OpenStackRequest getObjectVersionsRequest:account container:container object:object]; |
361 |
return [self callbackWithRequest:request]; |
362 |
} |
363 |
|
364 |
- (APICallback *)getObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate |
365 |
requestUserInfo:(NSDictionary *)requestUserInfo version:(NSString *)version { |
366 |
__block OpenStackRequest *request = [OpenStackRequest getObjectRequest:self.account container:container object:object version:version]; |
367 |
request.delegate = self; |
368 |
request.downloadProgressDelegate = downloadProgressDelegate; |
369 |
request.showAccurateProgress = YES; |
370 |
if (requestUserInfo) { |
371 |
request.userInfo = requestUserInfo; |
372 |
} |
373 |
|
374 |
OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate]; |
375 |
[app setObjectDownloadRequest:request forAccount:account container:container object:object]; |
376 |
return [self callbackWithRequest:request |
377 |
success:^(OpenStackRequest *request) { |
378 |
if (!object.hash) { |
379 |
object.hash = [request.responseHeaders objectForKey:@"X-Object-Hash"]; |
380 |
} |
381 |
OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate]; |
382 |
NSString *filePath = [app.cacheDirectoryPath stringByAppendingFormat:@"/%@.%@", object.hash, object.name.pathExtension]; |
383 |
[[request responseData] writeToFile:filePath atomically:YES]; |
384 |
[app setCacheFilePath:filePath forHash:object.hash]; |
385 |
[app removeObjectDownloadRequestForAccount:account container:container object:object]; |
386 |
} |
387 |
failure:^(OpenStackRequest *request) { |
388 |
OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate]; |
389 |
[app removeObjectDownloadRequestForAccount:account container:container object:object]; |
390 |
}]; |
391 |
} |
392 |
|
393 |
- (APICallback *)getObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate |
394 |
requestUserInfo:(NSDictionary *)requestUserInfo { |
395 |
return [self getObject:container object:object downloadProgressDelegate:downloadProgressDelegate requestUserInfo:requestUserInfo version:nil]; |
396 |
} |
397 |
|
398 |
- (APICallback *)getObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate { |
399 |
return [self getObject:container object:object downloadProgressDelegate:downloadProgressDelegate requestUserInfo:nil version:nil]; |
400 |
} |
401 |
|
402 |
- (APICallback *)writeObject:(Container *)container object:(StorageObject *)object downloadProgressDelegate:(id)downloadProgressDelegate { |
403 |
__block OpenStackRequest *request = [OpenStackRequest writeObjectRequest:self.account container:container object:object]; |
404 |
request.delegate = self; |
405 |
request.uploadProgressDelegate = downloadProgressDelegate; |
406 |
request.showAccurateProgress = YES; |
407 |
return [self callbackWithRequest:request]; |
408 |
} |
409 |
|
410 |
- (APICallback *)writeObjectMetadata:(Container *)container object:(StorageObject *)object { |
411 |
__block OpenStackRequest *request = [OpenStackRequest writeObjectMetadataRequest:self.account container:container object:object]; |
412 |
return [self callbackWithRequest:request]; |
413 |
} |
414 |
|
415 |
- (APICallback *)deleteObject:(Container *)container object:(StorageObject *)object { |
416 |
__block OpenStackRequest *request = [OpenStackRequest deleteObjectRequest:self.account container:container object:object]; |
417 |
return [self callbackWithRequest:request]; |
418 |
} |
419 |
|
420 |
#pragma mark - Notifications |
421 |
|
422 |
- (NSString *)notificationName:(NSString *)key identifier:(NSString *)identifier { |
423 |
return [NSString stringWithFormat:@"%@-%@-%@", key, self.account.uuid, identifier]; |
424 |
} |
425 |
|
426 |
- (void)notify:(NSString *)name request:(OpenStackRequest *)request { |
427 |
NSNotification *notification = [NSNotification notificationWithName:name object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; |
428 |
[[NSNotificationCenter defaultCenter] postNotification:notification]; |
429 |
} |
430 |
|
431 |
- (void)notify:(NSString *)name request:(OpenStackRequest *)request object:(id)object { |
432 |
NSNotification *notification = [NSNotification notificationWithName:name object:object userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; |
433 |
[[NSNotificationCenter defaultCenter] postNotification:notification]; |
434 |
} |
435 |
|
436 |
#pragma mark - Request Delegates |
437 |
|
438 |
- (void)requestFinished:(OpenStackRequest *)request { |
439 |
NSString *notificationName = [request.userInfo objectForKey:@"notificationName"]; |
440 |
if (!notificationName) |
441 |
return; |
442 |
|
443 |
id notificationObject = [request.userInfo objectForKey:@"notificationObject"]; |
444 |
if ([request isSuccess]) { |
445 |
NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Succeeded", notificationName] object:notificationObject]; |
446 |
[[NSNotificationCenter defaultCenter] postNotification:notification]; |
447 |
} else { |
448 |
NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Failed", notificationName] object:notificationObject userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; |
449 |
[[NSNotificationCenter defaultCenter] postNotification:notification]; |
450 |
} |
451 |
} |
452 |
|
453 |
- (void)requestFailed:(OpenStackRequest *)request { |
454 |
NSString *notificationName = [request.userInfo objectForKey:@"notificationName"]; |
455 |
if (!notificationName) |
456 |
return; |
457 |
|
458 |
id notificationObject = [request.userInfo objectForKey:@"notificationObject"]; |
459 |
NSNotification *notification = [NSNotification notificationWithName:[NSString stringWithFormat:@"%@Failed", notificationName] object:notificationObject userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]; |
460 |
[[NSNotificationCenter defaultCenter] postNotification:notification]; |
461 |
} |
462 |
|
463 |
@end |