Statistics
| Branch: | Tag: | Revision:

root / pithos-macos / PithosAccountNode.m @ fb27f368

History | View | Annotate | Download (26 kB)

1
//
2
//  PithosAccountNode.m
3
//  pithos-macos
4
//
5
// Copyright 2011-2013 GRNET S.A. All rights reserved.
6
//
7
// Redistribution and use in source and binary forms, with or
8
// without modification, are permitted provided that the following
9
// conditions are met:
10
// 
11
//   1. Redistributions of source code must retain the above
12
//      copyright notice, this list of conditions and the following
13
//      disclaimer.
14
// 
15
//   2. Redistributions in binary form must reproduce the above
16
//      copyright notice, this list of conditions and the following
17
//      disclaimer in the documentation and/or other materials
18
//      provided with the distribution.
19
// 
20
// THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
21
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
24
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
// POSSIBILITY OF SUCH DAMAGE.
32
// 
33
// The views and conclusions contained in the software and
34
// documentation are those of the authors and should not be
35
// interpreted as representing official policies, either expressed
36
// or implied, of GRNET S.A.
37

    
38
#import "PithosAccountNode.h"
39
#import "PithosContainerNode.h"
40
#import "ASIPithos.h"
41
#import "ASIPithosAccountRequest.h"
42
#import "ASIPithosAccount.h"
43
#import "ASIPithosContainer.h"
44
#import "ASIDownloadCache.h"
45
#import "PithosAccount.h"
46
#import "PithosUtilities.h"
47
#import "PithosActivityFacility.h"
48

    
49
static NSImage *sharedIcon = nil;
50

    
51
@implementation PithosAccountNode
52
@synthesize pithosAccount, accountRequest, applyMetadataAccountRequest, refreshMetadataAccountRequest, translatedGroups;
53

    
54
+ (void)initialize {
55
	if (self == [PithosAccountNode class])
56
        sharedIcon = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kUserIcon)];
