Statistics
| Branch: | Tag: | Revision:

root / pithos-macos / PithosAccount.m @ 32ae06f7

History | View | Annotate | Download (17.9 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 "pithos_macosAppDelegate.h"
43

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

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

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

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

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

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

    
93
#pragma mark -
94
#pragma mark Internal
95

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

    
105
#pragma mark -
106
#pragma mark Properties
107

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

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

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

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

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

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

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

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

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

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

    
206
- (PithosSyncDaemon *)syncDaemon {
207
    @synchronized(self) {
208
        if (self.syncActive && !syncDaemon)
209
            syncDaemon = [[PithosSyncDaemon alloc] initWithDirectoryPath:self.syncDirectoryPath 
210
                                                           pithosAccount:self
211
                                                    containersDictionary:self.syncContainersDictionary
212
                                                         resetLocalState:resetSyncDaemonLocalState];
213
        resetSyncDaemonLocalState = NO;
214
    }
215
    return syncDaemon;
216
}
217

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

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

    
239
        @synchronized(self) {
240
            updatePithos = YES;
241
            resetSyncDaemonLocalState = YES;
242
            [syncLastCompleted release];
243
            syncLastCompleted = nil;
244
        }
245
    }
246
}
247

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

    
259
        }
260
    }
261
}
262

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

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

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

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

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

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

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

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

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

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

    
357
            if (accountNode && ![accountNode.pithos isEqualTo:pithos]) {
358
                accountNode.pithos = pithos;
359
                if (active)
360
                    [accountNode refreshInfo];
361
            }
362
            
363
            updatePithos = NO;
364
        }
365
    }
366
    return pithos;
367
}
368

    
369
- (PithosAccountNode *)accountNode {
370
    if (!accountNode) {
371
        accountNode = [[PithosAccountNode alloc] initWithPithos:self.pithos];
372
        accountNode.childrenUpdatedNotificationName = nil;
373
        accountNode.inheritChildrenUpdatedNotificationName = YES;
374
    }
375
    return accountNode;
376
}
377

    
378
#pragma mark -
379
#pragma mark Actions
380

    
381
- (void)authenticateWithServerURL:(NSString *)aServerURL authUser:(NSString *)anAuthUser authToken:(NSString *)anAuthToken {
382
    self.serverURL = aServerURL;
383
    self.authUser = anAuthUser;
384
    self.authToken = anAuthToken;
385
    NSLog(@"Account: %@\nauthentication", self);
386
    if (![authUser length] || ![authToken length]) {
387
        self.active = NO;
388
        self.syncActive = NO;
389
        // XXX Show preferences with self as the selected account?
390
    } else  {
391
        self.active = YES;
392
        if (syncDaemon) {
393
            self.syncDaemon.pithos = self.pithos;
394
            if (self.syncActive)
395
                [self.syncDaemon startDaemon];
396
        }
397
    }
398
}
399

    
400
- (void)loginWithServerURL:(NSString *)aServerURL {
401
    self.serverURL = aServerURL;
402
    NSProcessInfo *processInfo = [NSProcessInfo processInfo];
403
    NSString *loginURL = [NSString stringWithFormat:@"%@?next=pithos://%d/%@", 
404
                          self.loginURLPrefix, [processInfo processIdentifier], self.name];
405
    NSLog(@"Account: %@\nloginURL: %@", self, loginURL);
406
    [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:loginURL]];
407
}
408

    
409
- (void)updateSyncWithSyncActive:(BOOL)aSyncActive 
410
               syncDirectoryPath:(NSString *)aSyncDirectoryPath 
