// // PithosLocalObjectState.m // pithos-macos // // Copyright 2011 GRNET S.A. All rights reserved. // // Redistribution and use in source and binary forms, with or // without modification, are permitted provided that the following // conditions are met: // // 1. Redistributions of source code must retain the above // copyright notice, this list of conditions and the following // disclaimer. // // 2. Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and // documentation are those of the authors and should not be // interpreted as representing official policies, either expressed // or implied, of GRNET S.A. #import "PithosLocalObjectState.h" #import "PithosUtilities.h" #import "HashMapHash.h" @implementation PithosLocalObjectState @synthesize filePath, isDirectory, hash, tmpFilePath, fileModificationDate, fileSize; #pragma mark - #pragma mark Object Lifecycle - (id)initWithFile:(NSString *)aFilePath blockHash:(NSString *)blockHash blockSize:(NSUInteger)blockSize { if ((self = [self init])) { self.filePath = aFilePath; if ([[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory] && !isDirectory) { self.hash = [HashMapHash calculateHashMapHash:[HashMapHash calculateObjectHashMap:filePath withBlockHash:blockHash andBlockSize:blockSize]]; } } return self; } - (id)initWithHash:(NSString *)aHash directory:(BOOL)anIsDirectory { if ((self = [self init])) { if (anIsDirectory) isDirectory = YES; else if ([aHash length] == 64) self.hash = aHash; } return self; } + (id)localObjectState { return [[self alloc] init]; } + (id)localObjectStateWithFile:(NSString *)aFilePath blockHash:(NSString *)blockHash blockSize:(NSUInteger)blockSize { return [[self alloc] initWithFile:aFilePath blockHash:blockHash blockSize:blockSize]; } + (id)localObjectStateWithHash:(NSString *)aHash directory:(BOOL)anIsDirectory { return [[self alloc] initWithHash:aHash directory:anIsDirectory]; } - (void)dealloc { self.tmpFilePath = nil; } - (NSString *)description { return [NSString stringWithFormat:@"hash: %@, filePath: %@, isDirectory: %d, fileModificationDate: %@, fileSize: %@", hash, filePath, isDirectory, fileModificationDate, fileSize]; } - (BOOL)isEqualToState:(PithosLocalObjectState *)aState { if (self.isDirectory) // Object is a directory, check the other return aState.isDirectory; else if (aState.isDirectory) // Object is not a directory, while the other is return NO; else if (![self exists]) // Object doesn't exist, check the other return (![aState exists]); else if (![aState exists]) // Object exists, while the other doesn't return NO; else // Both objects exist, check that they have the same hash return [self.hash isEqualToString:aState.hash]; } #pragma mark - #pragma mark Properties - (void)setIsDirectory:(BOOL)anIsDirectory { isDirectory = anIsDirectory; if (isDirectory) { self.hash = nil; self.tmpFilePath = nil; } } - (void)setTmpFilePath:(NSString *)aTmpFilePath { if (![tmpFilePath isEqualToString:aTmpFilePath]) { if (!aTmpFilePath) { NSFileManager *fileManager = [NSFileManager defaultManager]; if ([fileManager fileExistsAtPath:tmpFilePath]) { NSError *error = nil; if (![fileManager removeItemAtPath:tmpFilePath error:&error] || error) [PithosUtilities fileActionFailedAlertWithTitle:@"Remove File Error" message:[NSString stringWithFormat:@"Cannot remove file at '%@'", tmpFilePath] error:error]; } } tmpFilePath = aTmpFilePath; } } - (void)setHash:(NSString *)aHash { if ([aHash length] == 64) hash = aHash; else hash = nil; if (filePath) { NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil]; self.fileModificationDate = [attributes objectForKey:NSFileModificationDate]; self.fileSize = [attributes objectForKey:NSFileSize]; } else { self.fileModificationDate = nil; self.fileSize = nil; } } #pragma mark - #pragma mark Methods - (BOOL)exists { return (isDirectory || hash); } - (BOOL)isModified { NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil]; return (![fileSize isEqualToNumber:[attributes objectForKey:NSFileSize]] || ![fileModificationDate isEqualToDate:[attributes objectForKey:NSFileModificationDate]]); } #pragma mark - #pragma mark NSCoding - (id)initWithCoder:(NSCoder *)decoder { if ((self = [super init])) { self.hash = [decoder decodeObjectForKey:@"hash"]; self.filePath = [decoder decodeObjectForKey:@"filePath"]; self.isDirectory = [decoder decodeBoolForKey:@"isDirectory"]; self.tmpFilePath = [decoder decodeObjectForKey:@"tmpFilePath"]; self.fileModificationDate = [decoder decodeObjectForKey:@"fileModificationDate"]; self.fileSize = [decoder decodeObjectForKey:@"fileSize"]; } return self; } - (void)encodeWithCoder:(NSCoder *)encoder { [encoder encodeObject:hash forKey:@"hash"]; [encoder encodeObject:filePath forKey:@"filePath"]; [encoder encodeBool:isDirectory forKey:@"isDirectory"]; [encoder encodeObject:tmpFilePath forKey:@"tmpFilePath"]; [encoder encodeObject:fileModificationDate forKey:@"fileModificationDate"]; [encoder encodeObject:fileSize forKey:@"fileSize"]; } @end