Statistics
| Branch: | Tag: | Revision:

root / pithos-macos / PithosAccount.m @ 56198066

History | View | Annotate | Download (19.5 kB)

1
//
2
//  PithosAccount.m
3
//  pithos-macos
4
//
5
// Copyright 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 "PithosAccount.h"
39
#import "PithosSyncDaemon.h"
40
#import "ASIPithos.h"
41
#import "PithosAccountNode.h"
42
#import "PithosSharingAccountsNode.h"
43
#import "pithos_macosAppDelegate.h"
44

    
45
@interface PithosAccount (Internal)
46
- (BOOL)urlIsValid:(NSString *)urlString;
47
@end
48

    
49
@implementation PithosAccount
50
@synthesize uniqueName, active, name;
51
@synthesize syncActive, syncDirectoryPath, syncAccountsDictionary, syncSkipHidden, syncLastCompleted, syncDaemon;
52
@synthesize serverURL, versionResource, loginResource, publicResource;
53
@synthesize authUser, authToken, storageURLPrefix, authURL, loginURLPrefix, publicURLPrefix;
54
@synthesize pithos, accountNode, sharingAccountsNode;
55

    
56
#pragma mark -
57
#pragma mark Object Lifecycle
58

    
59
+ (id)pithosAccount {
60
    PithosAccount *pithosAccount = [[[self alloc] init] autorelease];
61
    pithosAccount.uniqueName = [NSString stringWithFormat:@"pithosAccount-%f", [NSDate timeIntervalSinceReferenceDate]];
62
    pithosAccount.syncSkipHidden = YES;
63
    pithosAccount.versionResource = [NSString stringWithString:@"v1"];
64
    pithosAccount.loginResource = [NSString stringWithString:@"login"];
65
    return pithosAccount;
66
}
67

    
68
- (void)dealloc {
69
    [sharingAccountsNode release];
70
    [accountNode release];
71
    [pithos release];
72
    [publicURLPrefix release];
73
    [loginURLPrefix release];
74
    [authURL release];
75
    [storageURLPrefix release];
76
    [authToken release];
77
    [authUser release];
78
    [publicResource release];
79
    [loginResource release];
80
    [versionResource release];
81
    [serverURL release];
82
    [syncDaemon release];
83
    [syncLastCompleted release];
84
    [syncAccountsDictionary release];
85
    [syncDirectoryPath release];
86
    [name release];
87
    [uniqueName release];
88
    [super dealloc];
89
}
90

    
91
- (NSString *)description {
92
    return [NSString stringWithFormat:@"uniqueName: %@, active: %d, name: %@, syncActive: %d, syncDirectoryPath: %@, syncAccountsDictionary: %@, syncSkipHidden: %d, syncLastCompleted: %@, serverURL: %@, versionResource: %@, loginResource: %@, publicResource: %@, authUser: %@, authToken: %@, storageURLPrefix: %@, authURL: %@, loginURLPrefix: %@, publicURLPrefix: %@", 
93
            uniqueName, active, name, syncActive, syncDirectoryPath, syncAccountsDictionary, syncSkipHidden, syncLastCompleted, serverURL, versionResource, loginResource, publicResource, authUser, authToken, storageURLPrefix, authURL, loginURLPrefix, publicURLPrefix];
94
}
95

    
96
#pragma mark -
97
#pragma mark Internal
98

    
99
- (BOOL)urlIsValid:(NSString *)urlString {
100
    if (urlString) {
101
        NSURL *url = [NSURL URLWithString:urlString];
102
        if (url && url.scheme && url.host)
103
            return YES;
104
    }
105
    return NO;
106
}
107

    
108
#pragma mark -
109
#pragma mark Properties
110

    
111
- (NSString *)name {
112
    if (![name length]) {
113
        [name release];
114
        NSDictionary *pithosAccountsDictionary = [(pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate] pithosAccountsDictionary];
115
        NSString *namePrefix = [NSString stringWithString:@"okeanos"];
116
        NSUInteger nameSuffix = 1;
117
        name = [NSString stringWithString:@"okeanos"];
118
        NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
119
        NSFileManager *fileManager = [NSFileManager defaultManager];
120
        while ([pithosAccountsDictionary objectForKey:name] || 
121
               [fileManager fileExistsAtPath:[documentsDirectoryPath stringByAppendingPathComponent:name]]) {
122
            name = [NSString stringWithFormat:@"%@%d", namePrefix, ++nameSuffix];
123
        }
124
        [name retain];
125
    }
126
    return name;
127
}
128

    
129
- (void)setName:(NSString *)aName {
130
    NSMutableDictionary *pithosAccountsDictionary = [(pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate] pithosAccountsDictionary];
131
    if (![self.name isEqualToString:aName] && [aName length] && ![pithosAccountsDictionary objectForKey:aName]) {
132
        [pithosAccountsDictionary setObject:self forKey:aName];
133
        [pithosAccountsDictionary removeObjectForKey:name];
134
        [name release];
135
        name = [aName retain];
136
    }
137
}
138

    
139
- (BOOL)syncActive {
140
    if (active)
141
        return syncActive;
142
    else
143
        return NO;
144
}
145

    
146
- (void)setSyncActive:(BOOL)aSyncActive {
147
    syncActive = aSyncActive;
148
    if (syncDaemon && !self.syncActive)
149
        [syncDaemon resetDaemon];
150
}
151

    
152
- (NSString *)syncDirectoryPath {
153
    if (![syncDirectoryPath length]) {
154
        [syncDirectoryPath release];
155
        syncDirectoryPath = [[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] 
156
                              stringByAppendingPathComponent:self.name] retain];
157
    }
