示例#1
0
 /// <summary>
 /// Solve the specified situation by using localFile and remote object.
 /// </summary>
 /// <param name="localFileSystemInfo">Local filesystem info instance.</param>
 /// <param name="remoteId">Remote identifier or object.</param>
 /// <param name="localContent">Hint if the local content has been changed.</param>
 /// <param name="remoteContent">Information if the remote content has been changed.</param>
 public override void Solve(
     IFileSystemInfo localFileSystemInfo,
     IObjectId remoteId,
     ContentChangeType localContent,
     ContentChangeType remoteContent)
 {
     if (localFileSystemInfo is IDirectoryInfo)
     {
         IDirectoryInfo localFolder    = localFileSystemInfo as IDirectoryInfo;
         IDirectoryInfo localParent    = localFolder.Parent;
         IFolder        remoteFolder   = remoteId as IFolder;
         string         remoteParentId = remoteFolder.ParentId;
         IMappedObject  mappedParent   = this.Storage.GetObjectByRemoteId(remoteFolder.ParentId);
         IMappedObject  mappedObject   = this.Storage.GetObjectByRemoteId(remoteFolder.Id);
         if (localParent.Uuid == mappedParent.Guid)
         {
             // Both folders are in the same parent folder
             this.SyncNamesAndDates(localFolder, remoteFolder, mappedObject);
         }
         else
         {
             throw new NotImplementedException();
         }
     }
     else
     {
         throw new NotImplementedException();
     }
 }
 /// <summary>
 /// Solve the specified situation by using localFile and remote object.
 /// </summary>
 /// <param name="localFileSystemInfo">Local filesystem info instance.</param>
 /// <param name="remoteId">Remote identifier or object.</param>
 /// <param name="localContent">Hint if the local content has been changed.</param>
 /// <param name="remoteContent">Information if the remote content has been changed.</param>
 public override void Solve(
     IFileSystemInfo localFileSystemInfo,
     IObjectId remoteId,
     ContentChangeType localContent,
     ContentChangeType remoteContent)
 {
     if (localFileSystemInfo is IDirectoryInfo)
     {
         IDirectoryInfo localFolder    = localFileSystemInfo as IDirectoryInfo;
         IDirectoryInfo localParent    = localFolder.Parent;
         IFolder        remoteFolder   = remoteId as IFolder;
         string         remoteParentId = remoteFolder.ParentId;
         IMappedObject  mappedParent   = this.Storage.GetObjectByRemoteId(remoteParentId);
         IMappedObject  mappedObject   = this.Storage.GetObjectByRemoteId(remoteFolder.Id);
         if (localParent.Uuid == mappedParent.Guid)
         {
             // Both folders are in the same parent folder
             this.SyncNamesAndDates(localFolder, remoteFolder, mappedObject);
         }
         else
         {
             OperationsLogger.Warn(
                 string.Format(
                     "Synchronization Conflict: The local directory {0} has been moved to {1} with id {2},{4}" +
                     "but the remote folder was moved to {3}{4}You can fix this situation by moving them into the same folder",
                     localFileSystemInfo.Name,
                     localFileSystemInfo.FullName,
                     remoteFolder.Path,
                     Environment.NewLine));
             return;
         }
     }
     else if (localFileSystemInfo is IFileInfo)
     {
         IFileInfo      localFile      = localFileSystemInfo as IFileInfo;
         IDirectoryInfo localParent    = localFile.Directory;
         IDocument      remoteFile     = remoteId as IDocument;
         string         remoteParentId = remoteFile.Parents[0].Id;
         IMappedObject  mappedParent   = this.Storage.GetObjectByRemoteId(remoteParentId);
         IMappedObject  mappedObject   = this.Storage.GetObjectByRemoteId(remoteFile.Id);
         if (localParent.Uuid == mappedParent.Guid)
         {
             // Both files are in the same parent folder
             this.SyncNamesAndDates(localFile, remoteFile, mappedObject);
             return;
         }
         else
         {
             OperationsLogger.Warn(
                 string.Format(
                     "Synchronization Conflict: The local file {0} has been moved to {1} with id {2},{4}" +
                     "but the remote file was moved to {3}{4}You can fix this situation by moving them into the same folder",
                     localFileSystemInfo.Name,
                     localFileSystemInfo.FullName,
                     remoteFile.Paths[0],
                     Environment.NewLine));
             return;
         }
     }
 }
        private void HandleAsIFolder(ContentChangeEvent contentChangeEvent)
        {
            IFolder folder = contentChangeEvent.CmisObject as IFolder;

            IMappedObject  dir         = this.storage.GetObjectByRemoteId(folder.Id);
            IDirectoryInfo dirInfo     = (dir == null) ? null : this.fsFactory.CreateDirectoryInfo(this.storage.GetLocalPath(dir));
            var            folderEvent = new FolderEvent(dirInfo, folder, this);

            switch (contentChangeEvent.Type)
            {
            case DotCMIS.Enums.ChangeType.Created:
                Logger.Debug("Created Folder Event");
                folderEvent.Remote = MetaDataChangeType.CREATED;
                break;

            case DotCMIS.Enums.ChangeType.Updated:
                folderEvent.Remote = MetaDataChangeType.CHANGED;
                break;

            case DotCMIS.Enums.ChangeType.Security:
                folderEvent.Remote = MetaDataChangeType.CHANGED;
                break;
            }

            Queue.AddEvent(folderEvent);
        }
示例#4
0
        public CrawlEventCollection GenerateEvents(DescendantsTreeCollection trees)
        {
            IObjectTree <IMappedObject>       storedTree = trees.StoredTree;
            IObjectTree <IFileSystemInfo>     localTree  = trees.LocalTree;
            IObjectTree <IFileableCmisObject> remoteTree = trees.RemoteTree;
            CrawlEventCollection createdEvents           = new CrawlEventCollection();
            List <IMappedObject> storedObjectsForRemote  = storedTree.ToList();
            List <IMappedObject> storedObjectsForLocal   = new List <IMappedObject>(storedObjectsForRemote);

            Dictionary <string, Tuple <AbstractFolderEvent, AbstractFolderEvent> > eventMap = new Dictionary <string, Tuple <AbstractFolderEvent, AbstractFolderEvent> >();

            createdEvents.creationEvents = this.remoteEventGenerator.CreateEvents(storedObjectsForRemote, remoteTree, eventMap);
            createdEvents.creationEvents.AddRange(this.localEventGenerator.CreateEvents(storedObjectsForLocal, localTree, eventMap));

            createdEvents.mergableEvents = eventMap;

            IMappedObject rootNode = storedTree.Item;

            storedObjectsForLocal.Remove(rootNode);
            storedObjectsForRemote.Remove(rootNode);

            createdEvents.removedLocalObjects  = this.TransformToFileSystemInfoDict(storedObjectsForLocal);
            createdEvents.removedRemoteObjects = this.TransformToFileSystemInfoDict(storedObjectsForRemote);

            return(createdEvents);
        }
示例#5
0
        private string GetParentId(IFileSystemInfo fileInfo, IMetaDataStorage storage)
        {
            IDirectoryInfo parent = null;

            if (fileInfo is IDirectoryInfo)
            {
                IDirectoryInfo localDirInfo = fileInfo as IDirectoryInfo;
                parent = localDirInfo.Parent;
            }
            else
            {
                IFileInfo localFileInfo = fileInfo as IFileInfo;
                parent = localFileInfo.Directory;
            }

            try {
                Guid uuid;
                if (Guid.TryParse(parent.GetExtendedAttribute(MappedObject.ExtendedAttributeKey), out uuid))
                {
                    return(storage.GetObjectByGuid(uuid).RemoteObjectId);
                }
            } catch (IOException) {
            }

            IMappedObject mappedParent = storage.GetObjectByLocalPath(parent);

            return(mappedParent.RemoteObjectId);
        }
示例#6
0
        /// <summary>
        /// Gets the local path. Return null if not exists.
        /// </summary>
        /// <returns>
        /// The local path.
        /// </returns>
        /// <param name='mappedObject'>
        /// Mapped object. Must not be null.
        /// </param>
        public string GetLocalPath(IMappedObject mappedObject)
        {
            string id = this.GetId(mappedObject);

            using (var tran = this.engine.GetTransaction()) {
                string[] segments = this.GetRelativePathSegments(tran, id);
                if (segments == null)
                {
                    return(null);
                }

                if (segments.Length > 0 && segments[0].Equals("/"))
                {
                    string[] temp = new string[segments.Length - 1];
                    for (int i = 1; i < segments.Length; i++)
                    {
                        temp[i - 1] = segments[i];
                    }

                    segments = temp;
                }

                return(Path.Combine(this.matcher.LocalTargetRootPath, Path.Combine(segments)));
            }
        }
