Statistics
| Branch: | Tag: | Revision:

root / pithos-macos / PithosAccount.m @ e8dc9335

History | View | Annotate | Download (19.1 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, 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.versionResource = [NSString stringWithString:@"v1"];
63
    pithosAccount.loginResource = [NSString stringWithString:@"login"];
64
    return pithosAccount;
65
}
66

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

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

    
95
#pragma mark -
96
#pragma mark Internal
97

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

    
107
#pragma mark -
108
#pragma mark Properties
109

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

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

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

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

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

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

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

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

    
187
- (void)setSyncAccountsDictionary:(NSMutableDictionary *)aSyncAccountsDictionary {
188
    if (aSyncAccountsDictionary && ![self.syncAccountsDictionary isEqualToDictionary:aSyncAccountsDictionary]) {
189
        [syncAccountsDictionary release];
190
        syncAccountsDictionary = [aSyncAccountsDictionary retain];
191
        // XXX maybe check also here the validity of the dictionary? 
192
        
193
        @synchronized(self) {
194
            resetSyncDaemonLocalState = YES;
195
            [syncLastCompleted release];
196
            syncLastCompleted = nil;
197
        }
198
    }
199
}
200

    
201
- (NSDate *)syncLastCompleted {
202
    if (self.syncDaemon.lastCompletedSync && ![self.syncDaemon.lastCompletedSync isEqualToDate:syncLastCompleted]) {
203
        [syncLastCompleted release];
204
        syncLastCompleted = [self.syncDaemon.lastCompletedSync copy];
205
    }
206
    return syncLastCompleted;
207
}
208

    
209
- (PithosSyncDaemon *)syncDaemon {
210
    @synchronized(self) {
211
        if (self.syncActive && !syncDaemon)
212
            syncDaemon = [[PithosSyncDaemon alloc] initWithDirectoryPath:self.syncDirectoryPath 
213
                                                           pithosAccount:self
214
                                                      accountsDictionary:self.syncAccountsDictionary
215
                                                         resetLocalState:resetSyncDaemonLocalState];
216
        resetSyncDaemonLocalState = NO;
217
    }
218
    return syncDaemon;
219
}
220

    
221
- (NSString *)serverURL {
222
    if (![self urlIsValid:serverURL]) {
223
        [serverURL release];
224
        serverURL = [[NSString stringWithString:@"https://pithos.okeanos.grnet.gr"] retain];
225
    }
226
    return serverURL;
227
}
228

    
229
- (void)setServerURL:(NSString *)aServerURL {
230
    if (![self.serverURL isEqualToString:aServerURL] && [self urlIsValid:aServerURL]) {
231
        [serverURL release];
232
        serverURL = [aServerURL retain];
233
        [storageURLPrefix release];
234
        storageURLPrefix = nil;
235
        [authURL release];
236
        authURL = nil;
237
        [publicURLPrefix release];
238
        publicURLPrefix = nil;
239
        [loginURLPrefix release];
240
        loginURLPrefix = nil;
241

    
242
        @synchronized(self) {
243
            updatePithos = YES;
244
            resetSyncDaemonLocalState = YES;
245
            [syncLastCompleted release];
246
            syncLastCompleted = nil;
247
        }
248
    }
249
}
250

    
251
- (void)setAuthUser:(NSString *)anAuthUser {
252
    if ([anAuthUser length] && ![anAuthUser isEqualToString:authUser]) {
253
        [authUser release];
254
        authUser = [anAuthUser retain];
255
        
256
        @synchronized(self) {
257
            updatePithos = YES;
258
            resetSyncDaemonLocalState = YES;
259
            [syncLastCompleted release];
260
            syncLastCompleted = nil;
261

    
262
        }
263
    }
264
}
265

    
266
- (void)setAuthToken:(NSString *)anAuthToken {
267
    if ([anAuthToken length] && ![anAuthToken isEqualToString:authToken]) {
268
        [authToken release];
269
        authToken = [anAuthToken retain];
270
        
271
        @synchronized(self) {
272
            updatePithos = YES;
273
        }
274
    }
275
}
276

    
277
- (NSString *)storageURLPrefix {
278
    if (![self urlIsValid:storageURLPrefix]) {
279
        [storageURLPrefix release];
280
        if (versionResource)
281
            storageURLPrefix = [[self.serverURL stringByAppendingFormat:@"/%@", versionResource] retain];
282
        else
283
            storageURLPrefix = [self.serverURL copy];
284
    }
285
    return storageURLPrefix;
286
}
287

    
288
- (void)setStorageURLPrefix:(NSString *)aStorageURLPrefix {
289
    if (![self.storageURLPrefix isEqualToString:aStorageURLPrefix] && [self urlIsValid:aStorageURLPrefix]) {
290
        [storageURLPrefix release];
291
        storageURLPrefix = [aStorageURLPrefix retain];
292
    }
293
}
294

    
295
- (NSString *)authURL {
296
    if (![self urlIsValid:authURL]) {
297
        [authURL release];
298
        if (versionResource)
299
            authURL = [[self.serverURL stringByAppendingFormat:@"/%@", versionResource] retain];
300
        else
301
            authURL = [self.serverURL copy];
302
    }
303
    return authURL;
304
}
305

    
306
- (void)setAuthURL:(NSString *)anAuthURL {
307
    if (![self.authURL isEqualToString:anAuthURL] && [self urlIsValid:anAuthURL]) {
308
        [authURL release];
309
        authURL = [anAuthURL retain];
310
    }
311
}
312

    
313
- (NSString *)publicURLPrefix {
314
    if (![self urlIsValid:publicURLPrefix]) {
315
        [publicURLPrefix release];
316
        if (publicResource)
317
            publicURLPrefix = [[self.serverURL stringByAppendingFormat:@"/%@", publicResource] retain];
318
        else
319
            publicURLPrefix = [self.serverURL copy];
320
    }
321
    return publicURLPrefix;
322
}
323

    
324
- (void)setPublicURLPrefix:(NSString *)aPublicURLPrefix {
325
    if (![self.publicURLPrefix isEqualToString:aPublicURLPrefix] && [self urlIsValid:aPublicURLPrefix]) {
326
        [publicURLPrefix release];
327
        publicURLPrefix = [aPublicURLPrefix retain];
328
    }
329
}
330

    
331
- (NSString *)loginURLPrefix {
332
    if (![self urlIsValid:loginURLPrefix]) {
333
        [loginURLPrefix release];
334
        if (loginResource)
335
            loginURLPrefix = [[self.serverURL stringByAppendingFormat:@"/%@", loginResource] retain];
336
        else
337
            loginURLPrefix = [self.serverURL copy];
338
    }
339
    return loginURLPrefix;
340
}
341

    
342
- (void)setLoginURLPrefix:(NSString *)aLoginURLPrefix {
343
    if (![self.loginURLPrefix isEqualToString:aLoginURLPrefix] && [self urlIsValid:aLoginURLPrefix]) {
344
        [loginURLPrefix release];
345
        loginURLPrefix = [aLoginURLPrefix retain];
346
    }
347
}
348

    
349
- (ASIPithos *)pithos {
350
    @synchronized(self) {
351
        if (!pithos || updatePithos) {
352
            [pithos release];
353
            pithos = [[ASIPithos pithos] retain];
354
            pithos.authUser = authUser;
355
            pithos.authToken = authToken;
356
            pithos.storageURLPrefix = self.storageURLPrefix;
357
            pithos.authURL = self.authURL;
358
            pithos.publicURLPrefix = self.publicURLPrefix;
359

    
360
            if (accountNode && ![accountNode.pithos isEqualTo:pithos]) {
361
                accountNode.pithos = pithos;
362
                if (active)
363
                    [accountNode refreshInfo];
364
            }
365
            if (sharingAccountsNode && ![sharingAccountsNode.pithos isEqualTo:pithos])
366
                sharingAccountsNode.pithos = pithos;
367
            
368
            updatePithos = NO;
369
        }
370
    }
371
    return pithos;
372
}
373

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

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

    
392
#pragma mark -
393
#pragma mark Actions
394

    
395
- (void)authenticateWithServerURL:(NSString *)aServerURL authUser:(NSString *)anAuthUser authToken:(NSString *)anAuthToken {
396
    self.serverURL = aServerURL;
397
    self.authUser = anAuthUser;
398
    self.authToken = anAuthToken;
399
    NSLog(@"Account: %@\nauthentication", self);
400
    if (![authUser length] || ![authToken length]) {
401
        self.active = NO;
402
        self.syncActive = NO;
403
        // XXX Show preferences with self as the selected account?
404
    } else  {
405
        self.active = YES;
406
        if (syncDaemon) {
407
            self.syncDaemon.pithos = self.pithos;
408
            if (self.syncActive)
409
                [self.syncDaemon startDaemon];
410
        }
411
    }
412
}
413

    
414
- (void)loginWithServerURL:(NSString *)aServerURL {
415
    self.serverURL = aServerURL;
416
    NSProcessInfo *processInfo = [NSProcessInfo processInfo];
417
    NSString *loginURL = [NSString stringWithFormat:@"%@?next=pithos://%d/%@", 
418
                          self.loginURLPrefix, [processInfo processIdentifier], self.name];
419
    NSLog(@"Account: %@\nloginURL: %@", self, loginURL);
420
    [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:loginURL]];
