OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 6 #error "This file requires ARC support." |
| 7 #endif |
| 8 |
| 9 #import "remoting/ios/data_store.h" |
| 10 |
| 11 @interface DataStore (Private) |
| 12 - (NSString*)itemArchivePath; |
| 13 @end |
| 14 |
| 15 @implementation DataStore { |
| 16 @private |
| 17 NSMutableArray* _allHosts; |
| 18 NSManagedObjectContext* _context; |
| 19 NSManagedObjectModel* _model; |
| 20 } |
| 21 |
| 22 // Create or Get a static data store |
| 23 + (DataStore*)sharedStore { |
| 24 static DataStore* sharedStore = nil; |
| 25 static dispatch_once_t onceToken; |
| 26 dispatch_once(&onceToken, |
| 27 ^{ sharedStore = [[super allocWithZone:nil] init]; }); |
| 28 |
| 29 return sharedStore; |
| 30 } |
| 31 |
| 32 // General methods |
| 33 + (id)allocWithZone:(NSZone*)zone { |
| 34 return [self sharedStore]; |
| 35 } |
| 36 |
| 37 // Load data store from SQLLite backing store |
| 38 - (id)init { |
| 39 self = [super init]; |
| 40 |
| 41 if (self) { |
| 42 // Read in ChromotingModel.xdatamodeld |
| 43 _model = [NSManagedObjectModel mergedModelFromBundles:nil]; |
| 44 |
| 45 NSPersistentStoreCoordinator* psc = [[NSPersistentStoreCoordinator alloc] |
| 46 initWithManagedObjectModel:_model]; |
| 47 |
| 48 NSString* path = [self itemArchivePath]; |
| 49 NSURL* storeUrl = [NSURL fileURLWithPath:path]; |
| 50 |
| 51 NSError* error = nil; |
| 52 |
| 53 NSDictionary* tryOptions = @{ |
| 54 NSMigratePersistentStoresAutomaticallyOption : @YES, |
| 55 NSInferMappingModelAutomaticallyOption : @YES |
| 56 }; |
| 57 NSDictionary* makeOptions = |
| 58 @{NSMigratePersistentStoresAutomaticallyOption : @YES}; |
| 59 |
| 60 if (![psc addPersistentStoreWithType:NSSQLiteStoreType |
| 61 configuration:nil |
| 62 URL:storeUrl |
| 63 options:tryOptions |
| 64 error:&error]) { |
| 65 // An incompatible version of the store exists, delete it and start over |
| 66 [[NSFileManager defaultManager] removeItemAtURL:storeUrl error:nil]; |
| 67 |
| 68 [psc addPersistentStoreWithType:NSSQLiteStoreType |
| 69 configuration:nil |
| 70 URL:storeUrl |
| 71 options:makeOptions |
| 72 error:&error]; |
| 73 [NSException raise:@"Open failed" |
| 74 format:@"Reason: %@", [error localizedDescription]]; |
| 75 } |
| 76 |
| 77 // Create the managed object context |
| 78 _context = [[NSManagedObjectContext alloc] init]; |
| 79 [_context setPersistentStoreCoordinator:psc]; |
| 80 |
| 81 // The managed object context can manage undo, but we don't need it |
| 82 [_context setUndoManager:nil]; |
| 83 |
| 84 _allHosts = nil; |
| 85 } |
| 86 return self; |
| 87 } |
| 88 |
| 89 // Committing to backing store |
| 90 - (BOOL)saveChanges { |
| 91 NSError* err = nil; |
| 92 BOOL successful = [_context save:&err]; |
| 93 return successful; |
| 94 } |
| 95 |
| 96 // Looking up the backing store path |
| 97 - (NSString*)itemArchivePath { |
| 98 NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains( |
| 99 NSDocumentDirectory, NSUserDomainMask, YES); |
| 100 |
| 101 // Get one and only document directory from that list |
| 102 NSString* documentDirectory = [documentDirectories objectAtIndex:0]; |
| 103 |
| 104 return [documentDirectory stringByAppendingPathComponent:@"store.data"]; |
| 105 } |
| 106 |
| 107 // Return an array of all known hosts, if the list hasn't been loaded yet, then |
| 108 // load it now |
| 109 - (NSArray*)allHosts { |
| 110 if (!_allHosts) { |
| 111 NSFetchRequest* request = [[NSFetchRequest alloc] init]; |
| 112 |
| 113 NSEntityDescription* e = |
| 114 [[_model entitiesByName] objectForKey:@"HostPreferences"]; |
| 115 |
| 116 [request setEntity:e]; |
| 117 |
| 118 NSError* error; |
| 119 NSArray* result = [_context executeFetchRequest:request error:&error]; |
| 120 if (!result) { |
| 121 [NSException raise:@"Fetch failed" |
| 122 format:@"Reason: %@", [error localizedDescription]]; |
| 123 } |
| 124 _allHosts = [result mutableCopy]; |
| 125 } |
| 126 |
| 127 return _allHosts; |
| 128 } |
| 129 |
| 130 // Return a HostPreferences if it already exists, otherwise create a new |
| 131 // HostPreferences to use |
| 132 - (const HostPreferences*)createHost:(NSString*)hostId { |
| 133 |
| 134 const HostPreferences* p = [self getHostForId:hostId]; |
| 135 |
| 136 if (p == nil) { |
| 137 p = [NSEntityDescription insertNewObjectForEntityForName:@"HostPreferences" |
| 138 inManagedObjectContext:_context]; |
| 139 p.hostId = hostId; |
| 140 [_allHosts addObject:p]; |
| 141 } |
| 142 return p; |
| 143 } |
| 144 |
| 145 - (void)removeHost:(HostPreferences*)p { |
| 146 [_context deleteObject:p]; |
| 147 [_allHosts removeObjectIdenticalTo:p]; |
| 148 } |
| 149 |
| 150 // Search the store for any matching HostPreferences |
| 151 // return the 1st match or nil |
| 152 - (const HostPreferences*)getHostForId:(NSString*)hostId { |
| 153 NSFetchRequest* request = [[NSFetchRequest alloc] init]; |
| 154 |
| 155 NSEntityDescription* e = |
| 156 [[_model entitiesByName] objectForKey:@"HostPreferences"]; |
| 157 [request setEntity:e]; |
| 158 |
| 159 NSPredicate* predicate = |
| 160 [NSPredicate predicateWithFormat:@"(hostId = %@)", hostId]; |
| 161 [request setPredicate:predicate]; |
| 162 |
| 163 NSError* error; |
| 164 NSArray* result = [_context executeFetchRequest:request error:&error]; |
| 165 if (!result) { |
| 166 [NSException raise:@"Fetch failed" |
| 167 format:@"Reason: %@", [error localizedDescription]]; |
| 168 } |
| 169 |
| 170 for (HostPreferences* curHost in result) { |
| 171 return curHost; |
| 172 } |
| 173 return nil; |
| 174 } |
| 175 |
| 176 @end |
OLD | NEW |