158
    return syncDirectoryPath;
159
}
160

    
161
- (void)setSyncDirectoryPath:(NSString *)aSyncDirectoryPath {
162
    if (![self.syncDirectoryPath isEqualToString:aSyncDirectoryPath] && [aSyncDirectoryPath length]) {
163
        BOOL isDirectory;
164
        if (![[NSFileManager defaultManager] fileExistsAtPath:aSyncDirectoryPath isDirectory:&isDirectory] || isDirectory) {
165
            [syncDirectoryPath release];
166
            syncDirectoryPath = [aSyncDirectoryPath retain];
167
        } else {
168
            return;
169
        }
170

    
171
        @synchronized(self) {
172
            resetSyncDaemonLocalState = YES;
173
            [syncLastCompleted release];
174
            syncLastCompleted = nil;
175
        }
176
    }
177
}
178

    
179
- (NSMutableDictionary *)syncAccountsDictionary {
180
    if (!syncAccountsDictionary) {
181
        syncAccountsDictionary = [[NSMutableDictionary dictionaryWithObject:[NSMutableDictionary dictionaryWithObject:[NSMutableSet set] 
182
                                                                                                               forKey:@"pithos"] 
183
                                                                     forKey:@""] retain];
184
    }        
185
    return syncAccountsDictionary;
186
}
187

    
188
- (void)setSyncAccountsDictionary:(NSMutableDictionary *)aSyncAccountsDictionary {
189
    if (aSyncAccountsDictionary && ![self.syncAccountsDictionary isEqualToDictionary:aSyncAccountsDictionary]) {
190
        [syncAccountsDictionary release];
191
        syncAccountsDictionary = [[NSMutableDictionary alloc] initWithCapacity:[aSyncAccountsDictionary count]];
192
        for (NSString *accountName in aSyncAccountsDictionary) {
193
            NSDictionary *aSyncContainersDictionary = [aSyncAccountsDictionary objectForKey:accountName];
194
            NSMutableDictionary *syncContainersDictionary = [NSMutableDictionary dictionary];
195
            for (NSString *containerName in aSyncContainersDictionary) {
196
                if (![accountName isEqualToString:@""] || ![[containerName lowercaseString] isEqualToString:@"shared to me"])
197
                    [syncContainersDictionary setObject:[NSMutableSet setWithSet:[aSyncContainersDictionary objectForKey:containerName]] 
198
                                                 forKey:containerName];
199
            }
200
            if ([syncContainersDictionary count])
201
                [syncAccountsDictionary setObject:syncContainersDictionary forKey:accountName];
202
        }
203
        
204
        @synchronized(self) {
205
            resetSyncDaemonLocalState = YES;
206
            [syncLastCompleted release];
207
            syncLastCompleted = nil;
208
        }
209
    }
210
}
211

    
212
- (NSDate *)syncLastCompleted {
213
    if (self.syncDaemon.lastCompletedSync && ![self.syncDaemon.lastCompletedSync isEqualToDate:syncLastCompleted]) {
214
        [syncLastCompleted release];
215
        syncLastCompleted = [self.syncDaemon.lastCompletedSync copy];
216
    }
217
    return syncLastCompleted;
218
}
219

    
220
- (PithosSyncDaemon *)syncDaemon {
221
    @synchronized(self) {
222
        if (self.syncActive && !syncDaemon)
223
            syncDaemon = [[PithosSyncDaemon alloc] initWithDirectoryPath:self.syncDirectoryPath 
224
                                                           pithosAccount:self 
225
                                                      accountsDictionary:self.syncAccountsDictionary 
226
                                                              skipHidden:self.syncSkipHidden 
227
                                                         resetLocalState:resetSyncDaemonLocalState];
228
        resetSyncDaemonLocalState = NO;
229
    }
230
    return syncDaemon;
231
}
232

    
233
- (NSString *)serverURL {
234
    if (![self urlIsValid:serverURL]) {
235
        [serverURL release];
236
        serverURL = [[NSString stringWithString:@"https://pithos.okeanos.grnet.gr"] retain];
237
    }
238
    return serverURL;
239
}
240

    
241
- (void)setServerURL:(NSString *)aServerURL {
242
    if (![self.serverURL isEqualToString:aServerURL] && [self urlIsValid:aServerURL]) {
243
        [serverURL release];
244
        serverURL = [aServerURL retain];
245
        [storageURLPrefix release];
246
        storageURLPrefix = nil;
247
        [authURL release];
248
        authURL = nil;
249
        [publicURLPrefix release];
250
        publicURLPrefix = nil;
251
        [loginURLPrefix release];
252
        loginURLPrefix = nil;
253

    
254
        @synchronized(self) {
255
            updatePithos = YES;
256
            resetSyncDaemonLocalState = YES;
257
            [syncLastCompleted release];
258
            syncLastCompleted = nil;
259
        }
260
    }
261
}
262

    
263
- (void)setAuthUser:(NSString *)anAuthUser {
264
    if ([anAuthUser length] && ![anAuthUser isEqualToString:authUser]) {
265
        [authUser release];
266
        authUser = [anAuthUser retain];
267
        
268
        @synchronized(self) {
269
            updatePithos = YES;
270
            resetSyncDaemonLocalState = YES;
271
            [syncLastCompleted release];
272
            syncLastCompleted = nil;
273

    
274
        }
275
    }
276
}
277

    
278
- (void)setAuthToken:(NSString *)anAuthToken {
279
    if ([anAuthToken length] && ![anAuthToken isEqualToString:authToken]) {
280
        [authToken release];
281
        authToken = [anAuthToken retain];
282
        
283
        @synchronized(self) {
284
            updatePithos = YES;
285
        }
286
    }
287
}
288

    
289
- (NSString *)storageURLPrefix {
290
    if (![self urlIsValid:storageURLPrefix]) {
291
        [storageURLPrefix release];
292
        if (versionResource)
293
            storageURLPrefix = [[self.serverURL stringByAppendingFormat:@"/%@", versionResource] retain];
294
        else
295
            storageURLPrefix = [self.serverURL copy];
296
    }
297
    return storageURLPrefix;
298
}
299

    
300
- (void)setStorageURLPrefix:(NSString *)aStorageURLPrefix {
301
    if (![self.storageURLPrefix isEqualToString:aStorageURLPrefix] && [self urlIsValid:aStorageURLPrefix]) {
302
        [storageURLPrefix release];
303
        storageURLPrefix = [aStorageURLPrefix retain];
304
    }
305
}
306

    
307
- (NSString *)authURL {
308
    if (![self urlIsValid:authURL]) {
309
        [authURL release];
310
        if (versionResource)
311
            authURL = [[self.serverURL stringByAppendingFormat:@"/%@", versionResource] retain];
312
        else
313
            authURL = [self.serverURL copy];
314
    }
315
    return authURL;
316
}
317

    
318
- (void)setAuthURL:(NSString *)anAuthURL {
319
    if (![self.authURL isEqualToString:anAuthURL] && [self urlIsValid:anAuthURL]) {
320
        [authURL release];
321
        authURL = [anAuthURL retain];
322
    }
323
}
324

    
325
- (NSString *)publicURLPrefix {
326
    if (![self urlIsValid:publicURLPrefix]) {
327
        [publicURLPrefix release];
328
        if (publicResource)
329
            publicURLPrefix = [[self.serverURL stringByAppendingFormat:@"/%@", publicResource] retain];
330
        else
331
            publicURLPrefix = [self.serverURL copy];
332
    }
333
    return publicURLPrefix;
334
}
335

    
336
- (void)setPublicURLPrefix:(NSString *)aPublicURLPrefix {
337
    if (![self.publicURLPrefix isEqualToString:aPublicURLPrefix] && [self urlIsValid:aPublicURLPrefix]) {
338
        [publicURLPrefix release];
339
        publicURLPrefix = [aPublicURLPrefix retain];
340
    }
341
}
342

    
343
- (NSString *)loginURLPrefix {
344
    if (![self urlIsValid:loginURLPrefix]) {
345
        [loginURLPrefix release];
346
        if (loginResource)
347
            loginURLPrefix = [[self.serverURL stringByAppendingFormat:@"/%@", loginResource] retain];
348
        else
349
            loginURLPrefix = [self.serverURL copy];
350
    }
351
    return loginURLPrefix;
352
}
353

    
354
- (void)setLoginURLPrefix:(NSString *)aLoginURLPrefix {
355
    if (![self.loginURLPrefix isEqualToString:aLoginURLPrefix] && [self urlIsValid:aLoginURLPrefix]) {
356
        [loginURLPrefix release];
357
        loginURLPrefix = [aLoginURLPrefix retain];
358
    }
359
}
360

    
361
- (ASIPithos *)pithos {
362
    @synchronized(self) {
363
        if (!pithos || updatePithos) {
364
            [pithos release];
365
            pithos = [[ASIPithos pithos] retain];
366
            pithos.authUser = authUser;
367
            pithos.authToken = authToken;
368
            pithos.storageURLPrefix = self.storageURLPrefix;
369
            pithos.authURL = self.authURL;
370
            pithos.publicURLPrefix = self.publicURLPrefix;
371
            updatePithos = NO;
372
        }
373
    }
374
    return pithos;
375
}
376

    
377
- (PithosAccountNode *)accountNode {
378
    if (!accountNode) {
379
        accountNode = [[PithosAccountNode alloc] initWithPithos:self.pithos];
380
        accountNode.childrenUpdatedNotificationName = nil;
381
        accountNode.inheritChildrenUpdatedNotificationName = YES;
382
    }
383
    return accountNode;
384
}
385

    
386
- (PithosSharingAccountsNode *)sharingAccountsNode {
387
    if (!sharingAccountsNode) {
388
        sharingAccountsNode = [[PithosSharingAccountsNode alloc] initWithPithos:self.pithos];
389
        sharingAccountsNode.childrenUpdatedNotificationName = nil;
390
        sharingAccountsNode.inheritChildrenUpdatedNotificationName = YES;
391
    }
392
    return sharingAccountsNode;
393
}
394

    
395
#pragma mark -
396
#pragma mark Actions
397

    
398
- (void)authenticateWithServerURL:(NSString *)aServerURL authUser:(NSString *)anAuthUser authToken:(NSString *)anAuthToken {
399
    self.serverURL = aServerURL;
400
    self.authUser = anAuthUser;
401
    self.authToken = anAuthToken;
402
    NSLog(@"Account: %@\nauthentication", self);
403
    if (![authUser length] || ![authToken length]) {
404
        self.active = NO;
405
        self.syncActive = NO;
406
        // XXX Show preferences with self as the selected account?
407
    } else  {
408
        self.active = YES;
409
        if (syncDaemon) {
410
            self.syncDaemon.pithos = self.pithos;
411
            if (self.syncActive)
412
                [self.syncDaemon startDaemon];
413
        }
414
        if (accountNode)
415
            self.accountNode.pithos = self.pithos;
416
        if (sharingAccountsNode)
417
            self.sharingAccountsNode.pithos = self.pithos;
418
        if (accountNode) {
419
            if (self.accountNode.children) {
420
            }
421
            [self.accountNode refreshInfo];
422
        }
423
        if (sharingAccountsNode && self.sharingAccountsNode.children) {
424
        }
425
    }
426
}
427

    
428
- (void)loginWithServerURL:(NSString *)aServerURL {
429
    self.serverURL = aServerURL;
430
    NSProcessInfo *processInfo = [NSProcessInfo processInfo];
431
    NSString *loginURL = [NSString stringWithFormat:@"%@?next=pithos://%d/%@&force=", 
432
                          self.loginURLPrefix, [processInfo processIdentifier], self.name];
433
    NSLog(@"Account: %@\nloginURL: %@", self, loginURL);
434
    [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:loginURL]];