57
}
58

    
59
#pragma mark -
60
#pragma mark Object Lifecycle
61

    
62
- (void)dealloc {
63
    [accountRequest clearDelegatesAndCancel];
64
    [refreshMetadataAccountRequest clearDelegatesAndCancel];
65
    [applyMetadataAccountRequest clearDelegatesAndCancel];
66
}
67

    
68
#pragma mark -
69
#pragma mark Internal
70

    
71
- (void)updateGroups {
72
    if (!pithosAccount) {
73
        self.translatedGroups = [NSMutableDictionary dictionary];
74
    } else if (pithosAccountManager) {
75
        NSMutableSet *UUIDs = [NSMutableSet set];
76
        for (NSString *groupName in pithosAccount.groups) {
77
            [UUIDs addObjectsFromArray:[pithosAccount.groups objectForKey:groupName]];
78
        }
79
        [UUIDs removeObject:@""];
80
        [UUIDs removeObject:@"*"];
81
        if (UUIDs.count) {
82
            [pithosAccountManager updateUserCatalogForDisplaynames:nil UUIDs:[UUIDs allObjects]];
83
        }
84
        
85
        NSMutableDictionary *newTranslatedGroups = [NSMutableDictionary dictionaryWithCapacity:pithosAccount.groups.count];
86
        for (NSString *groupName in pithosAccount.groups) {
87
            NSMutableArray *groupUsers = [NSMutableArray array];
88
            for (NSString *UUID in [pithosAccount.groups objectForKey:groupName]) {
89
                [groupUsers addObject:[pithosAccountManager displaynameForUUID:UUID safe:YES]];
90
            }
91
            [newTranslatedGroups setObject:groupUsers forKey:groupName];
92
        }
93
        self.translatedGroups = newTranslatedGroups;
94
    } else {
95
        self.translatedGroups = [pithosAccount.groups copy];
96
    }
97
}
98

    
99
#pragma mark -
100
#pragma mark Actions
101

    
102
- (void)reset {
103
    [accountRequest clearDelegatesAndCancel];
104
    self.accountRequest = nil;
105
    [refreshMetadataAccountRequest clearDelegatesAndCancel];
106
    self.refreshMetadataAccountRequest = nil;
107
    [applyMetadataAccountRequest clearDelegatesAndCancel];
108
    self.applyMetadataAccountRequest = nil;
109
    children = nil;
110
    newChildren = nil;
111
    self.pithosAccount = nil;
112
    freshness = PithosNodeStateRefreshNeeded;
113
    forcedRefresh = YES;
114
    [self postChildrenUpdatedNotificationName];
115
    [self children];
116
}
117

    
118
#pragma mark -
119
#pragma mark Properties
120

    
121
- (void)setPithosAccount:(ASIPithosAccount *)aPithosAccount {
122
    if (![pithosAccount isEqualTo:aPithosAccount]) {
123
        pithosAccount = aPithosAccount;
124
        [self updateGroups];
125
    }
126
}
127

    
128
- (NSString *)url {
129
    return [NSString stringWithFormat:@"@account@%@%@",
130
            (sharingAccount ? sharingAccount : pithosAccountManager.pithos.authUser),
131
            (shared ? @"?shared" : @"")];
132
}
133

    
134
- (NSArray *)children {
135
    @synchronized(self) {
136
        switch (freshness) {
137
            case PithosNodeStateFresh:
138
                break;
139
            case PithosNodeStateRefreshNeeded:
140
                freshness = PithosNodeStateRefreshing;
141
                self.accountRequest = [ASIPithosAccountRequest listContainersRequestWithPithos:pithosAccountManager.pithos
142
                                                                                         limit:0
143
                                                                                        marker:nil
144
                                                                                        shared:shared
145
                                                                                         until:nil];
146
                if (sharingAccount)
147
                    [accountRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithosAccountManager.pithos];
148
                else if (!forcedRefresh)
149
                    accountRequest.downloadCache = [ASIDownloadCache sharedCache];
150
                accountRequest.delegate = self;
151
                accountRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
152
                accountRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
153
                accountRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
154
                                           [NSNumber numberWithInteger:NSOperationQueuePriorityVeryHigh], @"priority", 
155
                                           [NSNumber numberWithUnsignedInteger:10], @"retries", 
156
                                           NSStringFromSelector(@selector(accountRequestFinished:)), @"didFinishSelector", 
157
                                           NSStringFromSelector(@selector(accountRequestFailed:)), @"didFailSelector", 
158
                                           nil];
159
                [[PithosUtilities prepareRequest:accountRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous];
160
                break;
161
            case PithosNodeStateRefreshing:
162
                break;
163
            case PithosNodeStateRefreshFinished:
164
                if (newChildren) {
165
                    children = newChildren;
166
                    newChildren = nil;
167
                }
168
                freshness = PithosNodeStateFresh;
169
            default:
170
                break;
171
        }
172
        return children;
173
    }
174
}
175

    
176
- (NSString *)displayName {
177
    if (displayName == nil) {
178
        if (!sharingAccount) {
179
            return @"account";
180
        } else if (pithosAccountManager) {
181
            return [pithosAccountManager displaynameForUUID:sharingAccount safe:YES];
182
        } else {
183
            return [sharingAccount copy];
184
        }
185
    }
186
    return [displayName copy];
187
}
188

    
189
- (NSImage *)icon {
190
    if (icon == nil)
191
        icon = sharedIcon;
192
    return icon;
193
}
194

    
195
#pragma mark -
196
#pragma mark ASIHTTPRequestDelegate
197

    
198
- (void)accountRequestFailed:(ASIPithosAccountRequest *)request {
199
    @autoreleasepool {
200
        NSString *message;
201
        NSError *error = [accountRequest error];
202
        if (error)
203
            message = [NSString stringWithFormat:@"Account listing %@ failed: %@", accountRequest.url, [error localizedDescription]];
204
        else
205
            message = [NSString stringWithFormat:@"Account listing %@ failed: (%d) %@", 
206
                       accountRequest.url, accountRequest.responseStatusCode, accountRequest.responseStatusMessage];
207
        dispatch_async(dispatch_get_main_queue(), ^{
208
            [[PithosActivityFacility defaultPithosActivityFacility] startAndEndActivityWithType:PithosActivityOther message:message];
209
        });
210
        NSUInteger retries = [[accountRequest.userInfo objectForKey:@"retries"] unsignedIntegerValue];
211
        if (retries > 0) {
212
            ASIPithosAccountRequest *newAccountRequest = (ASIPithosAccountRequest *)[PithosUtilities copyRequest:accountRequest];
213
            [(NSMutableDictionary *)(newAccountRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
214
            self.accountRequest = newAccountRequest;
215
            [[PithosUtilities prepareRequest:accountRequest priority:[[accountRequest.userInfo objectForKey:@"priority"] integerValue]] startAsynchronous];
216
        } else {
217
            newChildren = nil;
218
            self.accountRequest = nil;
219
            forcedRefresh = NO;
220
            @synchronized(self) {
221
                freshness = PithosNodeStateRefreshNeeded;
222
            }
223
        }
224
    }
225
}
226

    
227
- (void)accountRequestFinished:(ASIPithosAccountRequest *)request {
228
    @autoreleasepool {
229
        DLog(@"List account finished: %@", [accountRequest url]);
230
        DLog(@"Cached: %d", [accountRequest didUseCachedResponse]);
231
        if (accountRequest.responseStatusCode == 200) {
232
            self.pithosAccount = [accountRequest account];
233
            
234
            NSMutableArray *containers = [accountRequest.userInfo objectForKey:@"containers"];
235
            NSArray *someContainers = [accountRequest containers];
236
            if (containers == nil) {
237
                containers = [NSMutableArray arrayWithArray:someContainers];
238
            } else {
239
                [containers addObjectsFromArray:someContainers];
240
            }
241
            if ([someContainers count] < 10000) {
242
                if (!accountRequest.didUseCachedResponse || ([containers count] != [someContainers count]) || !children) {
243
                    // Save new children
244
                    DLog(@"using newChildren");
245
                    newChildren = [[NSMutableArray alloc] init];
246
                    NSMutableIndexSet *keptNodes = [NSMutableIndexSet indexSet];
247
                    for (ASIPithosContainer *container in containers) {
248
                        PithosContainerNode *node = [[PithosContainerNode alloc] initWithPithosAccountManager:pithosAccountManager
249
                                                                                              pithosContainer:container];
250
                        node.parent = self;
251
                        node.shared = shared;
252
                        node.sharingAccount = sharingAccount;
253
                        node.inheritChildrenUpdatedNotificationName = inheritChildrenUpdatedNotificationName;
254
                        if (children) {
255
                            NSUInteger oldIndex = [children indexOfObject:node];
256
                            if (oldIndex != NSNotFound) {
257
                                // Use the same pointer value, if possible
258
                                node = [children objectAtIndex:oldIndex];
259
    //                            node.pithosContainer = container;
260
                                [node setLimitedPithosContainer:container];
261
                                [keptNodes addIndex:oldIndex];
262
                            }
263
                        }
264
                        [newChildren addObject:node];
265
                    }
266
                    [[children objectsAtIndexes:
267
                      [[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [children count])] indexesPassingTest:^(NSUInteger idx, BOOL *stop){
268
                        if ([keptNodes containsIndex:idx])
269
                            return NO;
270
                        return YES;
271
                    }]] makeObjectsPerformSelector:@selector(pithosNodeWillBeRemoved)];
272
                }
273
                // Else cache was used and all results were fetched during this request, so existing children can be reused
274
                self.accountRequest = nil;
275
                forcedRefresh = NO;
276
                @synchronized(self) {
277
                    freshness = PithosNodeStateRefreshFinished;
278
                }
279
                [self postChildrenUpdatedNotificationName];
280
            } else {
281
                // Do an additional request to fetch more objects
282
                self.accountRequest = [ASIPithosAccountRequest listContainersRequestWithPithos:pithosAccountManager.pithos
283
                                                                                         limit:0
284
                                                                                        marker:[[someContainers lastObject] name]
285
                                                                                        shared:shared
286
                                                                                         until:nil];
287
                if (sharingAccount)
288
                    [accountRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithosAccountManager.pithos];
289
                else if (!forcedRefresh)
290
                    accountRequest.downloadCache = [ASIDownloadCache sharedCache];
291
                accountRequest.delegate = self;
292
                accountRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
293
                accountRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
294
                accountRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
295
                                           [NSNumber numberWithInteger:NSOperationQueuePriorityVeryHigh], @"priority", 
296
                                           [NSNumber numberWithUnsignedInteger:10], @"retries", 
297
                                           NSStringFromSelector(@selector(accountRequestFinished:)), @"didFinishSelector", 
298
                                           NSStringFromSelector(@selector(accountRequestFailed:)), @"didFailSelector",
299
                                           containers, @"containers",
300
                                           nil];
301
                [[PithosUtilities prepareRequest:accountRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous];
302
            }
303
        } else if (accountRequest.responseStatusCode == 304) {
304
            // Account is not modified, so existing children can be reused
305
            self.accountRequest = nil;
306
            forcedRefresh = NO;
307
            @synchronized(self) {
308
                freshness = PithosNodeStateRefreshFinished;
309
            }
310
            [self postChildrenUpdatedNotificationName];
311
        } else {
312
            [self accountRequestFailed:accountRequest];
313
        }
314
    }
315
}
316

    
317
- (void)accountMetadataRequestFinished:(ASIPithosAccountRequest *)request {
318
    @autoreleasepool {
319
        DLog(@"URL: %@", [request url]);
320
        DLog(@"cached: %d", [request didUseCachedResponse]);
321
        
322
        if ([request isEqualTo:applyMetadataAccountRequest]) {
323
            @synchronized(self) {
324
                self.applyMetadataAccountRequest = nil;
325
            }
326
            [self refreshInfo];
327
        } else if ([request isEqualTo:refreshMetadataAccountRequest]) {
328
            self.pithosAccount = [refreshMetadataAccountRequest account];
329
            @synchronized(self) {
330
                self.refreshMetadataAccountRequest = nil;
331
            }
332
        }
333
    }
334
}
335

    
336
- (void)accountMetadataRequestFailed:(ASIPithosAccountRequest *)request {
337
    @autoreleasepool {
338
        NSUInteger retries = [[request.userInfo objectForKey:@"retries"] unsignedIntegerValue];
339
        if (retries > 0) {
340
            ASIPithosAccountRequest *newRequest = (ASIPithosAccountRequest *)[PithosUtilities copyRequest:request];
341
            [(NSMutableDictionary *)(newRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
342
            if ([request isEqualTo:applyMetadataAccountRequest]) {
343
                @synchronized(self) {
344
                    self.applyMetadataAccountRequest = newRequest;
345
                }
346
            } else if ([request isEqualTo:refreshMetadataAccountRequest]) {
347
                @synchronized(self) {
348
                    self.refreshMetadataAccountRequest = newRequest;
349
                }
350
            }
351
            [[PithosUtilities prepareRequest:newRequest priority:[[newRequest.userInfo objectForKey:@"priority"] integerValue]] startAsynchronous];
352
        } else {
353
            if ([request isEqualTo:applyMetadataAccountRequest]) {
354
                [PithosUtilities httpRequestErrorAlertWithRequest:applyMetadataAccountRequest];
355
                @synchronized(self) {
356
                    self.applyMetadataAccountRequest = nil;
357
                }
358
            } else if ([request isEqualTo:refreshMetadataAccountRequest]) {
359
                [PithosUtilities httpRequestErrorAlertWithRequest:refreshMetadataAccountRequest];
360
                @synchronized(self) {
361
                    self.refreshMetadataAccountRequest = nil;
362
                }
363
            }
364
        }
365
    }
366
}
367

    
368
#pragma mark -
369
#pragma mark Info
370

    
371
- (void)applyInfo {
372
    @synchronized(self) {
373
        if (applyMetadataAccountRequest == nil) {
374
            NSMutableDictionary *groups = [NSMutableDictionary dictionary];
375
            if (translatedGroups.count) {
376
                for (NSString *groupName in translatedGroups) {
377
                    if (!groupName.length ||
378
                        [groupName rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@" -_~,;"]].location != NSNotFound) {
379
                        NSAlert *alert = [[NSAlert alloc] init];
380
                        [alert setMessageText:@"Invalid Input"];
381
                        [alert setInformativeText:@"Group names cannot be empty or contain ' ', '-', '_', '~', ',' or ';'."];
382
                        [alert addButtonWithTitle:@"OK"];
383
                        [alert runModal];
384
                        return;
385
                    }
386
                }
387
                if (pithosAccountManager) {
388
                    NSMutableSet *allGroupUsers = [NSMutableSet set];
389
                    for (NSMutableArray *groupUsers in [translatedGroups objectEnumerator]) {
390
                        [allGroupUsers addObjectsFromArray:groupUsers];
391
                    }
392
                    [allGroupUsers removeObject:@""];
393
                    [allGroupUsers removeObject:@"*"];
394
                    if (allGroupUsers.count) {
395
                        ASIPithosRequest *userCatalogRequest = [pithosAccountManager updateUserCatalogForDisplaynames:[allGroupUsers allObjects]
396
                                                                                                                        UUIDs:nil];
397
                        if (userCatalogRequest.error || ((userCatalogRequest.responseStatusCode != 200) && (userCatalogRequest.responseStatusCode != 404))) {
398
                            return;
399
                        } else if (userCatalogRequest.responseStatusCode == 200) {
400
                            // Check if all users exist.
401
                            NSDictionary *displaynameCatalog = [userCatalogRequest displaynameCatalog];
402
                            NSMutableArray *inexistentGroupUsers = [NSMutableArray array];
403
                            for (NSString *groupUser in allGroupUsers) {
404
                                if (![displaynameCatalog objectForKey:groupUser]) {
405
                                    [inexistentGroupUsers addObject:groupUser];
406
                                }
407
                            }
408
                            if (!inexistentGroupUsers.count) {
409
                                // Create groups.
410
                                for (NSString *groupName in translatedGroups) {
411
                                    NSMutableArray *groupUsers = [NSMutableArray array];
412
                                    for (NSString *groupUser in [translatedGroups objectForKey:groupName]) {
413
                                        [groupUsers addObject:([groupUser isEqualToString:@"*"] ?
414
                                                               @"*" : [displaynameCatalog objectForKey:groupUser])];
415
                                    }
416
                                    [groups setObject:groupUsers forKey:groupName];
417
                                }
418
                            } else {
419
                                NSAlert *alert = [[NSAlert alloc] init];
420
                                if (inexistentGroupUsers.count == 1) {
421
                                    [alert setMessageText:@"Invalid User"];
422
                                    [alert setInformativeText:[NSString stringWithFormat:@"User '%@' doesn't exist.", [inexistentGroupUsers objectAtIndex:0]]];
423
                                } else {
424
                                    [alert setMessageText:@"Invalid Users"];
425
                                    [alert setInformativeText:[NSString stringWithFormat:@"Users '%@' don't exist.", [inexistentGroupUsers componentsJoinedByString:@"', '"]]];
426
                                }
427
                                [alert addButtonWithTitle:@"OK"];
428
                                [alert runModal];
429
                                return;
430
                            }
431
                        } else {
432
                            // 404. Since we don't translate to UUIDs, check for invalid chars.
433
                            BOOL valid = YES;
434
                            for (NSString *groupUser in allGroupUsers) {
435
                                if ([groupUser rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@" ~,;:"]].location != NSNotFound) {
436
                                    valid = NO;
437
                                    break;
438
                                }
439
                            }
440
                            if (valid) {
441
                                [groups addEntriesFromDictionary:translatedGroups];
442
                            } else {
443
                                NSAlert *alert = [[NSAlert alloc] init];
444
                                [alert setMessageText:@"Invalid Input"];
445
                                [alert setInformativeText:@"Users cannot contain ' ', '~', ',', ';' or ':'."];
446
                                [alert addButtonWithTitle:@"OK"];
447
                                [alert runModal];
448
                                return;
449
                            }
450
                        }
451
                    } else {
452
                        for (NSString *groupName in translatedGroups) {
453
                            if ([[translatedGroups objectForKey:groupName] containsObject:@"*"]) {
454
                                [groups setObject:[NSMutableArray arrayWithObject:@"*"] forKey:groupName];
455
                            }
456
                        }
457
                        if (!groups.count) {
458
                            [groups setObject:[NSArray arrayWithObject:@""] forKey:@"group"];
459
                        }
460
                    }
461
                } else {
462
                    [groups addEntriesFromDictionary:translatedGroups];
463
                }
464
            } else {
465
                [groups setObject:[NSArray arrayWithObject:@""] forKey:@"group"];
466
            }
467
            
468
            self.applyMetadataAccountRequest = [ASIPithosAccountRequest updateAccountMetadataRequestWithPithos:pithosAccountManager.pithos
469
                                                                                                        groups:groups
470
                                                                                                      metadata:pithosAccount.metadata
471
                                                                                                        update:NO];
472
            applyMetadataAccountRequest.delegate = self;
473
            applyMetadataAccountRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
474
            applyMetadataAccountRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
475
            applyMetadataAccountRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
476
                                                    [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
477
                                                    [NSNumber numberWithUnsignedInteger:10], @"retries", 
478
                                                    NSStringFromSelector(@selector(accountMetadataRequestFinished:)), @"didFinishSelector", 
479
                                                    NSStringFromSelector(@selector(accountMetadataRequestFailed:)), @"didFailSelector", 
480
                                                    nil];
481
            [[PithosUtilities prepareRequest:applyMetadataAccountRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
482
        }
483
    }
484
}
485

    
486
- (void)refreshInfo {
487
    @synchronized(self) {
488
        if (refreshMetadataAccountRequest == nil) {
489
            self.refreshMetadataAccountRequest = [ASIPithosAccountRequest accountMetadataRequestWithPithos:pithosAccountManager.pithos];
490
            refreshMetadataAccountRequest.delegate = self;
491
            refreshMetadataAccountRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
492
            refreshMetadataAccountRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
493
            refreshMetadataAccountRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
494
                                                      [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
495
                                                      [NSNumber numberWithUnsignedInteger:10], @"retries", 
496
                                                      NSStringFromSelector(@selector(accountMetadataRequestFinished:)), @"didFinishSelector", 
497
                                                      NSStringFromSelector(@selector(accountMetadataRequestFailed:)), @"didFailSelector", 
498
                                                      nil];
499
            if (!sharingAccount)
500
                refreshMetadataAccountRequest.downloadCache = [ASIDownloadCache sharedCache];
501
            [[PithosUtilities prepareRequest:refreshMetadataAccountRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
502
        }
503
    }
504
}
505

    
506
@end