421
}
422

    
423
- (void)updateSyncWithSyncActive:(BOOL)aSyncActive 
424
               syncDirectoryPath:(NSString *)aSyncDirectoryPath 
425
          syncAccountsDictionary:(NSMutableDictionary *)aSyncAccountsDictionary {
426
    self.syncAccountsDictionary = aSyncAccountsDictionary;
427
    self.syncDirectoryPath = aSyncDirectoryPath;
428
    self.syncActive = aSyncActive;
429
    if (syncDaemon) {
430
        self.syncDaemon.accountsDictionary = self.syncAccountsDictionary;
431
        self.syncDaemon.directoryPath = self.syncDirectoryPath;
432
        if (self.syncActive)
433
            [self.syncDaemon startDaemon];
434
    }    
435
}
436

    
437
#pragma mark -
438
#pragma mark NSCoding
439

    
440
- (id)initWithCoder:(NSCoder *)decoder {
441
    if ((self = [super init])) {
442
        self.uniqueName = [decoder decodeObjectForKey:@"uniqueName"];
443
        self.active = [decoder decodeBoolForKey:@"active"];
444
        name = [[decoder decodeObjectForKey:@"name"] retain];
445

    
446
        self.syncActive = [decoder decodeBoolForKey:@"syncActive"];
447
        self.syncDirectoryPath = [decoder decodeObjectForKey:@"syncDirectoryPath"];
448
        NSDictionary *immutableAccountsDictionary = [decoder decodeObjectForKey:@"syncAccountsDictionary"];
449
        syncAccountsDictionary = [[NSMutableDictionary alloc] initWithCapacity:[immutableAccountsDictionary count]];
450
        for (NSString *accountName in immutableAccountsDictionary) {
451
            NSDictionary *immutableContainersDictionary = [immutableAccountsDictionary objectForKey:accountName];
452
            NSMutableDictionary *syncContainersDictionary = [NSMutableDictionary dictionary];
453
            for (NSString *containerName in [immutableAccountsDictionary objectForKey:accountName]) {
454
                [syncContainersDictionary setObject:[NSMutableArray arrayWithArray:[immutableContainersDictionary objectForKey:containerName]] 
455
                                             forKey:containerName];
456
            }
457
            if ([syncContainersDictionary count])
458
                [syncAccountsDictionary setObject:syncContainersDictionary forKey:accountName];
459
        }
460
        self.syncLastCompleted = [decoder decodeObjectForKey:@"syncLastCompleted"];
461
        
462
        self.serverURL = [decoder decodeObjectForKey:@"serverURL"];
463
        self.versionResource = [decoder decodeObjectForKey:@"versionResource"];
464
        self.loginResource = [decoder decodeObjectForKey:@"loginResource"];
465
        self.publicResource = [decoder decodeObjectForKey:@"publicResource"];
466
        
467
        self.authUser = [decoder decodeObjectForKey:@"authUser"];
468
        self.authToken = [decoder decodeObjectForKey:@"authToken"];
469
        self.storageURLPrefix = [decoder decodeObjectForKey:@"storageURLPrefix"];
470
        self.authURL = [decoder decodeObjectForKey:@"authURL"];
471
        self.publicURLPrefix = [decoder decodeObjectForKey:@"publicURLPrefix"];
472
        self.loginURLPrefix = [decoder decodeObjectForKey:@"loginURLPrefix"];
473
        
474
        if (![authUser length] || ![authToken length] || ![self.storageURLPrefix length])
475
            self.active = NO;
476
        
477
        resetSyncDaemonLocalState = NO;
478
    }
479
    return self;
480
}
481

    
482
- (void)encodeWithCoder:(NSCoder *)encoder {
483
    [encoder encodeObject:uniqueName forKey:@"uniqueName"];
484
    [encoder encodeBool:active forKey:@"active"];
485
    [encoder encodeObject:name forKey:@"name"];
486
    
487
    [encoder encodeBool:syncActive forKey:@"syncActive"];
488
    [encoder encodeObject:syncDirectoryPath forKey:@"syncDirectoryPath"];
489
    [encoder encodeObject:syncAccountsDictionary forKey:@"syncAccountsDictionary"];
490
    [encoder encodeObject:self.syncLastCompleted forKey:@"syncLastCompleted"];
491

    
492
    [encoder encodeObject:serverURL forKey:@"serverURL"];
493
    [encoder encodeObject:versionResource forKey:@"versionResource"];
494
    [encoder encodeObject:publicResource forKey:@"publicResource"];
495
    [encoder encodeObject:loginResource forKey:@"loginResource"];
496
    
497
    [encoder encodeObject:authUser forKey:@"authUser"];
498
    [encoder encodeObject:authToken forKey:@"authToken"];
499
    [encoder encodeObject:storageURLPrefix forKey:@"storageURLPrefix"];
500
    [encoder encodeObject:authURL forKey:@"authURL"];
501
    [encoder encodeObject:publicURLPrefix forKey:@"publicURLPrefix"];
502
    [encoder encodeObject:loginURLPrefix forKey:@"loginURLPrefix"];
503
}
504

    
505
@end