示例#7
0
        /// <summary>
        ///  Gets the children of the given parent object.
        /// </summary>
        /// <returns>
        ///  The saved children.
        /// </returns>
        /// <param name='parent'>
        ///  Parent of the children.
        /// </param>
        public List <IMappedObject> GetChildren(IMappedObject parent)
        {
            string parentId = this.GetId(parent);
            List <IMappedObject> results = new List <IMappedObject>();
            bool parentExists            = false;

            using (var tran = this.engine.GetTransaction()) {
                foreach (var row in tran.SelectForward <string, DbCustomSerializer <MappedObject> >(MappedObjectsTable))
                {
                    var data = row.Value.Get;
                    if (data == null)
                    {
                        continue;
                    }

                    if (parentId == data.ParentId)
                    {
                        results.Add(new MappedObject(data));
                    }
                    else if (data.RemoteObjectId == parentId)
                    {
                        parentExists = true;
                    }
                }
            }

            if (!parentExists)
            {
                throw new EntryNotFoundException();
            }

            return(results);
        }
        /// <summary>
        /// Determines if file content is changed to the specified obj.
        /// </summary>
        /// <returns><c>true</c> if is the file content is different to the specified obj otherwise, <c>false</c>.</returns>
        /// <param name="file">File instance.</param>
        /// <param name="obj">Object to check the file content against.</param>
        /// <param name="actualHash">Contains the hash of the local file if scanned, or null if file wasn't scanned</param>
        /// <param name="scanOnlyIfModificationDateDiffers">If set to <c>true</c> content scan runs only if the modification date differs to given one.</param>
        public static bool IsContentChangedTo(this IFileInfo file, IMappedObject obj, out byte[] actualHash, bool scanOnlyIfModificationDateDiffers = false) {
            actualHash = null;
            if (obj == null) {
                throw new ArgumentNullException("obj");
            }

            if (obj.LastContentSize < 0) {
                throw new ArgumentOutOfRangeException(string.Format("Given LastContentSize {0} is invalid for files", obj.LastContentSize.ToString()));
            }

            if (!file.Exists) {
                throw new FileNotFoundException(string.Format("File {0} does not exists", file.FullName));
            }

            if (obj.LastChecksum == null) {
                return true;
            }

            if (file.Length == obj.LastContentSize) {
                if (scanOnlyIfModificationDateDiffers && obj.LastLocalWriteTimeUtc == file.LastWriteTimeUtc) {
                    return false;
                } else {
                    using (var f = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) {
                        byte[] fileHash = SHA1Managed.Create().ComputeHash(f);
                        actualHash = fileHash;
                        return !fileHash.SequenceEqual(obj.LastChecksum);
                    }
                }
            } else {
                return true;
            }
        }
示例#9
0
        /// <summary>
        /// Saves the mapped object.
        /// </summary>
        /// <param name='obj'>
        /// The MappedObject instance.
        /// </param>
        /// <exception cref="DublicateGuidException">Is thrown when guid already in database</exception>
        public void SaveMappedObject(IMappedObject obj)
        {
            string id = this.GetId(obj);

            using (var tran = this.engine.GetTransaction()) {
                var byteGuid = obj.Guid.ToByteArray();
                var row      = tran.Select <byte[], string>(MappedObjectsGuidsTable, byteGuid);
                if (row.Exists && row.Value != id)
                {
                    tran.Rollback();
                    throw new DublicateGuidException(string.Format("An entry with Guid {0} already exists", obj.Guid));
                }

                if (this.fullValidationOnEachManipulation && obj.ParentId != null)
                {
                    DbCustomSerializer <MappedObject> value = tran.Select <string, DbCustomSerializer <MappedObject> >(MappedObjectsTable, obj.ParentId).Value;
                    if (value == null)
                    {
                        tran.Rollback();
                        throw new InvalidDataException();
                    }
                }

                obj.LastTimeStoredInStorage = DateTime.UtcNow;
                tran.Insert <string, DbCustomSerializer <MappedObject> >(MappedObjectsTable, id, obj as MappedObject);
                if (!obj.Guid.Equals(Guid.Empty))
                {
                    tran.Insert <byte[], string>(MappedObjectsGuidsTable, obj.Guid.ToByteArray(), id);
                }

                tran.Commit();
            }

            this.ValidateObjectStructureIfFullValidationIsEnabled();
        }
        private void HandleDeletion(ContentChangeEvent contentChangeEvent)
        {
            Logger.Debug(contentChangeEvent.ObjectId);
            IMappedObject savedObject = this.storage.GetObjectByRemoteId(contentChangeEvent.ObjectId);

            if (savedObject != null)
            {
                IMappedObject obj = savedObject as IMappedObject;
                if (obj != null)
                {
                    if (obj.Type == MappedObjectType.Folder)
                    {
                        var dirInfo = this.fsFactory.CreateDirectoryInfo(this.storage.GetLocalPath(obj));
                        Queue.AddEvent(new FolderEvent(dirInfo, null, this)
                        {
                            Remote = MetaDataChangeType.DELETED
                        });
                        return;
                    }
                    else
                    {
                        var fileInfo = this.fsFactory.CreateFileInfo(this.storage.GetLocalPath(obj));
                        Queue.AddEvent(new FileEvent(fileInfo, null)
                        {
                            Remote = MetaDataChangeType.DELETED
                        });
                        return;
                    }
                }
            }

            Logger.Debug("nothing found in local storage; it has never been synced");
        }