435
}
436

    
437
- (void)updateSyncWithSyncActive:(BOOL)aSyncActive 
438
               syncDirectoryPath:(NSString *)aSyncDirectoryPath 
439
          syncAccountsDictionary:(NSMutableDictionary *)aSyncAccountsDictionary 
440
                  syncSkipHidden:(BOOL)aSyncSkipHidden {
441
    self.syncAccountsDictionary = aSyncAccountsDictionary;
442
    self.syncDirectoryPath = aSyncDirectoryPath;
443
    self.syncSkipHidden = aSyncSkipHidden;
444
    self.syncActive = aSyncActive;
445
    if (syncDaemon) {
446
        self.syncDaemon.accountsDictionary = self.syncAccountsDictionary;
447
        self.syncDaemon.directoryPath = self.syncDirectoryPath;
448
        self.syncDaemon.skipHidden = self.syncSkipHidden;
449
        if (self.syncActive)
450
            [self.syncDaemon startDaemon];
451
    }    
452
}
453

    
454
#pragma mark -
455
#pragma mark NSCoding
456

    
457
- (id)initWithCoder:(NSCoder *)decoder {
458
    if ((self = [super init])) {
459
        self.uniqueName = [decoder decodeObjectForKey:@"uniqueName"];
460
        self.active = [decoder decodeBoolForKey:@"active"];
461
        name = [[decoder decodeObjectForKey:@"name"] retain];
462

    
463
        self.syncActive = [decoder decodeBoolForKey:@"syncActive"];
464
        self.syncDirectoryPath = [decoder decodeObjectForKey:@"syncDirectoryPath"];
465
        self.syncAccountsDictionary = [decoder decodeObjectForKey:@"syncAccountsDictionary"];
466
        self.syncSkipHidden = [decoder decodeBoolForKey:@"syncSkipHidden"];
467
        self.syncLastCompleted = [decoder decodeObjectForKey:@"syncLastCompleted"];
468
        
469
        self.serverURL = [decoder decodeObjectForKey:@"serverURL"];
470
        self.versionResource = [decoder decodeObjectForKey:@"versionResource"];
471
        self.loginResource = [decoder decodeObjectForKey:@"loginResource"];
472
        self.publicResource = [decoder decodeObjectForKey:@"publicResource"];
473
        
474
        self.authUser = [decoder decodeObjectForKey:@"authUser"];
475
        self.authToken = [decoder decodeObjectForKey:@"authToken"];
476
        self.storageURLPrefix = [decoder decodeObjectForKey:@"storageURLPrefix"];
477
        self.authURL = [decoder decodeObjectForKey:@"authURL"];
478
        self.publicURLPrefix = [decoder decodeObjectForKey:@"publicURLPrefix"];
479
        self.loginURLPrefix = [decoder decodeObjectForKey:@"loginURLPrefix"];
480
        
481
        if (![authUser length] || ![authToken length] || ![self.storageURLPrefix length])
482
            self.active = NO;
483
        
484
        resetSyncDaemonLocalState = NO;
485
    }
486
    return self;
487
}
488

    
489
- (void)encodeWithCoder:(NSCoder *)encoder {
490
    [encoder encodeObject:uniqueName forKey:@"uniqueName"];
491
    [encoder encodeBool:active forKey:@"active"];
492
    [encoder encodeObject:name forKey:@"name"];
493
    
494
    [encoder encodeBool:syncActive forKey:@"syncActive"];
495
    [encoder encodeObject:syncDirectoryPath forKey:@"syncDirectoryPath"];
496
    [encoder encodeObject:syncAccountsDictionary forKey:@"syncAccountsDictionary"];
497
    [encoder encodeBool:syncSkipHidden forKey:@"syncSkipHidden"];
498
    [encoder encodeObject:self.syncLastCompleted forKey:@"syncLastCompleted"];
499

    
500
    [encoder encodeObject:serverURL forKey:@"serverURL"];
501
    [encoder encodeObject:versionResource forKey:@"versionResource"];
502
    [encoder encodeObject:publicResource forKey:@"publicResource"];
503
    [encoder encodeObject:loginResource forKey:@"loginResource"];
504
    
505
    [encoder encodeObject:authUser forKey:@"authUser"];
506
    [encoder encodeObject:authToken forKey:@"authToken"];
507
    [encoder encodeObject:storageURLPrefix forKey:@"storageURLPrefix"];
508
    [encoder encodeObject:authURL forKey:@"authURL"];
509
    [encoder encodeObject:publicURLPrefix forKey:@"publicURLPrefix"];
510
    [encoder encodeObject:loginURLPrefix forKey:@"loginURLPrefix"];
511
}
512

    
513
@end