411
        syncContainersDictionary:(NSMutableDictionary *)aSyncContainersDictionary {
412
    self.syncContainersDictionary = aSyncContainersDictionary;
413
    self.syncDirectoryPath = aSyncDirectoryPath;
414
    self.syncActive = aSyncActive;
415
    if (syncDaemon) {
416
        self.syncDaemon.containersDictionary = self.syncContainersDictionary;
417
        self.syncDaemon.directoryPath = self.syncDirectoryPath;
418
        if (self.syncActive)
419
            [self.syncDaemon startDaemon];
420
    }    
421
}
422

    
423
#pragma mark -
424
#pragma mark NSCoding
425

    
426
- (id)initWithCoder:(NSCoder *)decoder {
427
    if ((self = [super init])) {
428
        self.uniqueName = [decoder decodeObjectForKey:@"uniqueName"];
429
        self.active = [decoder decodeBoolForKey:@"active"];
430
        name = [[decoder decodeObjectForKey:@"name"] retain];
431

    
432
        self.syncActive = [decoder decodeBoolForKey:@"syncActive"];
433
        self.syncDirectoryPath = [decoder decodeObjectForKey:@"syncDirectoryPath"];
434
        NSDictionary *immutableContainersDictionary = [decoder decodeObjectForKey:@"syncContainersDictionary"];
435
        syncContainersDictionary = [[NSMutableDictionary alloc] initWithCapacity:[immutableContainersDictionary count]];
436
        for (NSString *containerName in immutableContainersDictionary) {
437
            [syncContainersDictionary setObject:[NSMutableArray arrayWithArray:[immutableContainersDictionary objectForKey:containerName]] 
438
                                         forKey:containerName];
439
        }
440
        self.syncLastCompleted = [decoder decodeObjectForKey:@"syncLastCompleted"];
441
        
442
        self.serverURL = [decoder decodeObjectForKey:@"serverURL"];
443
        self.versionResource = [decoder decodeObjectForKey:@"versionResource"];
444
        self.loginResource = [decoder decodeObjectForKey:@"loginResource"];
445
        self.publicResource = [decoder decodeObjectForKey:@"publicResource"];
446
        
447
        self.authUser = [decoder decodeObjectForKey:@"authUser"];
448
        self.authToken = [decoder decodeObjectForKey:@"authToken"];
449
        self.storageURLPrefix = [decoder decodeObjectForKey:@"storageURLPrefix"];
450
        self.authURL = [decoder decodeObjectForKey:@"authURL"];
451
        self.publicURLPrefix = [decoder decodeObjectForKey:@"publicURLPrefix"];
452
        self.loginURLPrefix = [decoder decodeObjectForKey:@"loginURLPrefix"];
453
        
454
        if (![authUser length] || ![authToken length] || ![self.storageURLPrefix length])
455
            self.active = NO;
456
        
457
        resetSyncDaemonLocalState = NO;
458
    }
459
    return self;
460
}
461

    
462
- (void)encodeWithCoder:(NSCoder *)encoder {
463
    [encoder encodeObject:uniqueName forKey:@"uniqueName"];
464
    [encoder encodeBool:active forKey:@"active"];
465
    [encoder encodeObject:name forKey:@"name"];
466
    
467
    [encoder encodeBool:syncActive forKey:@"syncActive"];
468
    [encoder encodeObject:syncDirectoryPath forKey:@"syncDirectoryPath"];
469
    [encoder encodeObject:syncContainersDictionary forKey:@"syncContainersDictionary"];
470
    [encoder encodeObject:self.syncLastCompleted forKey:@"syncLastCompleted"];
471

    
472
    [encoder encodeObject:serverURL forKey:@"serverURL"];
473
    [encoder encodeObject:versionResource forKey:@"versionResource"];
474
    [encoder encodeObject:publicResource forKey:@"publicResource"];
475
    [encoder encodeObject:loginResource forKey:@"loginResource"];
476
    
477
    [encoder encodeObject:authUser forKey:@"authUser"];
478
    [encoder encodeObject:authToken forKey:@"authToken"];
479
    [encoder encodeObject:storageURLPrefix forKey:@"storageURLPrefix"];
480
    [encoder encodeObject:authURL forKey:@"authURL"];
481
    [encoder encodeObject:publicURLPrefix forKey:@"publicURLPrefix"];
482
    [encoder encodeObject:loginURLPrefix forKey:@"loginURLPrefix"];
483
}
484

    
485
@end