// // PithosAccountNode.m // pithos-macos // // Copyright 2011-2013 GRNET S.A. All rights reserved. // // Redistribution and use in source and binary forms, with or // without modification, are permitted provided that the following // conditions are met: // // 1. Redistributions of source code must retain the above // copyright notice, this list of conditions and the following // disclaimer. // // 2. Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and // documentation are those of the authors and should not be // interpreted as representing official policies, either expressed // or implied, of GRNET S.A. #import "PithosSharingAccountsNode.h" #import "PithosAccountNode.h" #import "ASIPithosRequest.h" #import "ASIPithos.h" #import "ASIPithosAccount.h" #import "ASIDownloadCache.h" #import "PithosAccount.h" #import "PithosUtilities.h" #import "PithosActivityFacility.h" @implementation PithosSharingAccountsNode @synthesize sharingAccountsRequest; #pragma mark - #pragma mark Object Lifecycle - (id)initWithPithosAccountManager:(PithosAccount *)aPithosAccountManager { if ((self = [super initWithPithosAccountManager:aPithosAccountManager])) { self.sharingAccount = @""; } return self; } - (void)dealloc { [sharingAccountsRequest clearDelegatesAndCancel]; } #pragma mark - #pragma mark Actions - (void)reset { [sharingAccountsRequest clearDelegatesAndCancel]; self.sharingAccountsRequest = nil; children = nil; newChildren = nil; freshness = PithosNodeStateRefreshNeeded; forcedRefresh = YES; [self postChildrenUpdatedNotificationName]; [self children]; } #pragma mark - #pragma mark Properties - (NSString *)url { return @"@sharing accounts@"; } - (NSArray *)children { @synchronized(self) { switch (freshness) { case PithosNodeStateFresh: break; case PithosNodeStateRefreshNeeded: freshness = PithosNodeStateRefreshing; self.sharingAccountsRequest = [ASIPithosRequest listSharingAccountsRequestWithPithos:pithosAccountManager.pithos limit:0 marker:nil]; sharingAccountsRequest.delegate = self; sharingAccountsRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:); sharingAccountsRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:); sharingAccountsRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInteger:NSOperationQueuePriorityVeryHigh], @"priority", [NSNumber numberWithUnsignedInteger:10], @"retries", NSStringFromSelector(@selector(sharingAccountsRequestFinished:)), @"didFinishSelector", NSStringFromSelector(@selector(sharingAccountsRequestFailed:)), @"didFailSelector", nil]; // if (!forcedRefresh) // sharingAccountsRequest.downloadCache = [ASIDownloadCache sharedCache]; [[PithosUtilities prepareRequest:sharingAccountsRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous]; break; case PithosNodeStateRefreshing: break; case PithosNodeStateRefreshFinished: if (newChildren) { children = newChildren; newChildren = nil; } freshness = PithosNodeStateFresh; default: break; } return children; } } - (NSString *)displayName { if (displayName == nil) return @"sharing accounts"; return [displayName copy]; } #pragma mark - #pragma mark ASIHTTPRequestDelegate - (void)sharingAccountsRequestFailed:(ASIPithosRequest *)request { @autoreleasepool { NSString *message; NSError *error = [sharingAccountsRequest error]; if (error) message = [NSString stringWithFormat:@"Sharing accounts listing %@ failed: %@", sharingAccountsRequest.url, [error localizedDescription]]; else message = [NSString stringWithFormat:@"Sharing accounts listing %@ failed: (%d) %@", sharingAccountsRequest.url, sharingAccountsRequest.responseStatusCode, sharingAccountsRequest.responseStatusMessage]; dispatch_async(dispatch_get_main_queue(), ^{ [[PithosActivityFacility defaultPithosActivityFacility] startAndEndActivityWithType:PithosActivityOther message:message]; }); NSUInteger retries = [[sharingAccountsRequest.userInfo objectForKey:@"retries"] unsignedIntegerValue]; if (retries > 0) { ASIPithosRequest *newSharingAccountsRequest = (ASIPithosRequest *)[PithosUtilities copyRequest:sharingAccountsRequest]; [(NSMutableDictionary *)(newSharingAccountsRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"]; self.sharingAccountsRequest = newSharingAccountsRequest; [[PithosUtilities prepareRequest:sharingAccountsRequest priority:[[sharingAccountsRequest.userInfo objectForKey:@"priority"] integerValue]] startAsynchronous]; } else { newChildren = nil; self.sharingAccountsRequest = nil; forcedRefresh = NO; @synchronized(self) { freshness = PithosNodeStateRefreshNeeded; } } } } - (void)sharingAccountsRequestFinished:(ASIPithosRequest *)request { @autoreleasepool { DLog(@"List sharing accounts finished: %@", [sharingAccountsRequest url]); DLog(@"Cached: %d", [sharingAccountsRequest didUseCachedResponse]); if (sharingAccountsRequest.responseStatusCode == 200) { NSMutableArray *sharingAccounts = [sharingAccountsRequest.userInfo objectForKey:@"sharingAccounts"]; NSArray *someSharingAccounts = [sharingAccountsRequest sharingAccounts]; if (sharingAccounts == nil) { sharingAccounts = [NSMutableArray arrayWithArray:someSharingAccounts]; } else { [sharingAccounts addObjectsFromArray:someSharingAccounts]; } if ([someSharingAccounts count] < 10000) { if (!sharingAccountsRequest.didUseCachedResponse || ([sharingAccounts count] != [someSharingAccounts count]) || !children) { // Save new children DLog(@"using newChildren"); newChildren = [[NSMutableArray alloc] init]; NSMutableIndexSet *keptNodes = [NSMutableIndexSet indexSet]; for (ASIPithosAccount *account in sharingAccounts) { if (![account.name isEqualToString:pithosAccountManager.pithos.authUser]) { PithosAccountNode *node = [[PithosAccountNode alloc] initWithPithosAccountManager:pithosAccountManager]; node.parent = self; node.shared = shared; node.sharingAccount = account.name; node.inheritChildrenUpdatedNotificationName = inheritChildrenUpdatedNotificationName; if (children) { NSUInteger oldIndex = [children indexOfObject:node]; if (oldIndex != NSNotFound) { // Use the same pointer value, if possible node = [children objectAtIndex:oldIndex]; [keptNodes addIndex:oldIndex]; } } [newChildren addObject:node]; } } [[children objectsAtIndexes: [[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [children count])] indexesPassingTest:^(NSUInteger idx, BOOL *stop){ if ([keptNodes containsIndex:idx]) return NO; return YES; }]] makeObjectsPerformSelector:@selector(pithosNodeWillBeRemoved)]; } // Else cache was used and all results were fetched during this request, so existing children can be reused // Update user catalog even if cache was used NSMutableArray *sharingAccountsNames = [NSMutableArray arrayWithCapacity:sharingAccounts.count]; for (ASIPithosAccount *account in sharingAccounts) { [sharingAccountsNames addObject:account.name]; } [pithosAccountManager updateUserCatalogForDisplaynames:nil UUIDs:sharingAccountsNames]; self.sharingAccountsRequest = nil; forcedRefresh = NO; @synchronized(self) { freshness = PithosNodeStateRefreshFinished; } [self postChildrenUpdatedNotificationName]; } else { // Do an additional request to fetch more objects self.sharingAccountsRequest = [ASIPithosRequest listSharingAccountsRequestWithPithos:pithosAccountManager.pithos limit:0 marker:[[someSharingAccounts lastObject] name]]; sharingAccountsRequest.delegate = self; sharingAccountsRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:); sharingAccountsRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:); sharingAccountsRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInteger:NSOperationQueuePriorityVeryHigh], @"priority", [NSNumber numberWithUnsignedInteger:10], @"retries", NSStringFromSelector(@selector(sharingAccountsRequestFinished:)), @"didFinishSelector", NSStringFromSelector(@selector(sharingAccountsRequestFailed:)), @"didFailSelector", sharingAccounts, @"sharingAccounts", nil]; // if (!forcedRefresh) // sharingAccountsRequest.downloadCache = [ASIDownloadCache sharedCache]; [[PithosUtilities prepareRequest:sharingAccountsRequest priority:NSOperationQueuePriorityVeryHigh] startAsynchronous]; } } else { [self sharingAccountsRequestFailed:sharingAccountsRequest]; } } } @end