示例#11
0
        private string GetParentId(IFileSystemInfo fileInfo, IMetaDataStorage storage)
        {
            IDirectoryInfo parent = null;

            if (fileInfo is IDirectoryInfo)
            {
                IDirectoryInfo localDirInfo = fileInfo as IDirectoryInfo;
                parent = localDirInfo.Parent;
            }
            else
            {
                IFileInfo localFileInfo = fileInfo as IFileInfo;
                parent = localFileInfo.Directory;
            }

            try {
                Guid?uuid = parent.Uuid;
                if (uuid != null)
                {
                    return(storage.GetObjectByGuid((Guid)uuid).RemoteObjectId);
                }
            } catch (IOException) {
            }

            IMappedObject mappedParent = storage.GetObjectByLocalPath(parent);

            return(mappedParent.RemoteObjectId);
        }
        /// <summary>
        /// Creates the local events and returns the creationEvents, the other Events are stored in the eventMap, handled objects are removed from storedObjects
        /// </summary>
        /// <returns>
        /// The local events.
        /// </returns>
        /// <param name='storedObjects'>
        /// Stored objects.
        /// </param>
        /// <param name='localTree'>
        /// Local tree.
        /// </param>
        /// <param name='eventMap'>
        /// Event map.
        /// </param>
        public List <AbstractFolderEvent> CreateEvents(
            List <IMappedObject> storedObjects,
            IObjectTree <IFileSystemInfo> localTree,
            Dictionary <string, Tuple <AbstractFolderEvent, AbstractFolderEvent> > eventMap)
        {
            List <AbstractFolderEvent> creationEvents = new List <AbstractFolderEvent>();
            var           parent       = localTree.Item;
            IMappedObject storedParent = null;
            Guid?         guid         = parent.Uuid;

            if (guid != null)
            {
                storedParent = storedObjects.Find(o => o.Guid.Equals((Guid)guid));
            }

            foreach (var child in localTree.Children)
            {
                bool removeStoredMappedChild = false;

                IMappedObject storedMappedChild = this.FindStoredObjectByFileSystemInfo(storedObjects, child.Item);
                if (storedMappedChild != null)
                {
                    var localPath = this.storage.GetLocalPath(storedMappedChild);
                    #if __COCOA__
                    if ((!localPath.Normalize(NormalizationForm.FormD).Equals(child.Item.FullName.Normalize(NormalizationForm.FormD))) && this.fsFactory.IsDirectory(localPath) != null)
                    {
                    #else
                    if ((!localPath.Equals(child.Item.FullName)) && this.fsFactory.IsDirectory(localPath) != null)
                    {
                    #endif
                        // Copied
                        creationEvents.Add(this.GenerateCreatedEvent(child.Item));
                    }
                    else
                    {
                        // Moved, Renamed, Updated or Equal
                        AbstractFolderEvent correspondingRemoteEvent = GetCorrespondingRemoteEvent(eventMap, storedMappedChild);
                        AbstractFolderEvent createdEvent             = this.CreateLocalEventBasedOnStorage(child.Item, storedParent, storedMappedChild);

                        eventMap[storedMappedChild.RemoteObjectId] = new Tuple <AbstractFolderEvent, AbstractFolderEvent>(createdEvent, correspondingRemoteEvent);
                        removeStoredMappedChild = true;
                    }
                }
                else
                {
                    // Added
                    creationEvents.Add(this.GenerateCreatedEvent(child.Item));
                }

                creationEvents.AddRange(this.CreateEvents(storedObjects, child, eventMap));

                if (removeStoredMappedChild)
                {
                    storedObjects.Remove(storedMappedChild);
                }
            }

            return(creationEvents);
        }
        private static bool VerifyMappedObject(
            IMappedObject o,
            MappedObjectType type,
            string remoteId,
            string name,
            string parentId,
            string changeToken,
            bool extendedAttributeAvailable,
            DateTime?lastLocalModification,
            DateTime?lastRemoteModification,
            byte[] checksum,
            long contentSize,
            bool ignored)
        {
            Assert.That(o.RemoteObjectId, Is.EqualTo(remoteId), "Object remote Id is wrong");
            Assert.That(o.Name, Is.EqualTo(name), "Object name is wrong");
            Assert.That(o.ParentId, Is.EqualTo(parentId), "Object parent Id is wrong");
            Assert.That(o.LastChangeToken, Is.EqualTo(changeToken), "Object change token is wrong");
            Assert.That(o.Type, Is.EqualTo(type), "Object type is wrong");
            Assert.That(o.Ignored, Is.EqualTo(ignored), "Object ignore flag is wrong");
            if (extendedAttributeAvailable)
            {
                Assert.That(o.Guid, Is.Not.EqualTo(Guid.Empty), "Given Guid must not be empty");
            }
            else
            {
                Assert.That(o.Guid, Is.EqualTo(Guid.Empty), "Given Guid must be empty");
            }

            if (lastLocalModification != null)
            {
                Assert.That(o.LastLocalWriteTimeUtc, Is.EqualTo(lastLocalModification), "Last local modification date is wrong");
            }

            if (lastRemoteModification != null)
            {
                Assert.That(o.LastRemoteWriteTimeUtc, Is.EqualTo(lastRemoteModification), "Last remote modification date is wrong");
            }

            if (checksum != null)
            {
                Assert.That(o.ChecksumAlgorithmName, Is.EqualTo("SHA-1"));
                Assert.That(o.LastChecksum, Is.EqualTo(checksum), "Given checksum is not equal to last saved checksum");
            }

            if (type == MappedObjectType.File)
            {
                Assert.That(o.LastContentSize, Is.GreaterThanOrEqualTo(0), "Last content size is wrong");
                Assert.That(o.LastContentSize, Is.EqualTo(contentSize), "Last content size is wrong");
            }

            if (type == MappedObjectType.Folder)
            {
                Assert.That(o.LastContentSize, Is.EqualTo(-1), "Folder content size is wrong");
            }

            return(true);
        }
        /// <summary>
        /// Solve the specified situation by using the session, storage, localFile and remoteId.
        /// If a folder is affected, simply update the local change time of the corresponding local folder.
        /// If it is a file and the changeToken is not equal to the saved, the new content is downloaded.
        /// </summary>
        /// <param name="localFile">Local file.</param>
        /// <param name="remoteId">Remote identifier.</param>
        /// <param name="localContent">Hint if the local content has been changed.</param>
        /// <param name="remoteContent">Information if the remote content has been changed.</param>
        public override void Solve(
            IFileSystemInfo localFile,
            IObjectId remoteId,
            ContentChangeType localContent  = ContentChangeType.NONE,
            ContentChangeType remoteContent = ContentChangeType.NONE)
        {
            IMappedObject obj = this.Storage.GetObjectByRemoteId(remoteId.Id);

            if (remoteId is IFolder)
            {
                var      remoteFolder = remoteId as IFolder;
                DateTime?lastModified = remoteFolder.LastModificationDate;
                obj.LastChangeToken = remoteFolder.ChangeToken;
                if (lastModified != null)
                {
                    try {
                        localFile.LastWriteTimeUtc = (DateTime)lastModified;
                    } catch (IOException e) {
                        Logger.Debug("Couldn't set the server side modification date", e);
                    }

                    obj.Ignored = remoteFolder.AreAllChildrenIgnored();
                    obj.LastLocalWriteTimeUtc = localFile.LastWriteTimeUtc;
                }
            }
            else if (remoteId is IDocument)
            {
                var      remoteDocument = remoteId as IDocument;
                DateTime?lastModified   = remoteDocument.LastModificationDate;
                if ((lastModified != null && lastModified != obj.LastRemoteWriteTimeUtc) || obj.LastChangeToken != remoteDocument.ChangeToken)
                {
                    if (remoteContent != ContentChangeType.NONE)
                    {
                        if (obj.LastLocalWriteTimeUtc != localFile.LastWriteTimeUtc)
                        {
                            throw new ArgumentException("The local file has been changed since last write => aborting update");
                        }

                        obj.LastChecksum = DownloadChanges(localFile as IFileInfo, remoteDocument, obj, this.fsFactory, this.transmissonManager, Logger);
                    }

                    obj.LastRemoteWriteTimeUtc = remoteDocument.LastModificationDate;
                    if (remoteDocument.LastModificationDate != null)
                    {
                        localFile.LastWriteTimeUtc = (DateTime)remoteDocument.LastModificationDate;
                    }

                    obj.LastLocalWriteTimeUtc = localFile.LastWriteTimeUtc;
                    obj.LastContentSize       = remoteDocument.ContentStreamLength ?? 0;
                }

                obj.LastChangeToken        = remoteDocument.ChangeToken;
                obj.LastRemoteWriteTimeUtc = lastModified;
            }

            this.Storage.SaveMappedObject(obj);
        }
示例#15
0
 private bool VerifySavedFolder(IMappedObject folder, MappedObjectType type, string id, string name, string parentId, string changeToken, DateTime modifiedTime)
 {
     Assert.That(folder.Type, Is.EqualTo(type));
     Assert.That(folder.RemoteObjectId, Is.EqualTo(id));
     Assert.That(folder.ParentId, Is.EqualTo(parentId));
     Assert.That(folder.Name, Is.EqualTo(name));
     Assert.That(folder.LastChangeToken, Is.EqualTo(changeToken));
     Assert.That(folder.LastRemoteWriteTimeUtc, Is.EqualTo(modifiedTime));
     return(true);
 }
示例#16
0
 public static void AddMappedFile(this Mock <IMetaDataStorage> db, IMappedObject file, string localPath = null, string remotePath = null)
 {
     db.Setup(foo => foo.GetObjectByLocalPath(It.Is <IFileInfo>(f => f.FullName == localPath))).Returns(file);
     db.Setup(foo => foo.GetObjectByRemoteId(It.Is <string>(s => s == file.RemoteObjectId))).Returns(file);
     db.Setup(foo => foo.GetLocalPath(It.Is <IMappedObject>(o => o.Equals(file)))).Returns(localPath);
     db.Setup(foo => foo.GetRemotePath(It.Is <IMappedObject>(o => o.Equals(file)))).Returns(remotePath);
     if (!file.Guid.Equals(Guid.Empty))
     {
         db.Setup(foo => foo.GetObjectByGuid(It.Is <Guid>(g => g.Equals(file.Guid)))).Returns(file);
     }
 }
示例#17
0
 // Don't use this method twice per test
 public static void AddMappedFolder(this Mock <IMetaDataStorage> db, IMappedObject folder, string localPath = null, string remotePath = null)
 {
     db.Setup(foo => foo.GetObjectByLocalPath(It.IsAny <IDirectoryInfo>())).Returns(folder);
     db.Setup(foo => foo.GetObjectByRemoteId(It.Is <string>(s => s == folder.RemoteObjectId))).Returns(folder);
     db.Setup(foo => foo.GetLocalPath(It.Is <IMappedObject>(o => o.Equals(folder)))).Returns(localPath);
     db.Setup(foo => foo.GetRemotePath(It.Is <IMappedObject>(o => o.Equals(folder)))).Returns(remotePath);
     if (!folder.Guid.Equals(Guid.Empty))
     {
         db.Setup(foo => foo.GetObjectByGuid(It.Is <Guid>(g => g.Equals(folder.Guid)))).Returns(folder);
     }
 }
 public void SetUp() {
     this.session = new Mock<ISession>();
     this.session.SetupTypeSystem();
     this.storage = new Mock<IMetaDataStorage>();
     this.remoteObject = new Mock<IObjectId>(MockBehavior.Strict);
     this.remoteObject.Setup(o => o.Id).Returns(RemoteId);
     this.deletedFsObject = new Mock<IFileSystemInfo>();
     this.mappedObject = Mock.Of<IMappedObject>(o => o.RemoteObjectId == RemoteId);
     this.underTest = new LocalObjectDeletedRemoteObjectRenamedOrMoved(
         this.session.Object,
         this.storage.Object);
 }
        private void AccumulateEvent(AbstractFolderEvent abstractFolderEvent, IMappedObject storedObject)
        {
            Logger.Debug("Accumulating: " + this.storage.GetLocalPath(storedObject));
            if (abstractFolderEvent is FolderEvent)
            {
                (abstractFolderEvent as FolderEvent).LocalFolder = this.fsFactory.CreateDirectoryInfo(this.storage.GetLocalPath(storedObject));
            }

            if (abstractFolderEvent is FileEvent)
            {
                (abstractFolderEvent as FileEvent).LocalFile = this.fsFactory.CreateFileInfo(this.storage.GetLocalPath(storedObject));
            }
        }
示例#20
0
        /// <summary>
        /// Gets the remote identifier by trying to read the Uuid of the given directory. If this fails or returns null,
        /// the local path is used to request the remote object id from the storage.
        /// </summary>
        /// <returns>The stored remote identifier, or null if there is no entry found.</returns>
        /// <param name="storage">Meta data storage instance.</param>
        /// <param name="info">File system item info.</param>
        public static string GetRemoteId(this IMetaDataStorage storage, IFileSystemInfo info)
        {
            IMappedObject mappedObject = storage.GetObject(info);

            if (mappedObject != null)
            {
                return(mappedObject.RemoteObjectId);
            }
            else
            {
                return(null);
            }
        }
示例#21
0
 public void SetUp()
 {
     this.session = new Mock <ISession>();
     this.session.SetupTypeSystem();
     this.storage      = new Mock <IMetaDataStorage>();
     this.remoteObject = new Mock <IObjectId>(MockBehavior.Strict);
     this.remoteObject.Setup(o => o.Id).Returns(RemoteId);
     this.deletedFsObject = new Mock <IFileSystemInfo>();
     this.mappedObject    = Mock.Of <IMappedObject>(o => o.RemoteObjectId == RemoteId);
     this.underTest       = new LocalObjectDeletedRemoteObjectRenamedOrMoved(
         this.session.Object,
         this.storage.Object);
 }
示例#22
0
        protected byte[] DownloadChanges(IFileInfo target, IDocument remoteDocument, IMappedObject obj, IFileSystemInfoFactory fsFactory, ITransmissionManager transmissionManager, ILog logger)
        {
            // Download changes
            byte[] hash = null;

            var cacheFile    = fsFactory.CreateDownloadCacheFileInfo(target);
            var transmission = transmissionManager.CreateTransmission(TransmissionType.DOWNLOAD_MODIFIED_FILE, target.FullName, cacheFile.FullName);

            hash = this.DownloadCacheFile(cacheFile, remoteDocument, transmission, fsFactory);
            obj.ChecksumAlgorithmName = "SHA-1";

            try {
                var  backupFile = fsFactory.CreateFileInfo(target.FullName + ".bak.sync");
                Guid?uuid       = target.Uuid;
                cacheFile.Replace(target, backupFile, true);
                try {
                    target.Uuid = uuid;
                } catch (RestoreModificationDateException e) {
                    logger.Debug("Failed to restore modification date of original file", e);
                }

                try {
                    backupFile.Uuid = null;
                } catch (RestoreModificationDateException e) {
                    logger.Debug("Failed to restore modification date of backup file", e);
                }

                byte[] checksumOfOldFile = null;
                using (var oldFileStream = backupFile.Open(FileMode.Open, FileAccess.Read, FileShare.None)) {
                    checksumOfOldFile = SHA1Managed.Create().ComputeHash(oldFileStream);
                }

                if (!obj.LastChecksum.SequenceEqual(checksumOfOldFile))
                {
                    var conflictFile = fsFactory.CreateConflictFileInfo(target);
                    backupFile.MoveTo(conflictFile.FullName);
                    OperationsLogger.Info(string.Format("Updated local content of \"{0}\" with content of remote document {1} and created conflict file {2}", target.FullName, remoteDocument.Id, conflictFile.FullName));
                }
                else
                {
                    backupFile.Delete();
                    OperationsLogger.Info(string.Format("Updated local content of \"{0}\" with content of remote document {1}", target.FullName, remoteDocument.Id));
                }
            } catch (Exception ex) {
                transmission.FailedException = ex;
                throw;
            }

            transmission.Status = TransmissionStatus.FINISHED;
            return(hash);
        }
        private static AbstractFolderEvent GetCorrespondingRemoteEvent(
            Dictionary <string, Tuple <AbstractFolderEvent, AbstractFolderEvent> > eventMap,
            IMappedObject storedMappedChild)
        {
            AbstractFolderEvent correspondingRemoteEvent = null;
            Tuple <AbstractFolderEvent, AbstractFolderEvent> tuple;

            if (eventMap.TryGetValue(storedMappedChild.RemoteObjectId, out tuple))
            {
                correspondingRemoteEvent = tuple.Item2;
            }

            return(correspondingRemoteEvent);
        }
 private static bool AssertMappedObjectEqualExceptGUID(IMappedObject expected, IMappedObject actual)
 {
     Assert.AreEqual(actual.ParentId, expected.ParentId);
     Assert.AreEqual(actual.Type, expected.Type);
     Assert.AreEqual(actual.RemoteObjectId, expected.RemoteObjectId);
     Assert.AreEqual(actual.LastChangeToken, expected.LastChangeToken);
     Assert.AreEqual(actual.LastRemoteWriteTimeUtc, expected.LastRemoteWriteTimeUtc);
     Assert.AreEqual(actual.LastLocalWriteTimeUtc, expected.LastLocalWriteTimeUtc);
     Assert.AreEqual(actual.LastChecksum, expected.LastChecksum);
     Assert.AreEqual(actual.ChecksumAlgorithmName, expected.ChecksumAlgorithmName);
     Assert.AreEqual(actual.Name, expected.Name);
     Assert.AreNotEqual(actual.Guid, Guid.Empty);
     return(true);
 }
示例#25
0
        /// <summary>
        /// Gets the remote path.
        /// </summary>
        /// <returns>
        /// The remote path.
        /// </returns>
        /// <param name='obj'>
        /// The MappedObject instance.
        /// </param>
        public string GetRemotePath(IMappedObject obj)
        {
            string id = this.GetId(obj);

            using (var tran = this.engine.GetTransaction()) {
                string[]      segments    = this.GetRelativePathSegments(tran, id);
                StringBuilder pathBuilder = new StringBuilder(this.matcher.RemoteTargetRootPath);
                foreach (var name in segments)
                {
                    pathBuilder.Append("/").Append(name);
                }

                return(this.slashRegex.Replace(pathBuilder.ToString(), @"/"));
            }
        }
示例#26
0
        /// <summary>
        /// Gets the identifier of the given object and throws Exceptions if object or remote object id is null
        /// </summary>
        /// <returns>
        /// The identifier.
        /// </returns>
        /// <param name='obj'>
        /// Object with the containing remote id.
        /// </param>
        private string GetId(IMappedObject obj)
        {
            if (obj == null)
            {
                throw new ArgumentNullException("The given obj is null");
            }

            string id = obj.RemoteObjectId;

            if (id == null)
            {
                throw new ArgumentException("The given object has no remote object id");
            }

            return(id);
        }
示例#27
0
        /// <summary>
        /// Removes the saved object.
        /// </summary>
        /// <param name='obj'>
        /// Object to be removed.
        /// </param>
        public void RemoveObject(IMappedObject obj)
        {
            string id = this.GetId(obj);

            using (var tran = this.engine.GetTransaction()) {
                MappedObject        root    = null;
                List <MappedObject> objects = new List <MappedObject>();
                foreach (var row in tran.SelectForward <string, DbCustomSerializer <MappedObject> >(MappedObjectsTable))
                {
                    var value = row.Value;
                    if (value == null)
                    {
                        continue;
                    }

                    var data = value.Get;
                    if (data == null)
                    {
                        continue;
                    }

                    if (row.Key.Equals(id))
                    {
                        root = data;
                    }
                    else
                    {
                        objects.Add(data);
                    }
                }

                if (root == null)
                {
                    return;
                }

                this.RemoveChildren(tran, root, ref objects);

                tran.RemoveKey <string>(MappedObjectsTable, id);
                tran.RemoveKey <byte[]>(MappedObjectsGuidsTable, root.Guid.ToByteArray());
                tran.Commit();
            }

            this.ValidateObjectStructureIfFullValidationIsEnabled();
        }
示例#28
0
        /// <summary>
        /// Gets the remote path.
        /// </summary>
        /// <returns>
        /// The remote path.
        /// </returns>
        /// <param name='obj'>
        /// The MappedObject instance.
        /// </param>
        public string GetRemotePath(IMappedObject obj)
        {
            Stopwatch watch = Stopwatch.StartNew();
            string    id    = this.GetId(obj);

            using (var tran = this.engine.GetTransaction())
            {
                string[] segments = this.GetRelativePathSegments(tran, id);
                string   path     = this.matcher.RemoteTargetRootPath;
                foreach (var name in segments)
                {
                    path += name.StartsWith("/") ? name : "/" + name;
                }

                watch.Stop();
                Logger.Debug(string.Format("Method GetRemotePath returned after {0} ms", watch.ElapsedMilliseconds));
                return(path.Replace("//", "/"));
            }
        }
示例#29
0
        /// <summary>
        /// Determines if file content is changed to the specified obj.
        /// </summary>
        /// <returns><c>true</c> if is the file content is different to the specified obj otherwise, <c>false</c>.</returns>
        /// <param name="file">File instance.</param>
        /// <param name="obj">Object to check the file content against.</param>
        /// <param name="actualHash">Contains the hash of the local file if scanned, or null if file wasn't scanned</param>
        /// <param name="scanOnlyIfModificationDateDiffers">If set to <c>true</c> content scan runs only if the modification date differs to given one.</param>
        public static bool IsContentChangedTo(this IFileInfo file, IMappedObject obj, out byte[] actualHash, bool scanOnlyIfModificationDateDiffers = false)
        {
            actualHash = null;
            if (obj == null)
            {
                throw new ArgumentNullException("obj");
            }

            if (obj.LastContentSize < 0)
            {
                throw new ArgumentOutOfRangeException(string.Format("Given LastContentSize {0} is invalid for files", obj.LastContentSize.ToString()));
            }

            if (!file.Exists)
            {
                throw new FileNotFoundException(string.Format("File {0} does not exists", file.FullName));
            }

            if (obj.LastChecksum == null)
            {
                return(true);
            }

            if (file.Length == obj.LastContentSize)
            {
                if (scanOnlyIfModificationDateDiffers && obj.LastLocalWriteTimeUtc == file.LastWriteTimeUtc)
                {
                    return(false);
                }
                else
                {
                    using (var f = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) {
                        byte[] fileHash = SHA1Managed.Create().ComputeHash(f);
                        actualHash = fileHash;
                        return(!fileHash.SequenceEqual(obj.LastChecksum));
                    }
                }
            }
            else
            {
                return(true);
            }
        }
示例#30
0
        public static IMappedObject GetObject(this IMetaDataStorage storage, IFileSystemInfo info)
        {
            IMappedObject mappedObject = null;

            try {
                Guid?guid = info.Uuid;
                if (guid != null)
                {
                    mappedObject = storage.GetObjectByGuid((Guid)guid);
                }
            } catch (Exception) {
            }

            if (mappedObject == null)
            {
                mappedObject = storage.GetObjectByLocalPath(info);
            }

            return(mappedObject);
        }
示例#31
0
        /// <summary>
        /// Saves the mapped object.
        /// </summary>
        /// <param name='obj'>
        /// The MappedObject instance.
        /// </param>
        /// <exception cref="DublicateGuidException">Is thrown when guid already in database</exception>
        public void SaveMappedObject(IMappedObject obj)
        {
            string id = this.GetId(obj);

            using (var tran = this.engine.GetTransaction())
            {
                var byteGuid = obj.Guid.ToByteArray();
                var row      = tran.Select <byte[], string>(MappedObjectsGuidsTable, byteGuid);
                if (row.Exists && row.Value != id)
                {
                    tran.Rollback();
                    throw new DublicateGuidException(string.Format("An entry with Guid {0} already exists", obj.Guid));
                }

                tran.Insert <string, DbCustomSerializer <MappedObject> >(MappedObjectsTable, id, obj as MappedObject);
                if (!obj.Guid.Equals(Guid.Empty))
                {
                    tran.Insert <byte[], string>(MappedObjectsGuidsTable, obj.Guid.ToByteArray(), id);
                }

                tran.Commit();
            }
        }
示例#32
0
        /// <summary>
        ///  Gets the children of the given parent object.
        /// </summary>
        /// <returns>
        ///  The saved children.
        /// </returns>
        /// <param name='parent'>
        ///  Parent of the children.
        /// </param>
        public List <IMappedObject> GetChildren(IMappedObject parent)
        {
            Stopwatch            watch    = Stopwatch.StartNew();
            string               parentId = this.GetId(parent);
            List <IMappedObject> results  = new List <IMappedObject>();
            bool parentExists             = false;

            using (var tran = this.engine.GetTransaction())
            {
                foreach (var row in tran.SelectForward <string, DbCustomSerializer <MappedObject> >(MappedObjectsTable))
                {
                    var data = row.Value.Get;
                    if (data == null)
                    {
                        continue;
                    }

                    if (parentId == data.ParentId)
                    {
                        results.Add(new MappedObject(data));
                    }
                    else if (data.RemoteObjectId == parentId)
                    {
                        parentExists = true;
                    }
                }
            }

            if (!parentExists)
            {
                throw new EntryNotFoundException();
            }

            watch.Stop();
            Logger.Debug(string.Format("Method GetChildren returned after {0} ms", watch.ElapsedMilliseconds));
            return(results);
        }
        private static void AddRemoteContentChangeTypeToFileEvent(FileEvent fileEvent, IMappedObject obj, IDocument remoteDoc) {
            if (fileEvent == null || obj == null || remoteDoc == null) {
                return;
            }

            byte[] remoteHash = remoteDoc.ContentStreamHash(obj.ChecksumAlgorithmName);
            if (remoteHash != null && remoteHash.SequenceEqual(obj.LastChecksum)) {
                fileEvent.RemoteContent = ContentChangeType.NONE;
            } else {
                fileEvent.RemoteContent = ContentChangeType.CHANGED;
            }
        }
示例#34
0
        /// <summary>
        /// Gets the remote path.
        /// </summary>
        /// <returns>
        /// The remote path.
        /// </returns>
        /// <param name='obj'>
        /// The MappedObject instance.
        /// </param>
        public string GetRemotePath(IMappedObject obj) {
            string id = this.GetId(obj);
            using(var tran = this.engine.GetTransaction()) {
                string[] segments = this.GetRelativePathSegments(tran, id);
                StringBuilder pathBuilder = new StringBuilder(this.matcher.RemoteTargetRootPath);
                foreach (var name in segments) {
                    pathBuilder.Append("/").Append(name);
                }

                return this.slashRegex.Replace(pathBuilder.ToString(), @"/");
            }
        }
        private static AbstractFolderEvent GetCorrespondingRemoteEvent(
                Dictionary<string, Tuple<AbstractFolderEvent, AbstractFolderEvent>> eventMap,
                IMappedObject storedMappedChild)
        {
            AbstractFolderEvent correspondingRemoteEvent = null;
            Tuple<AbstractFolderEvent, AbstractFolderEvent> tuple;
            if (eventMap.TryGetValue(storedMappedChild.RemoteObjectId, out tuple)) {
                correspondingRemoteEvent = tuple.Item2;
            }

            return correspondingRemoteEvent;
        }
        private AbstractFolderEvent CreateLocalEventBasedOnStorage(IFileSystemInfo fsObject, IMappedObject storedParent, IMappedObject storedMappedChild) {
            AbstractFolderEvent createdEvent = null;
            if (storedParent == null) {
                throw new ArgumentNullException("storedParent", "stored parent is null. Stored child: " + storedMappedChild.ToString() + Environment.NewLine + "local object is: " + fsObject.FullName);
            }

            if (storedMappedChild.ParentId == storedParent.RemoteObjectId) {
                // Renamed, Updated or Equal
                #if __COCOA__
                if (fsObject.Name.Normalize(NormalizationForm.FormD) == storedMappedChild.Name.Normalize(NormalizationForm.FormD) && fsObject.LastWriteTimeUtc == storedMappedChild.LastLocalWriteTimeUtc) {
                #else
                if (fsObject.Name == storedMappedChild.Name &&
                    fsObject.LastWriteTimeUtc == storedMappedChild.LastLocalWriteTimeUtc &&
                    fsObject.ReadOnly == storedMappedChild.IsReadOnly) {
                #endif
                    // Equal
                    createdEvent = null;
                } else {
                    // Updated or Renamed
                    createdEvent = FileOrFolderEventFactory.CreateEvent(null, fsObject, localChange: MetaDataChangeType.CHANGED, src: this);
                }
            } else {
                // Moved
                IFileSystemInfo oldLocalPath = fsObject is IFileInfo ? (IFileSystemInfo)this.fsFactory.CreateFileInfo(this.storage.GetLocalPath(storedMappedChild)) : (IFileSystemInfo)this.fsFactory.CreateDirectoryInfo(this.storage.GetLocalPath(storedMappedChild));
                createdEvent = FileOrFolderEventFactory.CreateEvent(null, fsObject, localChange: MetaDataChangeType.MOVED, oldLocalObject: oldLocalPath, src: this);
            }

            return createdEvent;
        }

        private IMappedObject FindStoredObjectByFileSystemInfo(List<IMappedObject> storedObjects, IFileSystemInfo fsInfo) {
            Guid? childGuid = fsInfo.Uuid;
            if (childGuid != null) {
               return storedObjects.Find(o => o.Guid == (Guid)childGuid);
            }

            return null;
        }
    }
 private static bool AssertMappedObjectEqualExceptGUID(IMappedObject expected, IMappedObject actual) {
     Assert.AreEqual(actual.ParentId, expected.ParentId);
     Assert.AreEqual(actual.Type, expected.Type);
     Assert.AreEqual(actual.RemoteObjectId, expected.RemoteObjectId);
     Assert.AreEqual(actual.LastChangeToken, expected.LastChangeToken);
     Assert.AreEqual(actual.LastRemoteWriteTimeUtc, expected.LastRemoteWriteTimeUtc);
     Assert.AreEqual(actual.LastLocalWriteTimeUtc, expected.LastLocalWriteTimeUtc);
     Assert.AreEqual(actual.LastChecksum, expected.LastChecksum);
     Assert.AreEqual(actual.ChecksumAlgorithmName, expected.ChecksumAlgorithmName);
     Assert.AreEqual(actual.Name, expected.Name);
     Assert.AreNotEqual(actual.Guid, Guid.Empty);
     return true;
 }
        private AbstractFolderEvent CreateRemoteEventBasedOnStorage(IFileableCmisObject cmisObject, IMappedObject storedParent, IMappedObject storedMappedChild)
        {
            AbstractFolderEvent newEvent = null;
            if (storedParent != null && storedMappedChild.ParentId == storedParent.RemoteObjectId) {
                // Renamed or Equal
                if (storedMappedChild.Name == cmisObject.Name) {
                    // Equal or property update
                    if (storedMappedChild.LastChangeToken != cmisObject.ChangeToken) {
                        // Update
                        newEvent = FileOrFolderEventFactory.CreateEvent(cmisObject, null, MetaDataChangeType.CHANGED, src: this);
                        AddRemoteContentChangeTypeToFileEvent(newEvent as FileEvent, storedMappedChild, cmisObject as IDocument);
                    } else {
                        // Equal
                        newEvent = null;
                    }
                } else {
                    // Renamed
                    newEvent = FileOrFolderEventFactory.CreateEvent(cmisObject, null, MetaDataChangeType.CHANGED, src: this);
                    AddRemoteContentChangeTypeToFileEvent(newEvent as FileEvent, storedMappedChild, cmisObject as IDocument);
                }
            } else {
                // Moved
                newEvent = FileOrFolderEventFactory.CreateEvent(cmisObject, null, MetaDataChangeType.MOVED, oldRemotePath: this.storage.GetRemotePath(storedMappedChild), src: this);
                AddRemoteContentChangeTypeToFileEvent(newEvent as FileEvent, storedMappedChild, cmisObject as IDocument);
            }

            return newEvent;
        }
 public byte[] CallUploadFileWithPWC(IFileInfo localFile, ref IDocument doc, Transmission transmission, IMappedObject mappedObject = null) {
     return this.UploadFileWithPWC(localFile, ref doc, transmission, mappedObject);
 }
        private void SyncNamesAndDates(IFileSystemInfo local, IFileableCmisObject remote, IMappedObject mappedObject)
        {
            DateTime? oldRemoteModificationDate = remote.LastModificationDate;
            DateTime oldLocalModificationDate = local.LastWriteTimeUtc;

            // Sync Names
            if (mappedObject.Name != local.Name && mappedObject.Name == remote.Name) {
                // local has been renamed => rename remote
                remote.Rename(local.Name, true);
                mappedObject.Name = local.Name;
            } else if (mappedObject.Name == local.Name && mappedObject.Name != remote.Name) {
                // remote has been renamed => rename local
                if (local is IFileInfo) {
                    IFileInfo localFile = local as IFileInfo;
                    localFile.MoveTo(Path.Combine(localFile.Directory.FullName, remote.Name));
                } else if (local is IDirectoryInfo) {
                    IDirectoryInfo localFolder = local as IDirectoryInfo;
                    localFolder.MoveTo(Path.Combine(localFolder.Parent.FullName, remote.Name));
                } else {
                    throw new ArgumentException("Solved move conflict => invoke crawl sync to detect other changes");
                }

                mappedObject.Name = remote.Name;
            } else if (mappedObject.Name != local.Name && mappedObject.Name != remote.Name) {
                // both are renamed => rename to the latest change
                DateTime localModification = local.LastWriteTimeUtc;
                DateTime remoteModification = (DateTime)remote.LastModificationDate;
                if (localModification > remoteModification) {
                    // local modification is newer
                    remote.Rename(local.Name, true);
                    mappedObject.Name = local.Name;
                } else {
                    // remote modification is newer
                    if (local is IFileInfo) {
                        IFileInfo localFile = local as IFileInfo;
                        localFile.MoveTo(Path.Combine(localFile.Directory.FullName, remote.Name));
                    } else if (local is IDirectoryInfo) {
                        IDirectoryInfo localFolder = local as IDirectoryInfo;
                        localFolder.MoveTo(Path.Combine(localFolder.Parent.FullName, remote.Name));
                    } else {
                        throw new ArgumentException("Solved move conflict => invoke crawl sync to detect other changes");
                    }

                    local.LastWriteTimeUtc = (DateTime)remote.LastModificationDate;
                    mappedObject.Name = remote.Name;
                }
            }

            // Sync modification dates
            if (oldRemoteModificationDate != null) {
                if (oldLocalModificationDate > oldRemoteModificationDate && this.ServerCanModifyDateTimes) {
                    remote.UpdateLastWriteTimeUtc(oldLocalModificationDate);
                    local.LastWriteTimeUtc = oldLocalModificationDate;
                } else if (oldLocalModificationDate < (DateTime)oldRemoteModificationDate) {
                    local.LastWriteTimeUtc = (DateTime)oldRemoteModificationDate;
                }
            }

            mappedObject.LastLocalWriteTimeUtc = local.LastWriteTimeUtc;
            mappedObject.LastRemoteWriteTimeUtc = (DateTime)remote.LastModificationDate;
            mappedObject.ParentId = remote.Parents[0].Id;
            mappedObject.LastChangeToken = remote.ChangeToken;
            mappedObject.Ignored = remote.AreAllChildrenIgnored();
            this.Storage.SaveMappedObject(mappedObject);
        }
 /// <summary>
 /// Determines if file content is changed to the specified obj.
 /// </summary>
 /// <returns><c>true</c> if is the file content is different to the specified obj otherwise, <c>false</c>.</returns>
 /// <param name="file">File instance.</param>
 /// <param name="obj">Object to check the file content against.</param>
 /// <param name="scanOnlyIfModificationDateDiffers">If set to <c>true</c> content scan runs only if the modification date differs to given one.</param>
 public static bool IsContentChangedTo(this IFileInfo file, IMappedObject obj, bool scanOnlyIfModificationDateDiffers = false) {
     byte[] actualHash;
     return file.IsContentChangedTo(obj, out actualHash, scanOnlyIfModificationDateDiffers);
 }
 // Don't use this method twice per test
 public static void AddMappedFolder(this Mock<IMetaDataStorage> db, IMappedObject folder, string localPath = null, string remotePath = null) {
     db.Setup(foo => foo.GetObjectByLocalPath(It.Is<IFileSystemInfo>(d => d.FullName == localPath))).Returns(folder);
     db.Setup(foo => foo.GetObjectByLocalPath(It.Is<IDirectoryInfo>(d => d.FullName == localPath))).Returns(folder);
     db.Setup(foo => foo.GetObjectByLocalPath(It.Is<IFileInfo>(d => d.FullName == localPath))).Returns(folder);
     db.Setup(foo => foo.GetObjectByRemoteId(It.Is<string>(s => s == folder.RemoteObjectId))).Returns(folder);
     db.Setup(foo => foo.GetLocalPath(It.Is<IMappedObject>(o => o.Equals(folder)))).Returns(localPath);
     db.Setup(foo => foo.GetRemotePath(It.Is<IMappedObject>(o => o.Equals(folder)))).Returns(remotePath);
     if (!folder.Guid.Equals(Guid.Empty)) {
         db.Setup(foo => foo.GetObjectByGuid(It.Is<Guid>(g => g.Equals(folder.Guid)))).Returns(folder);
     }
 }
示例#43
0
        /// <summary>
        /// Gets the local path. Return null if not exists.
        /// </summary>
        /// <returns>
        /// The local path.
        /// </returns>
        /// <param name='mappedObject'>
        /// Mapped object. Must not be null.
        /// </param>
        public string GetLocalPath(IMappedObject mappedObject) {
            string id = this.GetId(mappedObject);
            using(var tran = this.engine.GetTransaction()) {
                string[] segments = this.GetRelativePathSegments(tran, id);
                if (segments == null) {
                    return null;
                }

                if (segments.Length > 0 && segments[0].Equals("/")) {
                    string[] temp = new string[segments.Length - 1];
                    for (int i = 1; i < segments.Length; i++) {
                        temp[i - 1] = segments[i];
                    }

                    segments = temp;
                }

                return Path.Combine(this.matcher.LocalTargetRootPath, Path.Combine(segments));
            }
        }
示例#44
0
        /// <summary>
        ///  Gets the children of the given parent object.
        /// </summary>
        /// <returns>
        ///  The saved children.
        /// </returns>
        /// <param name='parent'>
        ///  Parent of the children.
        /// </param>
        public List<IMappedObject> GetChildren(IMappedObject parent) {
            string parentId = this.GetId(parent);
            List<IMappedObject> results = new List<IMappedObject>();
            bool parentExists = false;
            using(var tran = this.engine.GetTransaction()) {
                foreach (var row in tran.SelectForward<string, DbCustomSerializer<MappedObject>>(MappedObjectsTable)) {
                    var data = row.Value.Get;
                    if (data == null) {
                        continue;
                    }

                    if (parentId == data.ParentId) {
                        results.Add(new MappedObject(data));
                    } else if(data.RemoteObjectId == parentId) {
                        parentExists = true;
                    }
                }
            }

            if (!parentExists) {
                throw new EntryNotFoundException();
            }

            return results;
        }
示例#45
0
        /// <summary>
        /// Gets the identifier of the given object and throws Exceptions if object or remote object id is null
        /// </summary>
        /// <returns>
        /// The identifier.
        /// </returns>
        /// <param name='obj'>
        /// Object with the containing remote id.
        /// </param>
        private string GetId(IMappedObject obj) {
            if (obj == null) {
                throw new ArgumentNullException("obj");
            }

            string id = obj.RemoteObjectId;
            if (id == null) {
                throw new ArgumentException("The given object has no remote object id", "obj");
            }

            return id;
        }
        private void AccumulateEvent(AbstractFolderEvent abstractFolderEvent, IMappedObject storedObject) {
            Logger.Debug("Accumulating: " + this.storage.GetLocalPath(storedObject));
            if (abstractFolderEvent is FolderEvent) {
                (abstractFolderEvent as FolderEvent).LocalFolder = this.fsFactory.CreateDirectoryInfo(this.storage.GetLocalPath(storedObject));
            }

            if (abstractFolderEvent is FileEvent) {
                (abstractFolderEvent as FileEvent).LocalFile = this.fsFactory.CreateFileInfo(this.storage.GetLocalPath(storedObject));
            }
        }
        /// <summary>
        /// Uploads the file content to the remote document.
        /// </summary>
        /// <returns>The SHA-1 hash of the uploaded file content.</returns>
        /// <param name="localFile">Local file.</param>
        /// <param name="doc">Remote document.</param>
        /// <param name="transmissionManager">Transmission manager.</param>
        /// <param name="transmissionEvent">File Transmission event.</param>
        /// <param name="mappedObject">Mapped object saved in <c>Storage</c></param>
        protected byte[] UploadFileWithPWC(IFileInfo localFile, ref IDocument doc, Transmission transmission, IMappedObject mappedObject = null) {
            byte[] checksum = null;
            var docPWC = this.LoadRemotePWCDocument(doc, ref checksum);

            using (var file = localFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) {
                if (checksum != null) {
                    // check PWC checksum for integration
                    using (var hashAlg = new SHA1Managed()) {
                        int bufsize = 8 * 1024;
                        byte[] buffer = new byte[bufsize];
                        for (long offset = 0; offset < docPWC.ContentStreamLength.GetValueOrDefault();) {
                            int readsize = bufsize;
                            if (readsize + offset > docPWC.ContentStreamLength.GetValueOrDefault()) {
                                readsize = (int)(docPWC.ContentStreamLength.GetValueOrDefault() - offset);
                            }

                            readsize = file.Read(buffer, 0, readsize);
                            hashAlg.TransformBlock(buffer, 0, readsize, buffer, 0);
                            offset += readsize;
                            if (readsize == 0) {
                                break;
                            }
                        }

                        hashAlg.TransformFinalBlock(new byte[0], 0, 0);
                        if (!hashAlg.Hash.SequenceEqual(checksum)) {
                            docPWC.DeleteContentStream();
                        }

                        file.Seek(0, SeekOrigin.Begin);
                    }
                }

                byte[] hash = null;
                var uploader = FileTransmission.ContentTaskUtils.CreateUploader(this.TransmissionStorage.ChunkSize);
                using (var hashAlg = new SHA1Reuse()) {
                    try {
                        using (var hashstream = new NonClosingHashStream(file, hashAlg, CryptoStreamMode.Read)) {
                            int bufsize = 8 * 1024;
                            byte[] buffer = new byte[bufsize];
                            for (long offset = 0; offset < docPWC.ContentStreamLength.GetValueOrDefault();) {
                                int readsize = bufsize;
                                if (readsize + offset > docPWC.ContentStreamLength.GetValueOrDefault()) {
                                    readsize = (int)(docPWC.ContentStreamLength.GetValueOrDefault() - offset);
                                }

                                readsize = hashstream.Read(buffer, 0, readsize);
                                offset += readsize;
                                if (readsize == 0) {
                                    break;
                                }
                            }
                        }

                        var document = doc;
                        uploader.UploadFile(docPWC, file, transmission, hashAlg, false, (byte[] checksumUpdate, long length) => this.SaveRemotePWCDocument(localFile, document, docPWC, checksumUpdate, transmission));
                        hash = hashAlg.Hash;
                    } catch (Exception ex) {
                        transmission.FailedException = ex;
                        throw;
                    }
                }

                this.TransmissionStorage.RemoveObjectByRemoteObjectId(doc.Id);

                var properties = new Dictionary<string, object>();
                properties.Add(PropertyIds.LastModificationDate, localFile.LastWriteTimeUtc);
                doc = this.Session.GetObject(docPWC.CheckIn(true, properties, null, string.Empty)) as IDocument;

                // Refresh is required, or DotCMIS will use cached one only
                doc.Refresh();

                transmission.Status = TransmissionStatus.FINISHED;
                return hash;
            }
        }
 public static void AddMappedFile(this Mock<IMetaDataStorage> db, IMappedObject file, string localPath = null, string remotePath = null) {
     db.Setup(foo => foo.GetObjectByLocalPath(It.Is<IFileInfo>(f => f.FullName == localPath))).Returns(file);
     db.Setup(foo => foo.GetObjectByRemoteId(It.Is<string>(s => s == file.RemoteObjectId))).Returns(file);
     db.Setup(foo => foo.GetLocalPath(It.Is<IMappedObject>(o => o.Equals(file)))).Returns(localPath);
     db.Setup(foo => foo.GetRemotePath(It.Is<IMappedObject>(o => o.Equals(file)))).Returns(remotePath);
     if (!file.Guid.Equals(Guid.Empty)) {
         db.Setup(foo => foo.GetObjectByGuid(It.Is<Guid>(g => g.Equals(file.Guid)))).Returns(file);
     }
 }
示例#49
0
        /// <summary>
        /// Removes the saved object.
        /// </summary>
        /// <param name='obj'>
        /// Object to be removed.
        /// </param>
        public void RemoveObject(IMappedObject obj) {
            string id = this.GetId(obj);
            using (var tran = this.engine.GetTransaction()) {
                MappedObject root = null;
                List<MappedObject> objects = new List<MappedObject>();
                foreach (var row in tran.SelectForward<string, DbCustomSerializer<MappedObject>>(MappedObjectsTable)) {
                    var value = row.Value;
                    if (value == null) {
                        continue;
                    }

                    var data = value.Get;
                    if (data == null) {
                        continue;
                    }

                    if (row.Key.Equals(id)) {
                        root = data;
                    } else {
                        objects.Add(data);
                    }
                }

                if (root == null) {
                    return;
                }

                this.RemoveChildren(tran, root, ref objects);

                tran.RemoveKey<string>(MappedObjectsTable, id);
                tran.RemoveKey<byte[]>(MappedObjectsGuidsTable, root.Guid.ToByteArray());
                tran.Commit();
            }

            this.ValidateObjectStructureIfFullValidationIsEnabled();
        }
        private static bool VerifyMappedObject(
            IMappedObject o,
            MappedObjectType type,
            string remoteId,
            string name,
            string parentId,
            string changeToken,
            bool extendedAttributeAvailable,
            DateTime? lastLocalModification,
            DateTime? lastRemoteModification,
            byte[] checksum,
            long contentSize,
            bool ignored)
        {
            Assert.That(o.RemoteObjectId, Is.EqualTo(remoteId), "Object remote Id is wrong");
            Assert.That(o.Name, Is.EqualTo(name), "Object name is wrong");
            Assert.That(o.ParentId, Is.EqualTo(parentId), "Object parent Id is wrong");
            Assert.That(o.LastChangeToken, Is.EqualTo(changeToken), "Object change token is wrong");
            Assert.That(o.Type, Is.EqualTo(type), "Object type is wrong");
            Assert.That(o.Ignored, Is.EqualTo(ignored), "Object ignore flag is wrong");
            if (extendedAttributeAvailable) {
                Assert.That(o.Guid, Is.Not.EqualTo(Guid.Empty), "Given Guid must not be empty");
            } else {
                Assert.That(o.Guid, Is.EqualTo(Guid.Empty), "Given Guid must be empty");
            }

            if (lastLocalModification != null) {
                Assert.That(o.LastLocalWriteTimeUtc, Is.EqualTo(lastLocalModification), "Last local modification date is wrong");
            }

            if (lastRemoteModification != null) {
                Assert.That(o.LastRemoteWriteTimeUtc, Is.EqualTo(lastRemoteModification), "Last remote modification date is wrong");
            }

            if (checksum != null) {
                Assert.That(o.ChecksumAlgorithmName, Is.EqualTo("SHA-1"));
                Assert.That(o.LastChecksum, Is.EqualTo(checksum), "Given checksum is not equal to last saved checksum");
            }

            if (type == MappedObjectType.File) {
                Assert.That(o.LastContentSize, Is.GreaterThanOrEqualTo(0), "Last content size is wrong");
                Assert.That(o.LastContentSize, Is.EqualTo(contentSize), "Last content size is wrong");
            }

            if (type == MappedObjectType.Folder) {
                Assert.That(o.LastContentSize, Is.EqualTo(-1), "Folder content size is wrong");
            }

            return true;
        }
示例#51
0
        /// <summary>
        /// Saves the mapped object.
        /// </summary>
        /// <param name='obj'>
        /// The MappedObject instance.
        /// </param>
        /// <exception cref="DublicateGuidException">Is thrown when guid already in database</exception>
        public void SaveMappedObject(IMappedObject obj) {
            string id = this.GetId(obj);
            using(var tran = this.engine.GetTransaction()) {
                var byteGuid = obj.Guid.ToByteArray();
                var row = tran.Select<byte[], string>(MappedObjectsGuidsTable, byteGuid);
                if (row.Exists && row.Value != id) {
                    tran.Rollback();
                    throw new DublicateGuidException(string.Format("An entry with Guid {0} already exists", obj.Guid));
                }

                if (this.fullValidationOnEachManipulation && obj.ParentId != null) {
                    DbCustomSerializer<MappedObject> value = tran.Select<string, DbCustomSerializer<MappedObject>>(MappedObjectsTable, obj.ParentId).Value;
                    if (value == null) {
                        tran.Rollback();
                        throw new InvalidDataException();
                    }
                }

                obj.LastTimeStoredInStorage = DateTime.UtcNow;
                tran.Insert<string, DbCustomSerializer<MappedObject>>(MappedObjectsTable, id, obj as MappedObject);
                if (!obj.Guid.Equals(Guid.Empty)) {
                    tran.Insert<byte[], string>(MappedObjectsGuidsTable, obj.Guid.ToByteArray(), id);
                }

                tran.Commit();
            }

            this.ValidateObjectStructureIfFullValidationIsEnabled();
        }
 private bool VerifySavedObject(IMappedObject obj, MappedObjectType type, string id, string name, string parentId, string changeToken, DateTime modifiedTime)
 {
     Assert.That(obj.Type, Is.EqualTo(type));
     Assert.That(obj.RemoteObjectId, Is.EqualTo(id));
     Assert.That(obj.ParentId, Is.EqualTo(parentId));
     Assert.That(obj.Name, Is.EqualTo(name));
     Assert.That(obj.LastChangeToken, Is.EqualTo(changeToken));
     Assert.That(obj.LastRemoteWriteTimeUtc, Is.EqualTo(modifiedTime));
     Assert.That(obj.LastLocalWriteTimeUtc, Is.EqualTo(modifiedTime));
     return true;
 }
        protected byte[] DownloadChanges(IFileInfo target, IDocument remoteDocument, IMappedObject obj, IFileSystemInfoFactory fsFactory, ITransmissionManager transmissionManager, ILog logger) {
            // Download changes
            byte[] hash = null;

            var cacheFile = fsFactory.CreateDownloadCacheFileInfo(target);
            var transmission = transmissionManager.CreateTransmission(TransmissionType.DOWNLOAD_MODIFIED_FILE, target.FullName, cacheFile.FullName);
            hash = this.DownloadCacheFile(cacheFile, remoteDocument, transmission, fsFactory);
            obj.ChecksumAlgorithmName = "SHA-1";

            try {
                var backupFile = fsFactory.CreateFileInfo(target.FullName + ".bak.sync");
                Guid? uuid = target.Uuid;
                cacheFile.Replace(target, backupFile, true);
                try {
                    target.Uuid = uuid;
                } catch (RestoreModificationDateException e) {
                    logger.Debug("Failed to restore modification date of original file", e);
                }

                try {
                    backupFile.Uuid = null;
                } catch (RestoreModificationDateException e) {
                    logger.Debug("Failed to restore modification date of backup file", e);
                }

                byte[] checksumOfOldFile = null;
                using (var oldFileStream = backupFile.Open(FileMode.Open, FileAccess.Read, FileShare.None)) {
                    checksumOfOldFile = SHA1Managed.Create().ComputeHash(oldFileStream);
                }

                if (!obj.LastChecksum.SequenceEqual(checksumOfOldFile)) {
                    var conflictFile = fsFactory.CreateConflictFileInfo(target);
                    backupFile.MoveTo(conflictFile.FullName);
                    OperationsLogger.Info(string.Format("Updated local content of \"{0}\" with content of remote document {1} and created conflict file {2}", target.FullName, remoteDocument.Id, conflictFile.FullName));
                } else {
                    backupFile.Delete();
                    OperationsLogger.Info(string.Format("Updated local content of \"{0}\" with content of remote document {1}", target.FullName, remoteDocument.Id));
                }
            } catch(Exception ex) {
                transmission.FailedException = ex;
                throw;
            }

            transmission.Status = TransmissionStatus.FINISHED;
            return hash;
        }