Statistics
| Branch: | Tag: | Revision:

root / pithos-macos / PithosAccountNode.m @ baaf1397

History | View | Annotate | Download (26.8 kB)

1
//
2
//  PithosAccountNode.m
3
//  pithos-macos
4
//
5
// Copyright 2011-2012 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 pithos, 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
- (id)initWithPithosAccountManager:(PithosAccount *)aPithosAccountManager andPithos:(ASIPithos *)aPithos {
63
    if ((self = [super initWithPithosAccountManager:aPithosAccountManager])) {
64
        pithos = aPithos;
65
    }
66
    return self;
67
}
68

    
69
- (void)dealloc {
70
    [accountRequest clearDelegatesAndCancel];
71
    [refreshMetadataAccountRequest clearDelegatesAndCancel];
72
    [applyMetadataAccountRequest clearDelegatesAndCancel];
73
}
74

    
75
#pragma mark -
76
#pragma mark Internal
77

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

    
106
#pragma mark -
107
#pragma mark Properties
108

    
109
- (void)setPithos:(ASIPithos *)aPithos {
110
    if (aPithos && ![aPithos isEqualTo:pithos]) {
111
        pithos = aPithos;
112
        url = nil;
113
        [accountRequest clearDelegatesAndCancel];
114
        self.accountRequest = nil;
115
        [refreshMetadataAccountRequest clearDelegatesAndCancel];
116
        self.refreshMetadataAccountRequest = nil;
117
        [applyMetadataAccountRequest clearDelegatesAndCancel];
118
        self.applyMetadataAccountRequest = nil;
119
        reset = YES;
120
    }
121
}
122

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

    
130
- (NSString *)url {
131
    if (url == nil)
132
        url = [[NSString alloc] initWithFormat:@"%@%@", 
133
               (sharingAccount ? [pithos storageURLWithAuthUser:sharingAccount] : pithos.storageURL),
134
               (shared ? @"?shared" : @"")];
135
    return url;
136
}
137

    
138
- (NSArray *)children {
139
    @synchronized(self) {
140
        if (reset) {
141
            [accountRequest clearDelegatesAndCancel];
142
            self.accountRequest = nil;
143
            [refreshMetadataAccountRequest clearDelegatesAndCancel];
144
            self.refreshMetadataAccountRequest = nil;
145
            [applyMetadataAccountRequest clearDelegatesAndCancel];
146
            self.applyMetadataAccountRequest = nil;
147
            children = nil;
148
            newChildren = nil;
149
            self.pithosAccount = nil;
150
            freshness = PithosNodeStateRefreshNeeded;
151
            forcedRefresh = YES;
152
            reset = NO;
153
            [self postChildrenUpdatedNotificationName];
154
        }
155
        switch (freshness) {
156
            case PithosNodeStateFresh:
157
                break;
158
            case PithosNodeStateRefreshNeeded:
159
                freshness = PithosNodeStateRefreshing;
160
                self.accountRequest = [ASIPithosAccountRequest listContainersRequestWithPithos:pithos
161
                                                                                         limit:0
162
                                                                                        marker:nil
163
                                                                                        shared:shared
164
                                                                                         until:nil];
165
                if (sharingAccount)
166
                    [accountRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithos];
167
                else if (!forcedRefresh)
168
                    accountRequest.downloadCache = [ASIDownloadCache sharedCache];
169
                accountRequest.delegate = self;
170
                accountRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
171
                accountRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
172
                accountRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
173
                                           [NSNumber numberWithInteger:NSOperationQueuePriorityVeryHigh], @"priority", 
174
                                           [NSNumber numberWithUnsignedInteger:10], @"retries", 
175
                                           NSStringFromSelector(@selector(accountRequestFinished:)), @"didFinishSelector", 
176
                                           NSStringFromSelector(@selector(accountRequestFailed:)), @"didFailSelector", 
177
                                           nil];
178
                [[PithosUtilities prepareRequest:accountRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous];
179
                break;
180
            case PithosNodeStateRefreshing:
181
                break;
182
            case PithosNodeStateRefreshFinished:
183
                if (newChildren) {
184
                    children = newChildren;
185
                    newChildren = nil;
186
                }
187
                freshness = PithosNodeStateFresh;
188
            default:
189
                break;
190
        }
191
        return children;
192
    }
193
}
194

    
195
- (NSString *)displayName {
196
    if (displayName == nil) {
197
        if (!sharingAccount) {
198
            return @"account";
199
        } else if (pithosAccountManager) {
200
            return [pithosAccountManager displaynameForUUID:sharingAccount safe:YES];
201
        } else {
202
            return [sharingAccount copy];
203
        }
204
    }
205
    return [displayName copy];
206
}
207

    
208
- (NSImage *)icon {
209
    if (icon == nil)
210
        icon = sharedIcon;
211
    return icon;
212
}
213

    
214
#pragma mark -
215
#pragma mark ASIHTTPRequestDelegate
216

    
217
- (void)accountRequestFailed:(ASIPithosAccountRequest *)request {
218
    @autoreleasepool {
219
        NSString *message;
220
        NSError *error = [accountRequest error];
221
        if (error)
222
            message = [NSString stringWithFormat:@"Account listing %@ failed: %@", accountRequest.url, [error localizedDescription]];
223
        else
224
            message = [NSString stringWithFormat:@"Account listing %@ failed: (%d) %@", 
225
                       accountRequest.url, accountRequest.responseStatusCode, accountRequest.responseStatusMessage];
226
        dispatch_async(dispatch_get_main_queue(), ^{
227
            [[PithosActivityFacility defaultPithosActivityFacility] startAndEndActivityWithType:PithosActivityOther message:message];
228
        });
229
        NSUInteger retries = [[accountRequest.userInfo objectForKey:@"retries"] unsignedIntegerValue];
230
        if (retries > 0) {
231
            ASIPithosAccountRequest *newAccountRequest = (ASIPithosAccountRequest *)[PithosUtilities copyRequest:accountRequest];
232
            [(NSMutableDictionary *)(newAccountRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
233
            self.accountRequest = newAccountRequest;
234
            [[PithosUtilities prepareRequest:accountRequest priority:[[accountRequest.userInfo objectForKey:@"priority"] integerValue]] startAsynchronous];
235
        } else {
236
            newChildren = nil;
237
            self.accountRequest = nil;
238
            forcedRefresh = NO;
239
            @synchronized(self) {
240
                freshness = PithosNodeStateRefreshNeeded;
241
            }
242
        }
243
    }
244
}
245

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

    
337
- (void)accountMetadataRequestFinished:(ASIPithosAccountRequest *)request {
338
    @autoreleasepool {
339
        DLog(@"URL: %@", [request url]);
340
        DLog(@"cached: %d", [request didUseCachedResponse]);
341
        
342
        if ([request isEqualTo:applyMetadataAccountRequest]) {
343
            @synchronized(self) {
344
                self.applyMetadataAccountRequest = nil;
345
            }
346
            [self refreshInfo];
347
        } else if ([request isEqualTo:refreshMetadataAccountRequest]) {
348
            self.pithosAccount = [refreshMetadataAccountRequest account];
349
            @synchronized(self) {
350
                self.refreshMetadataAccountRequest = nil;
351
            }
352
        }
353
    }
354
}
355

    
356
- (void)accountMetadataRequestFailed:(ASIPithosAccountRequest *)request {
357
    @autoreleasepool {
358
        NSUInteger retries = [[request.userInfo objectForKey:@"retries"] unsignedIntegerValue];
359
        if (retries > 0) {
360
            ASIPithosAccountRequest *newRequest = (ASIPithosAccountRequest *)[PithosUtilities copyRequest:request];
361
            [(NSMutableDictionary *)(newRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
362
            if ([request isEqualTo:applyMetadataAccountRequest]) {
363
                @synchronized(self) {
364
                    self.applyMetadataAccountRequest = newRequest;
365
                }
366
            } else if ([request isEqualTo:refreshMetadataAccountRequest]) {
367
                @synchronized(self) {
368
                    self.refreshMetadataAccountRequest = newRequest;
369
                }
370
            }
371
            [[PithosUtilities prepareRequest:newRequest priority:[[newRequest.userInfo objectForKey:@"priority"] integerValue]] startAsynchronous];
372
        } else {
373
            if ([request isEqualTo:applyMetadataAccountRequest]) {
374
                [PithosUtilities httpRequestErrorAlertWithRequest:applyMetadataAccountRequest];
375
                @synchronized(self) {
376
                    self.applyMetadataAccountRequest = nil;
377
                }
378
            } else if ([request isEqualTo:refreshMetadataAccountRequest]) {
379
                [PithosUtilities httpRequestErrorAlertWithRequest:refreshMetadataAccountRequest];
380
                @synchronized(self) {
381
                    self.refreshMetadataAccountRequest = nil;
382
                }
383
            }
384
        }
385
    }
386
}
387

    
388
#pragma mark -
389
#pragma mark Info
390

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

    
506
- (void)refreshInfo {
507
    @synchronized(self) {
508
        if (refreshMetadataAccountRequest == nil) {
509
            self.refreshMetadataAccountRequest = [ASIPithosAccountRequest accountMetadataRequestWithPithos:pithos];
510
            refreshMetadataAccountRequest.delegate = self;
511
            refreshMetadataAccountRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
512
            refreshMetadataAccountRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
513
            refreshMetadataAccountRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
514
                                                      [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
515
                                                      [NSNumber numberWithUnsignedInteger:10], @"retries", 
516
                                                      NSStringFromSelector(@selector(accountMetadataRequestFinished:)), @"didFinishSelector", 
517
                                                      NSStringFromSelector(@selector(accountMetadataRequestFailed:)), @"didFailSelector", 
518
                                                      nil];
519
            if (!sharingAccount)
520
                refreshMetadataAccountRequest.downloadCache = [ASIDownloadCache sharedCache];
521
            [[PithosUtilities prepareRequest:refreshMetadataAccountRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
522
        }
523
    }
524
}
525

    
526
@end