Statistics
| Branch: | Tag: | Revision:

root / pithos-macos / PithosObjectNode.m @ 6d9d5dce

History | View | Annotate | Download (27 kB)

1
//
2
//  PithosObjectNode.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 "PithosObjectNode.h"
39
#import "ASIPithosRequest.h"
40
#import "ASIPithos.h"
41
#import "ASIPithosObjectRequest.h"
42
#import "ASIPithosContainer.h"
43
#import "ASIPithosObject.h"
44
#import "ASIPithosSharingUser.h"
45
#import "ASIDownloadCache.h"
46
#import "PithosAccount.h"
47
#import "PithosUtilities.h"
48
#import "PithosObjectNodeInfoController.h"
49

    
50
@implementation PithosObjectNode
51
@synthesize pithosContainer, pithosObject, versions, applyMetadataObjectRequest, refreshMetadataObjectRequest, refreshVersionsObjectRequest;
52
@synthesize isPublic, translatedModifiedBy, translatedPermissions;
53

    
54
#pragma mark -
55
#pragma mark Object Lifecycle
56

    
57
- (id)initWithPithosAccountManager:(PithosAccount *)aPithosAccountManager
58
                   pithosContainer:(ASIPithosContainer *)aPithosContainer
59
                      pithosObject:(ASIPithosObject *)aPithosObject {
60
    if ((self = [super initWithPithosAccountManager:aPithosAccountManager])) {
61
        isLeafItem = YES;
62
        self.pithosContainer = aPithosContainer;
63
        self.pithosObject = aPithosObject;
64
    }
65
    return self;
66
}
67

    
68
- (void)dealloc {
69
    [refreshVersionsObjectRequest clearDelegatesAndCancel];
70
    [refreshMetadataObjectRequest clearDelegatesAndCancel];
71
    [applyMetadataObjectRequest clearDelegatesAndCancel];
72
}
73

    
74
#pragma mark -
75
#pragma mark Internal
76

    
77
- (void)updateModifiedBy {
78
    if (!pithosObject.modifiedBy) {
79
        self.translatedModifiedBy = nil;
80
    } else if (pithosAccountManager) {
81
        NSString *displayname = [pithosAccountManager displaynameForUUID:pithosObject.modifiedBy safe:NO];
82
        if (displayname) {
83
            self.translatedModifiedBy = displayname;
84
        } else {
85
            [pithosAccountManager updateUserCatalogForDisplaynames:nil UUIDs:[NSArray arrayWithObject:pithosObject.modifiedBy]];
86
            self.translatedModifiedBy = [pithosAccountManager displaynameForUUID:pithosObject.modifiedBy safe:YES];
87
        }
88
    } else {
89
        self.translatedModifiedBy = [pithosObject.modifiedBy copy];
90
    }
91
}
92

    
93
- (void)updatePermissions {
94
    if (!pithosObject) {
95
        self.translatedPermissions = [NSMutableArray array];
96
    } else if (pithosAccountManager) {
97
        NSMutableSet *UUIDs = [NSMutableSet set];
98
        for (ASIPithosSharingUser *sharingUser in pithosObject.permissions) {
99
            [UUIDs addObject:sharingUser.name];
100
        }
101
        [UUIDs removeObject:@""];
102
        [UUIDs removeObject:@"*"];
103
        if (UUIDs.count) {
104
            [pithosAccountManager updateUserCatalogForDisplaynames:nil UUIDs:[UUIDs allObjects]];
105
        }
106
        
107
        NSMutableArray *newTranslatedPermissions = [NSMutableArray arrayWithCapacity:pithosObject.permissions.count];
108
        for (ASIPithosSharingUser *sharingUser in pithosObject.permissions) {
109
            ASIPithosSharingUser *translatedSharingUser = [sharingUser copy];
110
            translatedSharingUser.name = [pithosAccountManager displaynameForUUID:translatedSharingUser.name safe:YES];
111
            [newTranslatedPermissions addObject:translatedSharingUser];
112
        }
113
        self.translatedPermissions = newTranslatedPermissions;
114
    } else {
115
        self.translatedPermissions = [NSMutableArray arrayWithArray:[pithosObject.permissions copy]];
116
    }
117
}
118

    
119
#pragma mark -
120
#pragma mark Properties
121

    
122
- (NSString *)url {
123
    return [NSString stringWithFormat:@"@object@%@/%@/%@%@",
124
            (sharingAccount ? sharingAccount : pithosAccountManager.pithos.authUser),
125
            pithosContainer.name,
126
            pithosObject.name,
127
            (shared ? @"?shared" : @"")];
128
}
129

    
130
- (NSArray *)children {
131
    return nil;
132
}
133

    
134
- (NSString *)displayName {
135
    if (displayName == nil) {
136
        displayName = [pithosObject.name lastPathComponent];
137
        if([pithosObject.name hasSuffix:@"/"])
138
            displayName = [displayName stringByAppendingString:@"/"];
139
    }
140
    return [displayName copy];
141
}
142

    
143
- (void)setDisplayName:(NSString *)aDisplayName {    
144
}
145

    
146
- (NSImage *)icon {
147
    if (icon == nil)
148
        icon = [[NSWorkspace sharedWorkspace] iconForFileType:[pithosObject.name pathExtension]];
149
    return icon;
150
}
151

    
152
- (void)setPithosObject:(ASIPithosObject *)aPithosObject {
153
    if (![pithosObject isEqualTo:aPithosObject]) {
154
        pithosObject = aPithosObject;
155
        [self updateModifiedBy];
156
        [self updatePermissions];
157
    }
158
    self.isPublic = (pithosObject.publicURI != nil);
159
    // Refresh browser if the object is in my shared and is no longer shared
160
    if (shared && !pithosObject.sharing)
161
        [[NSNotificationCenter defaultCenter] postNotificationName:@"PithosBrowserRefreshNeeded" object:self];
162
}
163

    
164
- (void)setLimitedPithosObject:(ASIPithosObject *)aPithosObject {
165
    if (![pithosObject isEqualTo:aPithosObject]) {
166
        self.pithosObject.subdir = aPithosObject.subdir;
167
        self.pithosObject.name = aPithosObject.name;
168
        self.pithosObject.hash = aPithosObject.hash;
169
        self.pithosObject.objectHash = aPithosObject.objectHash;
170
        self.pithosObject.UUID = aPithosObject.UUID;
171
        self.pithosObject.bytes = aPithosObject.bytes;
172
        self.pithosObject.contentType = aPithosObject.contentType;
173
        self.pithosObject.lastModified = aPithosObject.lastModified;
174
        self.pithosObject.version = aPithosObject.version;
175
        self.pithosObject.versionTimestamp = aPithosObject.versionTimestamp;
176
        self.pithosObject.modifiedBy = aPithosObject.modifiedBy;
177
        self.pithosObject.sharedBy = aPithosObject.sharedBy;
178
        self.pithosObject.allowedTo = aPithosObject.allowedTo;
179
        if (!pithosNodeInfoController) {
180
            self.pithosObject.sharing = aPithosObject.sharing;
181
            self.pithosObject.publicURI = aPithosObject.publicURI;
182
            self.pithosObject = pithosObject;
183
            [self updatePermissions];
184
        } else {
185
            [self updateModifiedBy];
186
        }
187
    }
188
}
189

    
190
#pragma mark -
191
#pragma mark ASIHTTPRequestDelegate
192

    
193
- (void)objectRequestFinished:(ASIPithosObjectRequest *)request {
194
    @autoreleasepool {
195
        DLog(@"URL: %@", [request url]);
196
        DLog(@"cached: %d", [request didUseCachedResponse]);
197
        
198
        if ([request isEqualTo:applyMetadataObjectRequest]) {
199
            int responseStatusCode = applyMetadataObjectRequest.responseStatusCode;
200
            if (responseStatusCode != 202)
201
                [PithosUtilities unexpectedResponseStatusAlertWithRequest:applyMetadataObjectRequest];
202
            @synchronized(self) {
203
                self.applyMetadataObjectRequest = nil;
204
            }
205
            if (responseStatusCode == 202)
206
                [self refreshInfo];
207
        } else if ([request isEqualTo:refreshMetadataObjectRequest]) {
208
            [[pithosNodeInfoController window] makeFirstResponder:nil];
209
            self.pithosObject = [refreshMetadataObjectRequest object];
210
            @synchronized(self) {
211
                self.refreshMetadataObjectRequest = nil;
212
            }
213
        } else if ([request isEqualTo:refreshVersionsObjectRequest]) {
214
            [[pithosNodeInfoController window] makeFirstResponder:nil];
215
            self.versions = [refreshVersionsObjectRequest versions];
216
            @synchronized(self) {
217
                self.refreshVersionsObjectRequest = nil;
218
            }
219
        }
220
    }
221
}
222

    
223
- (void)objectRequestFailed:(ASIPithosObjectRequest *)request {
224
    @autoreleasepool {
225
        NSUInteger retries = [[request.userInfo objectForKey:@"retries"] unsignedIntegerValue];
226
        if (retries > 0) {
227
            ASIPithosObjectRequest *newRequest = (ASIPithosObjectRequest *)[PithosUtilities retryWithUpdatedURLRequest:request
228
                                                                                               andPithosAccountManager:pithosAccountManager];
229
            [(NSMutableDictionary *)(newRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
230
            if ([request isEqualTo:applyMetadataObjectRequest]) {
231
                @synchronized(self) {
232
                    self.applyMetadataObjectRequest = newRequest;
233
                }
234
            } else if ([request isEqualTo:refreshMetadataObjectRequest]) {
235
                @synchronized(self) {
236
                    self.refreshMetadataObjectRequest = newRequest;
237
                }
238
            } else if ([request isEqualTo:refreshVersionsObjectRequest]) {
239
                @synchronized(self) {
240
                    self.refreshVersionsObjectRequest = newRequest;
241
                }
242
            }
243
            [[PithosUtilities prepareRequest:newRequest priority:[[newRequest.userInfo objectForKey:@"priority"] integerValue]] startAsynchronous];
244
        } else {
245
            if ([request isEqualTo:applyMetadataObjectRequest]) {
246
                [PithosUtilities httpRequestErrorAlertWithRequest:applyMetadataObjectRequest];
247
                @synchronized(self) {
248
                    self.applyMetadataObjectRequest = nil;
249
                }
250
            } else if ([request isEqualTo:refreshMetadataObjectRequest]) {
251
                [PithosUtilities httpRequestErrorAlertWithRequest:refreshMetadataObjectRequest];
252
                @synchronized(self) {
253
                    self.refreshMetadataObjectRequest = nil;
254
                }
255
            } else if ([request isEqualTo:refreshVersionsObjectRequest]) {
256
                [PithosUtilities httpRequestErrorAlertWithRequest:refreshVersionsObjectRequest];
257
                @synchronized(self) {
258
                    self.refreshVersionsObjectRequest = nil;
259
                }
260
            }
261
        }
262
    }
263
}
264

    
265
#pragma mark -
266
#pragma mark Info
267

    
268
- (void)applyInfo {
269
    @synchronized(self) {
270
        if (applyMetadataObjectRequest == nil) {
271
            [[pithosNodeInfoController window] makeFirstResponder:nil];
272
            if (sharingAccount) {
273
                self.applyMetadataObjectRequest = [ASIPithosObjectRequest updateObjectMetadataRequestWithPithos:pithosAccountManager.pithos
274
                                                                                                  containerName:pithosContainer.name
275
                                                                                                     objectName:pithosObject.name
276
                                                                                                contentEncoding:nil
277
                                                                                             contentDisposition:nil
278
                                                                                                       manifest:nil
279
                                                                                                        sharing:nil
280
                                                                                                       isPublic:(isPublic ? ASIPithosObjectRequestPublicTrue : ASIPithosObjectRequestPublicFalse)
281
                                                                                                       metadata:pithosObject.metadata
282
                                                                                                         update:NO];
283
                [applyMetadataObjectRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithosAccountManager.pithos];
284
            } else {
285
                NSMutableArray *permissions = [NSMutableArray array];
286
                if (translatedPermissions.count) {
287
                    for (ASIPithosSharingUser *translatedsSharingUser in translatedPermissions) {
288
                        if (translatedsSharingUser.group.length &&
289
                            [translatedsSharingUser.group rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@" -_~,;"]].location != NSNotFound) {
290
                            NSAlert *alert = [[NSAlert alloc] init];
291
                            [alert setMessageText:@"Invalid Input"];
292
                            [alert setInformativeText:@"Group names cannot contain ' ', '-', '_', '~', ',' or ';'."];
293
                            [alert addButtonWithTitle:@"OK"];
294
                            [alert runModal];
295
                            return;
296
                        }
297
                    }
298
                    if (pithosAccountManager) {
299
                        NSMutableSet *allUsers = [NSMutableSet set];
300
                        for (ASIPithosSharingUser *translatedsSharingUser in translatedPermissions) {
301
                            if (translatedsSharingUser.name.length) {
302
                                [allUsers addObject:translatedsSharingUser.name];
303
                            }
304
                        }
305
                        [allUsers removeObject:@""];
306
                        [allUsers removeObject:@"*"];
307
                        if (allUsers.count) {
308
                            ASIPithosRequest *userCatalogRequest = [pithosAccountManager updateUserCatalogForDisplaynames:[allUsers allObjects]
309
                                                                                                                       UUIDs:nil];
310
                            if (userCatalogRequest.error || ((userCatalogRequest.responseStatusCode != 200) && (userCatalogRequest.responseStatusCode != 404))) {
311
                                return;
312
                            } else if (userCatalogRequest.responseStatusCode == 200) {
313
                                // Check if all users exist.
314
                                NSDictionary *displaynameCatalog = [userCatalogRequest displaynameCatalog];
315
                                NSMutableArray *inexistentUsers = [NSMutableArray array];
316
                                for (NSString *user in allUsers) {
317
                                    if (![displaynameCatalog objectForKey:user]) {
318
                                        [inexistentUsers addObject:user];
319
                                    }
320
                                }
321
                                if (!inexistentUsers.count) {
322
                                    // Create permissions.
323
                                    for (ASIPithosSharingUser *translatedsSharingUser in translatedPermissions) {
324
                                        if (translatedsSharingUser.name.length) {
325
                                            ASIPithosSharingUser *sharingUser = [translatedsSharingUser copy];
326
                                            if (![sharingUser.name isEqualToString:@"*"]) {
327
                                                sharingUser.name = [displaynameCatalog objectForKey:sharingUser.name];
328
                                            }
329
                                            if (!sharingUser.permission) {
330
                                                sharingUser.permission = @"read";
331
                                            }
332
                                            [permissions addObject:sharingUser];
333
                                        }
334
                                    }
335
                                } else {
336
                                    NSAlert *alert = [[NSAlert alloc] init];
337
                                    if (inexistentUsers.count == 1) {
338
                                        [alert setMessageText:@"Invalid User"];
339
                                        [alert setInformativeText:[NSString stringWithFormat:@"User '%@' doesn't exist.", [inexistentUsers objectAtIndex:0]]];
340
                                    } else {
341
                                        [alert setMessageText:@"Invalid Users"];
342
                                        [alert setInformativeText:[NSString stringWithFormat:@"Users '%@' don't exist.", [inexistentUsers componentsJoinedByString:@"', '"]]];
343
                                    }
344
                                    [alert addButtonWithTitle:@"OK"];
345
                                    [alert runModal];
346
                                    return;
347
                                }
348
                            } else {
349
                                // 404. Since we don't translate to UUIDs, check for invalid chars.
350
                                BOOL valid = YES;
351
                                // Create permissions.
352
                                for (ASIPithosSharingUser *translatedsSharingUser in translatedPermissions) {
353
                                    if (translatedsSharingUser.name.length &&
354
                                        ([translatedsSharingUser.name rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@" ~,;:"]].location != NSNotFound)) {
355
                                        valid = NO;
356
                                        break;
357
                                    }
358
                                }
359
                                if (valid) {
360
                                    for (ASIPithosSharingUser *translatedsSharingUser in translatedPermissions) {
361
                                        if (translatedsSharingUser.name.length) {
362
                                            ASIPithosSharingUser *sharingUser = [translatedsSharingUser copy];
363
                                            if (!sharingUser.permission) {
364
                                                sharingUser.permission = @"read";
365
                                            }                                            
366
                                            [permissions addObject:sharingUser];
367
                                        }
368
                                    }
369
                                } else {
370
                                    NSAlert *alert = [[NSAlert alloc] init];
371
                                    [alert setMessageText:@"Invalid Input"];
372
                                    [alert setInformativeText:@"Users cannot contain ' ', '~', ',', ';' or ':'."];
373
                                    [alert addButtonWithTitle:@"OK"];
374
                                    [alert runModal];
375
                                    return;
376
                                }
377
                            }
378
                        } else {
379
                            for (ASIPithosSharingUser *translatedsSharingUser in translatedPermissions) {
380
                                if ([translatedsSharingUser.name isEqualToString:@"*"]) {
381
                                    ASIPithosSharingUser *sharingUser = [translatedsSharingUser copy];
382
                                    if (!sharingUser.permission) {
383
                                        sharingUser.permission = @"read";
384
                                    }
385
                                    [permissions addObject:sharingUser];
386
                                }
387
                            }
388
                        }
389
                    } else {
390
                        for (ASIPithosSharingUser *translatedsSharingUser in translatedPermissions) {
391
                            if (translatedsSharingUser.name.length) {
392
                                ASIPithosSharingUser *sharingUser = [translatedsSharingUser copy];
393
                                if (!sharingUser.permission) {
394
                                    sharingUser.permission = @"read";
395
                                }
396
                                [permissions addObject:sharingUser];
397
                            }
398
                        }
399
                    }
400
                }
401
                pithosObject.permissions = permissions;
402
            
403
                self.applyMetadataObjectRequest = [ASIPithosObjectRequest updateObjectMetadataRequestWithPithos:pithosAccountManager.pithos
404
                                                                                                  containerName:pithosContainer.name
405
                                                                                                     objectName:pithosObject.name
406
                                                                                                contentEncoding:pithosObject.contentEncoding
407
                                                                                             contentDisposition:pithosObject.contentDisposition
408
                                                                                                       manifest:pithosObject.manifest
409
                                                                                                        sharing:(pithosObject.sharing ? pithosObject.sharing : @"")
410
                                                                                                       isPublic:(isPublic ? ASIPithosObjectRequestPublicTrue : ASIPithosObjectRequestPublicFalse)
411
                                                                                                       metadata:pithosObject.metadata
412
                                                                                                         update:NO];
413
            }
414
            applyMetadataObjectRequest.delegate = self;
415
            applyMetadataObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
416
            applyMetadataObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
417
            applyMetadataObjectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
418
                                                   [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
419
                                                   [NSNumber numberWithUnsignedInteger:10], @"retries", 
420
                                                   NSStringFromSelector(@selector(objectRequestFinished:)), @"didFinishSelector", 
421
                                                   NSStringFromSelector(@selector(objectRequestFailed:)), @"didFailSelector", 
422
                                                   nil];
423
            [[PithosUtilities prepareRequest:applyMetadataObjectRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
424
        }
425
    }
426
}
427

    
428
- (void)refreshInfo {
429
    @synchronized(self) {
430
        if (refreshMetadataObjectRequest == nil) {
431
            self.refreshMetadataObjectRequest = [ASIPithosObjectRequest objectMetadataRequestWithPithos:pithosAccountManager.pithos
432
                                                                                          containerName:pithosContainer.name
433
                                                                                             objectName:pithosObject.name];
434
            if (sharingAccount)
435
                [refreshMetadataObjectRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithosAccountManager.pithos];
436
            refreshMetadataObjectRequest.delegate = self;
437
            refreshMetadataObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
438
            refreshMetadataObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
439
            refreshMetadataObjectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
440
                                                     [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
441
                                                     [NSNumber numberWithUnsignedInteger:10], @"retries", 
442
                                                     NSStringFromSelector(@selector(objectRequestFinished:)), @"didFinishSelector", 
443
                                                     NSStringFromSelector(@selector(objectRequestFailed:)), @"didFailSelector", 
444
                                                     nil];
445
            if (!sharingAccount)
446
                refreshMetadataObjectRequest.downloadCache = [ASIDownloadCache sharedCache];
447
            [[PithosUtilities prepareRequest:refreshMetadataObjectRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
448
        }
449
    }
450
    [self refreshVersions];
451
}
452

    
453
#pragma mark -
454
#pragma mark Versions
455

    
456
- (void)refreshVersions {
457
    @synchronized(self) {
458
        if (refreshVersionsObjectRequest == nil) {
459
            self.refreshVersionsObjectRequest = [ASIPithosObjectRequest objectVersionsRequestWithPithos:pithosAccountManager.pithos
460
                                                                                          containerName:pithosContainer.name
461
                                                                                             objectName:pithosObject.name];
462
            if (sharingAccount)
463
                [refreshVersionsObjectRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithosAccountManager.pithos];
464
            refreshVersionsObjectRequest.delegate = self;
465
            refreshVersionsObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
466
            refreshVersionsObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
467
            refreshVersionsObjectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
468
                                                     [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
469
                                                     [NSNumber numberWithUnsignedInteger:10], @"retries", 
470
                                                     NSStringFromSelector(@selector(objectRequestFinished:)), @"didFinishSelector", 
471
                                                     NSStringFromSelector(@selector(objectRequestFailed:)), @"didFailSelector", 
472
                                                     nil];
473
            if (!sharingAccount)
474
                refreshVersionsObjectRequest.downloadCache = [ASIDownloadCache sharedCache];
475
            [[PithosUtilities prepareRequest:refreshVersionsObjectRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
476
        }
477
    }
478
}
479

    
480
#pragma mark -
481
#pragma mark Actions
482

    
483
- (void)showPithosNodeInfo:(id)sender {
484
    if (!pithosNodeInfoController) {
485
        pithosNodeInfoController = [[PithosObjectNodeInfoController alloc] initWithPithosNode:self];
486
        [self refreshInfo];
487
    }
488
    [pithosNodeInfoController showWindow:sender];
489
    [[pithosNodeInfoController window] makeKeyAndOrderFront:sender];
490
    [NSApp activateIgnoringOtherApps:YES];
491
}
492

    
493
@end