root / pithos-macos / PithosAccount.m @ d4433f6f
History | View | Annotate | Download (17.2 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 (![self.syncContainersDictionary isEqualTo:syncContainersDictionary]) { |
186 |
[syncContainersDictionary release]; |
187 |
syncContainersDictionary = [aSyncContainersDictionary retain]; |
188 |
// XXX check for proper dictionary here |
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 processName], [processInfo processIdentifier], self.name]; |
405 |
NSLog(@"Account: %@\nloginURL: %@", self, loginURL); |
406 |
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:loginURL]]; |
407 |
} |
408 |
|
409 |
- (void)updateSyncWithSyncActive:(BOOL)aSyncActive syncDirectoryPath:(NSString *)aSyncDirectoryPath { |
410 |
self.syncDirectoryPath = aSyncDirectoryPath; |
411 |
self.syncActive = aSyncActive; |
412 |
if (syncDaemon) { |
413 |
self.syncDaemon.directoryPath = self.syncDirectoryPath; |
414 |
if (self.syncActive) |
415 |
[self.syncDaemon startDaemon]; |
416 |
} |
417 |
} |
418 |
|
419 |
#pragma mark - |
420 |
#pragma mark NSCoding |
421 |
|
422 |
- (id)initWithCoder:(NSCoder *)decoder { |
423 |
if ((self = [super init])) { |
424 |
self.uniqueName = [decoder decodeObjectForKey:@"uniqueName"]; |
425 |
self.active = [decoder decodeBoolForKey:@"active"]; |
426 |
name = [[decoder decodeObjectForKey:@"name"] retain]; |
427 |
|
428 |
self.syncActive = [decoder decodeBoolForKey:@"syncActive"]; |
429 |
self.syncDirectoryPath = [decoder decodeObjectForKey:@"syncDirectoryPath"]; |
430 |
self.syncContainersDictionary = [decoder decodeObjectForKey:@"syncContainersDictionary"]; |
431 |
self.syncLastCompleted = [decoder decodeObjectForKey:@"syncLastCompleted"]; |
432 |
|
433 |
self.serverURL = [decoder decodeObjectForKey:@"serverURL"]; |
434 |
self.versionResource = [decoder decodeObjectForKey:@"versionResource"]; |
435 |
self.loginResource = [decoder decodeObjectForKey:@"loginResource"]; |
436 |
self.publicResource = [decoder decodeObjectForKey:@"publicResource"]; |
437 |
|
438 |
self.authUser = [decoder decodeObjectForKey:@"authUser"]; |
439 |
self.authToken = [decoder decodeObjectForKey:@"authToken"]; |
440 |
self.storageURLPrefix = [decoder decodeObjectForKey:@"storageURLPrefix"]; |
441 |
self.authURL = [decoder decodeObjectForKey:@"authURL"]; |
442 |
self.publicURLPrefix = [decoder decodeObjectForKey:@"publicURLPrefix"]; |
443 |
self.loginURLPrefix = [decoder decodeObjectForKey:@"loginURLPrefix"]; |
444 |
|
445 |
if (![authUser length] || ![authToken length] || ![self.storageURLPrefix length]) |
446 |
self.active = NO; |
447 |
|
448 |
resetSyncDaemonLocalState = NO; |
449 |
} |
450 |
return self; |
451 |
} |
452 |
|
453 |
- (void)encodeWithCoder:(NSCoder *)encoder { |
454 |
[encoder encodeObject:uniqueName forKey:@"uniqueName"]; |
455 |
[encoder encodeBool:active forKey:@"active"]; |
456 |
[encoder encodeObject:name forKey:@"name"]; |
457 |
|
458 |
[encoder encodeBool:syncActive forKey:@"syncActive"]; |
459 |
[encoder encodeObject:syncDirectoryPath forKey:@"syncDirectoryPath"]; |
460 |
[encoder encodeObject:syncContainersDictionary forKey:@"syncContainersDictionary"]; |
461 |
[encoder encodeObject:self.syncLastCompleted forKey:@"syncLastCompleted"]; |
462 |
|
463 |
[encoder encodeObject:serverURL forKey:@"serverURL"]; |
464 |
[encoder encodeObject:versionResource forKey:@"versionResource"]; |
465 |
[encoder encodeObject:publicResource forKey:@"publicResource"]; |
466 |
[encoder encodeObject:loginResource forKey:@"loginResource"]; |
467 |
|
468 |
[encoder encodeObject:authUser forKey:@"authUser"]; |
469 |
[encoder encodeObject:authToken forKey:@"authToken"]; |
470 |
[encoder encodeObject:storageURLPrefix forKey:@"storageURLPrefix"]; |
471 |
[encoder encodeObject:authURL forKey:@"authURL"]; |
472 |
[encoder encodeObject:publicURLPrefix forKey:@"publicURLPrefix"]; |
473 |
[encoder encodeObject:loginURLPrefix forKey:@"loginURLPrefix"]; |
474 |
} |
475 |
|
476 |
@end |