Do not use the shared cache in sharing account requests.
[pithos-macos] / pithos-macos / PithosObjectNode.m
1 //
2 //  PithosObjectNode.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 "PithosObjectNode.h"
39 #import "ASIPithosRequest.h"
40 #import "ASIPithos.h"
41 #import "ASIPithosObjectRequest.h"
42 #import "ASIPithosContainer.h"
43 #import "ASIPithosObject.h"
44 #import "ASIDownloadCache.h"
45 #import "PithosUtilities.h"
46 #import "PithosObjectNodeInfoController.h"
47
48 @implementation PithosObjectNode
49 @synthesize pithos, pithosContainer, pithosObject, versions;
50 @synthesize isPublic;
51
52 #pragma mark -
53 #pragma mark Object Lifecycle
54
55 - (id)initWithPithos:(ASIPithos *)aPithos 
56      pithosContainer:(ASIPithosContainer *)aPithosContainer 
57         pithosObject:(ASIPithosObject *)aPithosObject {
58     if ((self = [super init])) {
59         self.pithos = aPithos;
60         self.pithosContainer = aPithosContainer;
61         self.pithosObject = aPithosObject;
62         isLeafItem = YES;
63     }
64     return self;
65 }
66
67 - (void)dealloc {
68     [refreshVersionsObjectRequest clearDelegatesAndCancel];
69     [refreshVersionsObjectRequest release];
70     [refreshMetadataObjectRequest clearDelegatesAndCancel];
71     [refreshMetadataObjectRequest release];
72     [applyMetadataObjectRequest clearDelegatesAndCancel];
73     [applyMetadataObjectRequest release];
74     [versions release];
75     [pithosObject release];
76     [pithosContainer release];
77     [pithos release];
78     [super dealloc];
79 }
80
81 #pragma mark -
82 #pragma mark Properties
83
84 - (void)setPithos:(ASIPithos *)aPithos {
85     if (aPithos && ![aPithos isEqualTo:pithos]) {
86         [pithos release];
87         pithos = [aPithos retain];
88         [url release];
89         url = nil;
90     }
91 }
92
93 - (NSString *)url {
94     if (url == nil)
95         url = [[NSString alloc] initWithFormat:@"object %@/%@/%@%@", 
96                (sharingAccount ? [pithos storageURLWithAuthUser:sharingAccount] : pithos.storageURL), 
97                pithosContainer.name, 
98                pithosObject.name, 
99                (shared ? @"?shared" : @"")];
100     return url;
101 }
102
103 - (NSArray *)children {
104     return nil;
105 }
106
107 - (NSString *)displayName {
108     if (displayName == nil) {
109         displayName = [pithosObject.name lastPathComponent];
110         if([pithosObject.name hasSuffix:@"/"])
111             displayName = [displayName stringByAppendingString:@"/"];
112         [displayName retain];
113     }
114     return [[displayName copy] autorelease];
115 }
116
117 - (void)setDisplayName:(NSString *)aDisplayName {    
118 }
119
120 - (NSImage *)icon {
121     if (icon == nil)
122         icon = [[[NSWorkspace sharedWorkspace] iconForFileType:[pithosObject.name pathExtension]] retain];
123     return icon;
124 }
125
126 - (void)setPithosObject:(ASIPithosObject *)aPithosObject {
127     if (![pithosObject isEqualTo:aPithosObject]) {
128         [pithosObject release];
129         pithosObject = [aPithosObject retain];
130     }
131     self.isPublic = (pithosObject.publicURI != nil);
132     // Refresh browser if the object is in my shared and is no longer shared
133     if (shared && !pithosObject.sharing)
134         [[NSNotificationCenter defaultCenter] postNotificationName:@"PithosBrowserRefreshNeeeded" object:self];
135 }
136
137 - (void)setLimitedPithosObject:(ASIPithosObject *)aPithosObject {
138     if (![pithosObject isEqualTo:aPithosObject]) {
139         self.pithosObject.subdir = aPithosObject.subdir;
140         self.pithosObject.name = aPithosObject.name;
141         self.pithosObject.hash = aPithosObject.hash;
142         self.pithosObject.objectHash = aPithosObject.objectHash;
143         self.pithosObject.UUID = aPithosObject.UUID;
144         self.pithosObject.bytes = aPithosObject.bytes;
145         self.pithosObject.contentType = aPithosObject.contentType;
146         self.pithosObject.lastModified = aPithosObject.lastModified;
147         self.pithosObject.version = aPithosObject.version;
148         self.pithosObject.versionTimestamp = aPithosObject.versionTimestamp;
149         self.pithosObject.modifiedBy = aPithosObject.modifiedBy;
150         self.pithosObject.sharedBy = aPithosObject.sharedBy;
151         self.pithosObject.allowedTo = aPithosObject.allowedTo;
152         if (!pithosNodeInfoController) {
153             self.pithosObject.sharing = aPithosObject.sharing;
154             self.pithosObject.publicURI = aPithosObject.publicURI;
155             self.pithosObject = pithosObject;
156         }
157     }
158 }
159
160 #pragma mark -
161 #pragma mark ASIHTTPRequestDelegate
162
163 - (void)objectRequestFinished:(ASIPithosObjectRequest *)request {
164     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
165     NSLog(@"URL: %@", [request url]);
166     NSLog(@"cached: %d", [request didUseCachedResponse]);
167     
168     if ([request isEqualTo:applyMetadataObjectRequest]) {
169         int responseStatusCode = applyMetadataObjectRequest.responseStatusCode;
170         if (responseStatusCode != 202)
171             [PithosUtilities unexpectedResponseStatusAlertWithRequest:applyMetadataObjectRequest];
172         @synchronized(self) {
173             [applyMetadataObjectRequest release];
174             applyMetadataObjectRequest = nil;
175         }
176         if (responseStatusCode == 202)
177             [self refreshInfo];
178     } else if ([request isEqualTo:refreshMetadataObjectRequest]) {
179         [[pithosNodeInfoController window] makeFirstResponder:nil];
180         self.pithosObject = [refreshMetadataObjectRequest object];
181         @synchronized(self) {
182             [refreshMetadataObjectRequest release];
183             refreshMetadataObjectRequest = nil;
184         }
185     } else if ([request isEqualTo:refreshVersionsObjectRequest]) {
186         [[pithosNodeInfoController window] makeFirstResponder:nil];
187         self.versions = [refreshVersionsObjectRequest versions];
188         @synchronized(self) {
189             [refreshVersionsObjectRequest release];
190             refreshVersionsObjectRequest = nil;
191         }
192     }
193     [pool drain];
194 }
195
196 - (void)objectRequestFailed:(ASIPithosObjectRequest *)request {
197     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
198     NSUInteger retries = [[request.userInfo objectForKey:@"retries"] unsignedIntegerValue];
199     if (retries > 0) {
200         ASIPithosObjectRequest *newRequest = (ASIPithosObjectRequest *)[PithosUtilities copyRequest:request];
201         [(NSMutableDictionary *)(newRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
202         if ([request isEqualTo:applyMetadataObjectRequest]) {
203             @synchronized(self) {
204                 [applyMetadataObjectRequest release];
205                 applyMetadataObjectRequest = newRequest;
206             }
207         } else if ([request isEqualTo:refreshMetadataObjectRequest]) {
208             @synchronized(self) {
209                 [refreshMetadataObjectRequest release];
210                 refreshMetadataObjectRequest = newRequest;
211             }
212         } else if ([request isEqualTo:refreshVersionsObjectRequest]) {
213             @synchronized(self) {
214                 [refreshVersionsObjectRequest release];
215                 refreshVersionsObjectRequest = newRequest;
216             }
217         }
218         [[PithosUtilities prepareRequest:newRequest priority:[[newRequest.userInfo objectForKey:@"priority"] integerValue]] startAsynchronous];
219     } else {
220         if ([request isEqualTo:applyMetadataObjectRequest]) {
221             [PithosUtilities httpRequestErrorAlertWithRequest:applyMetadataObjectRequest];
222             @synchronized(self) {
223                 [applyMetadataObjectRequest release];
224                 applyMetadataObjectRequest = nil;
225             }
226         } else if ([request isEqualTo:refreshMetadataObjectRequest]) {
227             [PithosUtilities httpRequestErrorAlertWithRequest:refreshMetadataObjectRequest];
228             @synchronized(self) {
229                 [refreshMetadataObjectRequest release];
230                 refreshMetadataObjectRequest = nil;
231             }
232         } else if ([request isEqualTo:refreshVersionsObjectRequest]) {
233             [PithosUtilities httpRequestErrorAlertWithRequest:refreshVersionsObjectRequest];
234             @synchronized(self) {
235                 [refreshVersionsObjectRequest release];
236                 refreshVersionsObjectRequest = nil;
237             }
238         }
239     }
240     [pool drain];
241 }
242
243 #pragma mark -
244 #pragma mark Info
245
246 - (void)applyInfo {
247     @synchronized(self) {
248         if (applyMetadataObjectRequest == nil) {
249             [[pithosNodeInfoController window] makeFirstResponder:nil];
250             if (sharingAccount) {
251                 applyMetadataObjectRequest = [[ASIPithosObjectRequest updateObjectMetadataRequestWithPithos:pithos 
252                                                                                               containerName:pithosContainer.name 
253                                                                                                  objectName:pithosObject.name 
254                                                                                             contentEncoding:nil 
255                                                                                          contentDisposition:nil 
256                                                                                                    manifest:nil 
257                                                                                                     sharing:nil
258                                                                                                    isPublic:(isPublic ? ASIPithosObjectRequestPublicTrue : ASIPithosObjectRequestPublicFalse) 
259                                                                                                    metadata:pithosObject.metadata
260                                                                                                      update:NO] retain];
261                 [applyMetadataObjectRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithos];
262             } else {
263                 applyMetadataObjectRequest = [[ASIPithosObjectRequest updateObjectMetadataRequestWithPithos:pithos 
264                                                                                               containerName:pithosContainer.name 
265                                                                                                  objectName:pithosObject.name 
266                                                                                             contentEncoding:pithosObject.contentEncoding 
267                                                                                          contentDisposition:pithosObject.contentDisposition 
268                                                                                                    manifest:pithosObject.manifest 
269                                                                                                     sharing:(pithosObject.sharing ? pithosObject.sharing : @"")
270                                                                                                    isPublic:(isPublic ? ASIPithosObjectRequestPublicTrue : ASIPithosObjectRequestPublicFalse) 
271                                                                                                    metadata:pithosObject.metadata
272                                                                                                      update:NO] retain];
273             }
274             applyMetadataObjectRequest.delegate = self;
275             applyMetadataObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
276             applyMetadataObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
277             applyMetadataObjectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
278                                                    [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
279                                                    [NSNumber numberWithUnsignedInteger:10], @"retries", 
280                                                    NSStringFromSelector(@selector(objectRequestFinished:)), @"didFinishSelector", 
281                                                    NSStringFromSelector(@selector(objectRequestFailed:)), @"didFailSelector", 
282                                                    nil];
283             [[PithosUtilities prepareRequest:applyMetadataObjectRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
284         }
285     }
286 }
287
288 - (void)refreshInfo {
289     @synchronized(self) {
290         if (refreshMetadataObjectRequest == nil) {
291             refreshMetadataObjectRequest = [[ASIPithosObjectRequest objectMetadataRequestWithPithos:pithos 
292                                                                                       containerName:pithosContainer.name 
293                                                                                          objectName:pithosObject.name] retain];
294             if (sharingAccount)
295                 [refreshMetadataObjectRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithos];
296             refreshMetadataObjectRequest.delegate = self;
297             refreshMetadataObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
298             refreshMetadataObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
299             refreshMetadataObjectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
300                                                      [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
301                                                      [NSNumber numberWithUnsignedInteger:10], @"retries", 
302                                                      NSStringFromSelector(@selector(objectRequestFinished:)), @"didFinishSelector", 
303                                                      NSStringFromSelector(@selector(objectRequestFailed:)), @"didFailSelector", 
304                                                      nil];
305             if (!sharingAccount)
306                 refreshMetadataObjectRequest.downloadCache = [ASIDownloadCache sharedCache];
307             [[PithosUtilities prepareRequest:refreshMetadataObjectRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
308         }
309     }
310     [self refreshVersions];
311 }
312
313 #pragma mark -
314 #pragma mark Versions
315
316 - (void)refreshVersions {
317     @synchronized(self) {
318         if (refreshVersionsObjectRequest == nil) {
319             refreshVersionsObjectRequest = [[ASIPithosObjectRequest objectVersionsRequestWithPithos:pithos 
320                                                                                       containerName:pithosContainer.name 
321                                                                                          objectName:pithosObject.name] retain];
322             if (sharingAccount)
323                 [refreshVersionsObjectRequest setRequestUserFromDefaultTo:sharingAccount withPithos:pithos];
324             refreshVersionsObjectRequest.delegate = self;
325             refreshVersionsObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
326             refreshVersionsObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
327             refreshVersionsObjectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
328                                                      [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
329                                                      [NSNumber numberWithUnsignedInteger:10], @"retries", 
330                                                      NSStringFromSelector(@selector(objectRequestFinished:)), @"didFinishSelector", 
331                                                      NSStringFromSelector(@selector(objectRequestFailed:)), @"didFailSelector", 
332                                                      nil];
333             if (!sharingAccount)
334                 refreshVersionsObjectRequest.downloadCache = [ASIDownloadCache sharedCache];
335             [[PithosUtilities prepareRequest:refreshVersionsObjectRequest priority:NSOperationQueuePriorityHigh] startAsynchronous];
336         }
337     }
338 }
339
340 #pragma mark -
341 #pragma mark Actions
342
343 - (void)showPithosNodeInfo:(id)sender {
344     if (!pithosNodeInfoController) {
345         pithosNodeInfoController = [[PithosObjectNodeInfoController alloc] initWithPithosNode:self];
346         [self refreshInfo];
347     }
348     [pithosNodeInfoController showWindow:sender];
349     [[pithosNodeInfoController window] makeKeyAndOrderFront:sender];
350     [NSApp activateIgnoringOtherApps:YES];
351 }
352
353 @end