5 // Copyright 2011 GRNET S.A. All rights reserved.
7 // Redistribution and use in source and binary forms, with or
8 // without modification, are permitted provided that the following
11 // 1. Redistributions of source code must retain the above
12 // copyright notice, this list of conditions and the following
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.
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.
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.
38 #import "PithosContainerNode.h"
39 #import "PithosObjectNode.h"
40 #import "PithosSubdirNode.h"
41 #import "ASIPithosContainerRequest.h"
42 #import "ASIPithosContainer.h"
43 #import "ASIPithosObject.h"
44 #import "ASIDownloadCache.h"
46 static NSImage *sharedIcon = nil;
48 @implementation PithosContainerNode
49 @synthesize pithosContainer;
52 if (self == [PithosContainerNode class])
53 sharedIcon = [[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericHardDiskIcon)] retain];
57 #pragma mark Object Lifecycle
59 - (id)initWithPithosContainer:(ASIPithosContainer *)aPithosContainer icon:(NSImage *)anIcon {
60 if ((self = [super init])) {
61 pithosContainer = [aPithosContainer retain];
63 icon = [anIcon retain];
64 childrenUpdatedNotificationName = @"PithosContainerNodeChildrenUpdated";
69 - (id)initWithPithosContainer:(ASIPithosContainer *)aPithosContainer {
70 return [self initWithPithosContainer:aPithosContainer icon:nil];
73 - (id)initWithContainerName:(NSString *)aContainerName icon:(NSImage *)anIcon {
74 ASIPithosContainer *container = [ASIPithosContainer container];
75 container.name = aContainerName;
76 return [self initWithPithosContainer:container icon:anIcon];
79 - (id)initWithContainerName:(NSString *)aContainerName {
80 return [self initWithContainerName:aContainerName icon:nil];
84 [containerRequest clearDelegatesAndCancel];
85 [containerRequest release];
86 [childrenUpdatedNotificationName release];
89 [pithosContainer release];
94 #pragma mark ASIHTTPRequestDelegate
96 - (void)requestFinished:(ASIHTTPRequest *)request {
97 NSLog(@"URL: %@", [containerRequest url]);
98 NSLog(@"cached: %d", [containerRequest didUseCachedResponse]);
100 NSArray *someObjects = [containerRequest objects];
101 if (objects == nil) {
102 objects = [[NSMutableArray alloc] initWithArray:someObjects];
104 [objects addObjectsFromArray:someObjects];
106 if ([someObjects count] < 10000) {
107 if (!containerRequest.didUseCachedResponse || ([objects count] != [someObjects count]) || !children) {
109 NSLog(@"using newChildren");
110 newChildren = [[NSMutableArray alloc] init];
111 for (ASIPithosObject *object in objects) {
113 PithosSubdirNode *node = [[[PithosSubdirNode alloc] initWithPithosContainer:pithosContainer pithosObject:object] autorelease];
115 NSUInteger oldIndex = [children indexOfObject:node];
116 if (oldIndex != NSNotFound) {
117 // Use the same pointer value, if possible
118 node = [children objectAtIndex:oldIndex];
119 node.pithosContainer = pithosContainer;
120 node.pithosObject = object;
123 [newChildren addObject:node];
124 } else if (([self class] != [PithosSubdirNode class]) || (![((PithosSubdirNode *)self).pithosObject.name isEqualToString:object.name])) {
125 // XXX the if above removes false objects due to trailing slash
126 // XXX this will change in the server, but it is fixed in the client for now
127 PithosObjectNode *node = [[[PithosObjectNode alloc] initWithPithosContainer:pithosContainer pithosObject:object] autorelease];
129 NSUInteger oldIndex = [children indexOfObject:node];
130 if (oldIndex != NSNotFound) {
131 // Use the same pointer value, if possible
132 node = [children objectAtIndex:oldIndex];
133 node.pithosContainer = pithosContainer;
134 node.pithosObject = object;
137 [newChildren addObject:node];
141 // Else cache was used and all results were fetched during this request, so existing children can be reused
142 [containerRequest release];
143 containerRequest = nil;
146 // XXX sort children based on preferences
147 @synchronized(self) {
148 freshness = PithosNodeStateRefreshFinished;
150 // Notify observers that children are updated
151 [[NSNotificationCenter defaultCenter] postNotificationName:childrenUpdatedNotificationName object:self];
153 [containerRequest release];
154 // Do an additional request to fetch more objects
155 containerRequest = [[ASIPithosContainerRequest listObjectsRequestWithContainerName:pithosContainer.name
157 marker:[[someObjects lastObject] name]
164 containerRequest.delegate = self;
165 containerRequest.downloadCache = [ASIDownloadCache sharedCache];
166 [containerRequest startAsynchronous];
170 - (void)requestFailed:(ASIHTTPRequest *)request {
171 // XXX do something on error, cleanup
172 NSLog(@"error:%@", [containerRequest error]);
173 [newChildren release];
175 [containerRequest release];
176 containerRequest = nil;
179 @synchronized(self) {
180 freshness = PithosNodeStateRefreshNeeded;
185 #pragma mark Properties
189 url = [[NSString alloc] initWithFormat:@"%@/%@", [ASIPithosRequest storageURL], pithosContainer.name];
193 - (NSArray *)children {
194 @synchronized(self) {
196 case PithosNodeStateFresh:
198 case PithosNodeStateRefreshNeeded:
199 freshness = PithosNodeStateRefreshing;
200 containerRequest = [[ASIPithosContainerRequest listObjectsRequestWithContainerName:pithosContainer.name
209 containerRequest.delegate = self;
210 containerRequest.downloadCache = [ASIDownloadCache sharedCache];
211 [containerRequest startAsynchronous];
213 case PithosNodeStateRefreshing:
215 case PithosNodeStateRefreshFinished:
218 children = newChildren;
221 freshness = PithosNodeStateFresh;
229 - (NSString *)displayName {
230 return [[pithosContainer.name copy] autorelease];
239 - (void)setIcon:(NSImage *)anIcon {
241 icon = [anIcon retain];