public override void Solve(
            IFileSystemInfo localFileSystemInfo,
            IObjectId remoteId,
            ContentChangeType localContent,
            ContentChangeType remoteContent)
        {
            var    obj     = this.Storage.GetObjectByRemoteId(remoteId.Id);
            string oldName = (remoteId as ICmisObject).Name;

            // Rename object
            try {
                (remoteId as ICmisObject).Rename(localFileSystemInfo.Name, true);
            } catch (CmisConstraintException e) {
                if (!Utils.IsValidISO885915(localFileSystemInfo.Name))
                {
                    OperationsLogger.Warn(string.Format("Server denied to rename {0} to {1}, perhaps because it contains UTF-8 characters", oldName, localFileSystemInfo.Name));
                    throw new InteractionNeededException(string.Format("Server denied renaming of {0}", oldName), e)
                          {
                              Title       = string.Format("Server denied renaming of {0}", oldName),
                              Description = string.Format("Server denied to rename {0} to {1}, perhaps because it contains UTF-8 characters", oldName, localFileSystemInfo.Name)
                          };
                }

                throw;
            } catch (CmisPermissionDeniedException) {
                OperationsLogger.Warn(string.Format("Unable to renamed remote object from {0} to {1}: Permission Denied", oldName, localFileSystemInfo.Name));
                return;
            }

            obj.Name    = localFileSystemInfo.Name;
            obj.Ignored = (remoteId as ICmisObject).AreAllChildrenIgnored();
            this.Storage.SaveMappedObject(obj);
            this.changeChangeSolver.Solve(localFileSystemInfo, remoteId, localContent, remoteContent);
        }
 /// <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;
         }
     }
 }
示例#3
0
        /// <summary>
        /// Solves the situation by deleting the corresponding remote object.
        /// </summary>
        /// <param name="localFile">Local file.</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 localFile,
            IObjectId remoteId,
            ContentChangeType localContent  = ContentChangeType.NONE,
            ContentChangeType remoteContent = ContentChangeType.NONE)
        {
            var mappedObject = this.Storage.GetObjectByRemoteId(remoteId.Id);

            if (mappedObject.LastChangeToken != (remoteId as ICmisObject).ChangeToken)
            {
                throw new ArgumentException("Remote object has been changed since last sync => force crawl sync");
            }

            bool hasBeenDeleted = this.TryDeleteObjectOnServer(remoteId, mappedObject.Type);

            if (hasBeenDeleted)
            {
                this.Storage.RemoveObject(mappedObject);
                OperationsLogger.Info(string.Format("Deleted the corresponding remote object {0} of locally deleted object {1}", remoteId.Id, mappedObject.Name));
            }
            else
            {
                OperationsLogger.Warn(string.Format("Permission denied while trying to Delete the locally deleted object {0} on the server.", mappedObject.Name));
            }
        }
        public override void Solve(
            IFileSystemInfo localFileSystemInfo,
            IObjectId remoteId,
            ContentChangeType localContent,
            ContentChangeType remoteContent)
        {
            var obj = this.Storage.GetObjectByRemoteId(remoteId.Id);
            var localParent = localFileSystemInfo is IFileInfo ? (localFileSystemInfo as IFileInfo).Directory : (localFileSystemInfo as IDirectoryInfo).Parent;
            var mappedLocalParent = this.Storage.GetObjectByGuid((Guid)localParent.Uuid);
            var remoteObject = remoteId as IFileableCmisObject;
            var targetId = mappedLocalParent.RemoteObjectId;
            var src = this.Session.GetObject(obj.ParentId);
            var target = this.Session.GetObject(targetId);
            try {
                OperationsLogger.Info(string.Format("Moving remote object {2} from folder {0} to folder {1}", src.Name, target.Name, remoteId.Id));
                remoteObject = remoteObject.Move(src, target);
            } catch (CmisPermissionDeniedException) {
                OperationsLogger.Info(string.Format("Moving remote object failed {0}: Permission Denied", localFileSystemInfo.FullName));
                return;
            }

            obj.ParentId = targetId;
            this.Storage.SaveMappedObject(obj);

            if (obj.Name != localFileSystemInfo.Name) {
                this.renameChangeSolver.Solve(localFileSystemInfo, remoteObject, localContent, remoteContent);
            } else {
                this.changeChangeSolver.Solve(localFileSystemInfo, remoteObject, localContent, remoteContent);
            }
        }
        private IDocument CreateCheckedOutDocument(IFileInfo localFile, IObjectId parentId)
        {
            IDocument result;
            Dictionary <string, object> properties = new Dictionary <string, object>();

            properties.Add(PropertyIds.Name, localFile.Name);
            properties.Add(PropertyIds.ObjectTypeId, BaseTypeId.CmisDocument.GetCmisValue());
            if (this.ServerCanModifyDateTimes)
            {
                properties.Add(PropertyIds.CreationDate, localFile.CreationTimeUtc);
                properties.Add(PropertyIds.LastModificationDate, localFile.LastWriteTimeUtc);
            }

            try {
                var objId = this.Session.CreateDocument(
                    properties,
                    parentId,
                    null,
                    VersioningState.CheckedOut);
                result = this.Session.GetObject(objId) as IDocument;
            } catch (CmisConstraintException e) {
                this.EnsureThatLocalFileNameContainsLegalCharacters(localFile, e);
                throw;
            }

            OperationsLogger.Info(string.Format("Created remote private working copy document {0} for {1}", result.Id, localFile.FullName));
            return(result);
        }
示例#6
0
        /// <summary>
        /// Solve the specified situation by using localFile and remote object.
        /// </summary>
        /// <param name="localFile">Local file.</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 localFile,
            IObjectId remoteId,
            ContentChangeType localContent  = ContentChangeType.NONE,
            ContentChangeType remoteContent = ContentChangeType.NONE)
        {
            var obj = this.Storage.GetObjectByRemoteId(remoteId.Id);

            // Rename remote object
            if (remoteId is ICmisObject)
            {
                if ((remoteId as ICmisObject).ChangeToken != obj.LastChangeToken)
                {
                    throw new ArgumentException("Last changetoken is invalid => force crawl sync");
                }

                string oldName = (remoteId as ICmisObject).Name;
                try {
                    (remoteId as ICmisObject).Rename(localFile.Name, true);
                } catch (CmisConstraintException e) {
                    if (!Utils.IsValidISO885915(localFile.Name))
                    {
                        OperationsLogger.Warn(string.Format("The server denies the renaming of {2} from {0} to {1}, perhaps because the new name contains UTF-8 characters", oldName, localFile.Name, localFile.FullName));
                        throw new InteractionNeededException(string.Format("Server denied renaming of {0}", oldName), e)
                              {
                                  Title       = string.Format("Server denied renaming of {0}", oldName),
                                  Description = string.Format("The server denies the renaming of {2} from {0} to {1}, perhaps because the new name contains UTF-8 characters", oldName, localFile.Name, localFile.FullName)
                              };
                    }
                    else
                    {
                        OperationsLogger.Warn(string.Format("The server denies the renaming of {2} from {0} to {1}", oldName, localFile.Name, localFile.FullName), e);
                    }

                    throw;
                } catch (CmisPermissionDeniedException) {
                    OperationsLogger.Warn(string.Format("Unable to renamed remote object from {0} to {1}: Permission Denied", oldName, localFile.Name));
                    return;
                }

                OperationsLogger.Info(string.Format("Renamed remote object {0} from {1} to {2}", remoteId.Id, oldName, localFile.Name));
            }
            else
            {
                throw new ArgumentException("Given remoteId type is unknown: " + remoteId.GetType().Name);
            }

            bool isContentChanged = localFile is IFileInfo ? (localFile as IFileInfo).IsContentChangedTo(obj) : false;

            obj.Name = (remoteId as ICmisObject).Name;
            obj.LastRemoteWriteTimeUtc = (remoteId as ICmisObject).LastModificationDate;
            obj.LastLocalWriteTimeUtc  = isContentChanged ? obj.LastLocalWriteTimeUtc : localFile.LastWriteTimeUtc;
            obj.LastChangeToken        = (remoteId as ICmisObject).ChangeToken;
            this.Storage.SaveMappedObject(obj);
            if (isContentChanged)
            {
                throw new ArgumentException("Local file content is also changed => force crawl sync.");
            }
        }
示例#7
0
 private void MoveTo(IFileSystemInfo localFsInfo, string oldPath, string newPath)
 {
     if (localFsInfo is IFileInfo)
     {
         (localFsInfo as IFileInfo).MoveTo(newPath);
         OperationsLogger.Info(string.Format("Moved local file {0} to {1}", oldPath, newPath));
     }
     else
     {
         (localFsInfo as IDirectoryInfo).MoveTo(newPath);
         OperationsLogger.Info(string.Format("Moved local folder {0} to {1}", oldPath, newPath));
     }
 }
 public override void Solve(
     IFileSystemInfo localFileSystemInfo,
     IObjectId remoteId,
     ContentChangeType localContent,
     ContentChangeType remoteContent)
 {
     // User Interaction needed or the content will be downloaded on next sync.
     // Possibilities:
     // - Download new remote content (default, because no user interaction is needed and it is simple to solve)
     // - Remove remote element
     // - Ignore until situation is cleared
     OperationsLogger.Warn(string.Format("The remote object {0} of the corresponding locally deleted element has been changed => Downloading the remote changes", remoteId.Id));
     this.Storage.RemoveObject(this.Storage.GetObjectByRemoteId(remoteId.Id));
     throw new ArgumentException("Remote object has been changed while the object was deleted locally => force crawl sync");
 }
示例#9
0
        /// <summary>
        /// Deletes the given localFileInfo on file system and removes the stored object from storage.
        /// </summary>
        /// <param name="localFileInfo">Local file info.</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 localFileInfo,
            IObjectId remoteId,
            ContentChangeType localContent  = ContentChangeType.NONE,
            ContentChangeType remoteContent = ContentChangeType.NONE)
        {
            if (localFileInfo is IDirectoryInfo)
            {
                if (!this.DeleteLocalObjectIfHasBeenSyncedBefore(this.Storage, localFileInfo))
                {
                    this.Storage.RemoveObject(this.Storage.GetObjectByLocalPath(localFileInfo));
                    throw new IOException(string.Format("Not all local objects under {0} have been synced yet", localFileInfo.FullName));
                }
                else
                {
                    this.Storage.RemoveObject(this.Storage.GetObjectByLocalPath(localFileInfo));
                }
            }
            else if (localFileInfo is IFileInfo)
            {
                var file       = localFileInfo as IFileInfo;
                var mappedFile = this.Storage.GetObjectByLocalPath(file);
                if (mappedFile != null && file.LastWriteTimeUtc.Equals(mappedFile.LastLocalWriteTimeUtc))
                {
                    file.Delete();
                    OperationsLogger.Info(string.Format("Deleted local file {0} because the mapped remote object {0} has been deleted", file.FullName, mappedFile.RemoteObjectId));
                }
                else
                {
                    file.Uuid = null;
                    if (mappedFile == null)
                    {
                        return;
                    }

                    OperationsLogger.Info(string.Format("Deletion of local file {0} skipped because of not yet uploaded changes", file.FullName));
                }

                this.Storage.RemoveObject(this.Storage.GetObjectByLocalPath(localFileInfo));
                file.Refresh();
                if (file.Exists)
                {
                    throw new IOException(string.Format("Deletion of local file {0} skipped because of not yet uploaded changes", localFileInfo.FullName));
                }
            }
        }
示例#10
0
        /// <summary>
        /// Solve the specified situation by using the session, storage, localFile and remoteId.
        /// Moves the local file/folder to the new location.
        /// </summary>
        /// <param name="localFile">Old local file/folder.</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)
        {
            // Move local object
            var    savedObject = this.Storage.GetObjectByRemoteId(remoteId.Id);
            string newPath     = remoteId is IFolder?this.Storage.Matcher.CreateLocalPath(remoteId as IFolder) : this.Storage.Matcher.CreateLocalPath(remoteId as IDocument);

            if (remoteId is IFolder)
            {
                IDirectoryInfo dirInfo = localFile as IDirectoryInfo;
                string         oldPath = dirInfo.FullName;
                if (!dirInfo.FullName.Equals(newPath))
                {
                    dirInfo.MoveTo(newPath);
                    dirInfo.LastWriteTimeUtc = (remoteId as IFolder).LastModificationDate != null ? (DateTime)(remoteId as IFolder).LastModificationDate : dirInfo.LastWriteTimeUtc;
                    OperationsLogger.Info(string.Format("Moved local folder {0} to {1}", oldPath, newPath));
                }
                else
                {
                    return;
                }
            }
            else if (remoteId is IDocument)
            {
                IFileInfo fileInfo = localFile as IFileInfo;
                string    oldPath  = fileInfo.FullName;
                fileInfo.MoveTo(newPath);
                fileInfo.LastWriteTimeUtc = (remoteId as IDocument).LastModificationDate != null ? (DateTime)(remoteId as IDocument).LastModificationDate : fileInfo.LastWriteTimeUtc;
                OperationsLogger.Info(string.Format("Moved local file {0} to {1}", oldPath, newPath));
            }

            savedObject.Name                   = (remoteId as ICmisObject).Name;
            savedObject.ParentId               = remoteId is IFolder ? (remoteId as IFolder).ParentId : (remoteId as IDocument).Parents[0].Id;
            savedObject.LastChangeToken        = (remoteId is IDocument && remoteContent != ContentChangeType.NONE) ? savedObject.LastChangeToken : remoteId is ICmisObject ? (remoteId as ICmisObject).ChangeToken : null;
            savedObject.LastLocalWriteTimeUtc  = localFile.LastWriteTimeUtc;
            savedObject.LastRemoteWriteTimeUtc = (remoteId is IDocument && remoteContent != ContentChangeType.NONE) ? savedObject.LastRemoteWriteTimeUtc : (remoteId as ICmisObject).LastModificationDate;
            savedObject.Ignored                = (remoteId as ICmisObject).AreAllChildrenIgnored();
            this.Storage.SaveMappedObject(savedObject);
            if (remoteId is IDocument && remoteContent != ContentChangeType.NONE)
            {
                throw new ArgumentException("Remote content has also been changed => force crawl sync.");
            }
        }
示例#11
0
        public override void Solve(
            IFileSystemInfo localFileSystemInfo,
            IObjectId remoteId,
            ContentChangeType localContent,
            ContentChangeType remoteContent)
        {
            var    savedObject = this.Storage.GetObjectByRemoteId(remoteId.Id);
            string newPath     = remoteId is IFolder?this.Storage.Matcher.CreateLocalPath(remoteId as IFolder) : this.Storage.Matcher.CreateLocalPath(remoteId as IDocument);

            if (remoteId is IFolder)
            {
                IDirectoryInfo dirInfo = localFileSystemInfo as IDirectoryInfo;
                string         oldPath = dirInfo.FullName;
                if (!dirInfo.FullName.Equals(newPath))
                {
                    dirInfo.MoveTo(newPath);
                    OperationsLogger.Info(string.Format("Moved local folder {0} to {1}", oldPath, newPath));
                }
                else
                {
                    return;
                }
            }
            else if (remoteId is IDocument)
            {
                IFileInfo fileInfo = localFileSystemInfo as IFileInfo;
                string    oldPath  = fileInfo.FullName;
                fileInfo.MoveTo(newPath);
                OperationsLogger.Info(string.Format("Moved local file {0} to {1}", oldPath, newPath));
            }

            savedObject.Name     = (remoteId as ICmisObject).Name;
            savedObject.Ignored  = (remoteId as ICmisObject).AreAllChildrenIgnored();
            savedObject.ParentId = remoteId is IFolder ? (remoteId as IFolder).ParentId : (remoteId as IDocument).Parents[0].Id;
            this.Storage.SaveMappedObject(savedObject);

            this.changeChangeSolver.Solve(localFileSystemInfo, remoteId, localContent, remoteContent);
        }
        private bool DeleteLocalObjectIfHasBeenSyncedBefore(IFileSystemInfo fsInfo)
        {
            bool          delete = true;
            string        reason;
            Guid?         uuid = fsInfo.Uuid;
            IMappedObject obj  = null;

            if (uuid != null)
            {
                obj = this.Storage.GetObjectByGuid((Guid)uuid);
            }
            else
            {
                obj = this.Storage.GetObjectByLocalPath(fsInfo);
            }

            if (fsInfo is IFileInfo)
            {
                if (obj != null && fsInfo.LastWriteTimeUtc.Equals(obj.LastLocalWriteTimeUtc))
                {
                    (fsInfo as IFileInfo).Delete();
                    OperationsLogger.Info(string.Format("Deleted local file {0} because the mapped remote object {0} has been deleted", fsInfo.FullName, obj.RemoteObjectId));
                }
                else
                {
                    fsInfo.Uuid = null;
                    return(false);
                }
            }
            else if (fsInfo is IDirectoryInfo)
            {
                var dir = fsInfo as IDirectoryInfo;
                if (obj != null && obj.Ignored)
                {
                    dir.Delete(true);
                    return(true);
                }

                if (!this.filters.FolderNamesFilter.CheckFolderName(dir.Name, out reason))
                {
                    foreach (var folder in dir.GetDirectories())
                    {
                        if (!this.DeleteLocalObjectIfHasBeenSyncedBefore(folder))
                        {
                            delete = false;
                        }
                    }

                    foreach (var file in dir.GetFiles())
                    {
                        if (!this.filters.FileNamesFilter.CheckFile(file.Name, out reason))
                        {
                            if (!this.DeleteLocalObjectIfHasBeenSyncedBefore(file))
                            {
                                delete = false;
                            }
                        }
                        else
                        {
                            file.Delete();
                            OperationsLogger.Info(string.Format("Deleted local ignored file {0} because the mapped remote parent object {0} has been deleted", fsInfo.FullName, obj.RemoteObjectId));
                        }
                    }

                    if (delete)
                    {
                        try {
                            (fsInfo as IDirectoryInfo).Delete(false);
                            OperationsLogger.Info(string.Format("Deleted local folder {0} because the mapped remote folder has been deleted", fsInfo.FullName));
                        } catch (IOException) {
                            fsInfo.Uuid = null;
                            return(false);
                        }
                    }
                    else
                    {
                        fsInfo.Uuid = null;
                    }
                }
                else
                {
                    try {
                        (fsInfo as IDirectoryInfo).Delete(true);
                        OperationsLogger.Info(string.Format("Deleted locally ignored folder {0} because the parent mapped remote folder has been deleted", fsInfo.FullName));
                    } catch (IOException e) {
                        OperationsLogger.Info(string.Format("Deletion of locally ignored folder {0} failed", fsInfo.FullName), e);
                        return(false);
                    }
                }
            }

            return(delete);
        }
示例#13
0
        public override void Solve(
            IFileSystemInfo localFileSystemInfo,
            IObjectId remoteId,
            ContentChangeType localContent,
            ContentChangeType remoteContent)
        {
            var    savedObject = this.Storage.GetObjectByRemoteId(remoteId.Id);
            string oldPath     = localFileSystemInfo.FullName;
            string oldName     = (remoteId as ICmisObject).Name;

            if ((remoteId as ICmisObject).Name != savedObject.Name)
            {
                // Both are renamed and remote is also moved => move & rename/rename
                string newPath = remoteId is IFolder?this.Storage.Matcher.CreateLocalPath(remoteId as IFolder) : this.Storage.Matcher.CreateLocalPath(remoteId as IDocument);

                if ((remoteId as ICmisObject).Name == localFileSystemInfo.Name)
                {
                    // Move local object to new name, bacause it is the same => only change/change solver is needed
                    this.MoveTo(localFileSystemInfo, oldPath, newPath);
                    savedObject.Name     = localFileSystemInfo.Name;
                    savedObject.ParentId = remoteId is IFolder ? (remoteId as IFolder).ParentId : (remoteId as IDocument).Parents[0].Id;
                    this.Storage.SaveMappedObject(savedObject);
                    this.changeChangeSolver.Solve(localFileSystemInfo, remoteId, localContent, remoteContent);
                }
                else
                {
                    // Only move local object to new folder but keep the old name => both names are different => rename/rename solver needed
                    newPath = newPath.TrimEnd(Path.DirectorySeparatorChar);
                    newPath = newPath.Substring(0, newPath.Length - (remoteId as ICmisObject).Name.Length) + oldName;
                    this.MoveTo(localFileSystemInfo, oldPath, newPath);
                    savedObject.ParentId = remoteId is IFolder ? (remoteId as IFolder).ParentId : (remoteId as IDocument).Parents[0].Id;
                    this.Storage.SaveMappedObject(savedObject);
                    this.renameRenameSolver.Solve(localFileSystemInfo, remoteId, localContent, remoteContent);
                }
            }
            else
            {
                // Local rename and remote move => move locally and rename remote => change/change
                try {
                    // rename remote file
                    (remoteId as ICmisObject).Rename(localFileSystemInfo.Name, true);
                    OperationsLogger.Info(string.Format("Renamed remote object {0} from {1} to {2}", remoteId.Id, oldName, localFileSystemInfo.Name));
                    savedObject.Name = (remoteId as ICmisObject).Name;
                } catch (CmisConstraintException e) {
                    if (!Utils.IsValidISO885915(localFileSystemInfo.Name))
                    {
                        OperationsLogger.Warn(string.Format("Server denied to rename {0} to {1}, perhaps because it contains UTF-8 characters", oldName, localFileSystemInfo.Name));
                        throw new InteractionNeededException(string.Format("Server denied renaming of {0}", oldName), e)
                              {
                                  Title       = string.Format("Server denied renaming of {0}", oldName),
                                  Description = string.Format("Server denied to rename {0} to {1}, perhaps because it contains UTF-8 characters", oldName, localFileSystemInfo.Name)
                              };
                    }

                    throw;
                } catch (CmisPermissionDeniedException) {
                    OperationsLogger.Info(string.Format("Permission Denied: Cannot rename remote object ({1}): {0}", (remoteId as ICmisObject).Name, remoteId.Id));
                    return;
                }

                string newPath = remoteId is IFolder?this.Storage.Matcher.CreateLocalPath(remoteId as IFolder) : this.Storage.Matcher.CreateLocalPath(remoteId as IDocument);

                // move local object to same directory as the remote object is
                this.MoveTo(localFileSystemInfo, oldPath, newPath);

                savedObject.ParentId = remoteId is IFolder ? (remoteId as IFolder).ParentId : (remoteId as IDocument).Parents[0].Id;
                this.Storage.SaveMappedObject(savedObject);

                // Synchronize the rest with the change change solver
                this.changeChangeSolver.Solve(localFileSystemInfo, remoteId, localContent, remoteContent);
            }
        }
示例#14
0
        /// <summary>
        /// Solve the specified situation by using the session, storage, localFile and remoteId.
        /// </summary>
        /// <param name="localFile">Actual local file.</param>
        /// <param name="remoteId">Corresponding 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)
        {
            // Move Remote Object
            var remoteObject = remoteId as IFileableCmisObject;
            var mappedObject = this.Storage.GetObjectByRemoteId(remoteId.Id);

            if (mappedObject.LastChangeToken != (remoteId as ICmisObject).ChangeToken)
            {
                throw new ArgumentException("The remote change token is different to the last synchronization");
            }

            var targetPath = localFile is IDirectoryInfo ? (localFile as IDirectoryInfo).Parent : (localFile as IFileInfo).Directory;
            var targetId   = this.Storage.GetObjectByLocalPath(targetPath).RemoteObjectId;

            try {
                if (mappedObject.ParentId != targetId)
                {
                    var src    = this.Session.GetObject(mappedObject.ParentId);
                    var target = this.Session.GetObject(targetId);
                    OperationsLogger.Info(string.Format("Moving remote object {2} from folder {0} to folder {1}", src.Name, target.Name, remoteId.Id));
                    remoteObject = remoteObject.Move(src, target);
                }

                if (localFile.Name != remoteObject.Name)
                {
                    try {
                        remoteObject.Rename(localFile.Name, true);
                    } catch (CmisConstraintException e) {
                        if (!Utils.IsValidISO885915(localFile.Name))
                        {
                            OperationsLogger.Warn(string.Format("Server denied the rename of {0} to {1}, possibly because it contains UTF-8 charactes", remoteObject.Name, localFile.Name));
                            throw new InteractionNeededException(string.Format("Server denied renaming of {0}", remoteObject.Name), e)
                                  {
                                      Title       = string.Format("Server denied renaming of {0}", remoteObject.Name),
                                      Description = string.Format("Server denied the rename of {0} to {1}, possibly because it contains UTF-8 charactes", remoteObject.Name, localFile.Name)
                                  };
                        }

                        throw;
                    }
                }
            } catch (CmisPermissionDeniedException) {
                OperationsLogger.Info(string.Format("Moving remote object failed {0}: Permission Denied", localFile.FullName));
                return;
            }

            if (this.ServerCanModifyDateTimes)
            {
                if (mappedObject.LastLocalWriteTimeUtc != localFile.LastWriteTimeUtc)
                {
                    remoteObject.UpdateLastWriteTimeUtc(localFile.LastWriteTimeUtc);
                }
            }

            bool isContentChanged = localFile is IFileInfo ? (localFile as IFileInfo).IsContentChangedTo(mappedObject) : false;

            mappedObject.ParentId               = targetId;
            mappedObject.LastChangeToken        = remoteObject.ChangeToken;
            mappedObject.LastRemoteWriteTimeUtc = remoteObject.LastModificationDate;
            mappedObject.Name = remoteObject.Name;
            this.Storage.SaveMappedObject(mappedObject);
            if (isContentChanged)
            {
                throw new ArgumentException("Local file content is also changed => force crawl sync.");
            }
        }
示例#15
0
        public override void Solve(
            IFileSystemInfo localFileSystemInfo,
            IObjectId remoteId,
            ContentChangeType localContent  = ContentChangeType.NONE,
            ContentChangeType remoteContent = ContentChangeType.NONE)
        {
            if (localFileSystemInfo is IFileInfo && remoteId is IDocument)
            {
                var localFile      = localFileSystemInfo as IFileInfo;
                var remoteDocument = remoteId as IDocument;

                var mappedObject = this.Storage.GetObject(localFile);
                if (mappedObject == null)
                {
                    throw new ArgumentException(string.Format("Could not find db entry for {0} => invoke crawl sync", localFileSystemInfo.FullName));
                }

                if (mappedObject.LastChangeToken != (remoteId as ICmisObjectProperties).ChangeToken)
                {
                    throw new ArgumentException(string.Format("remote {1} {0} has also been changed since last sync => invoke crawl sync", remoteId.Id, remoteId is IDocument ? "document" : "folder"));
                }

                if (localFile != null && localFile.IsContentChangedTo(mappedObject, scanOnlyIfModificationDateDiffers: true))
                {
                    Logger.Debug(string.Format("\"{0}\" is different from {1}", localFile.FullName, mappedObject.ToString()));
                    OperationsLogger.Debug(string.Format("Local file \"{0}\" has been changed", localFile.FullName));
                    try {
                        var transmission = this.transmissionManager.CreateTransmission(TransmissionType.UPLOAD_MODIFIED_FILE, localFile.FullName);
                        mappedObject.LastChecksum          = this.UploadFileWithPWC(localFile, ref remoteDocument, transmission);
                        mappedObject.ChecksumAlgorithmName = "SHA-1";
                        if (remoteDocument.Id != mappedObject.RemoteObjectId)
                        {
                            this.TransmissionStorage.RemoveObjectByRemoteObjectId(mappedObject.RemoteObjectId);
                            mappedObject.RemoteObjectId = remoteDocument.Id;
                        }
                    } catch (Exception ex) {
                        if (ex.InnerException is CmisPermissionDeniedException)
                        {
                            OperationsLogger.Warn(string.Format("Local changed file \"{0}\" has not been uploaded: PermissionDenied", localFile.FullName));
                            return;
                        }
                        else if (ex.InnerException is CmisStorageException)
                        {
                            OperationsLogger.Warn(string.Format("Local changed file \"{0}\" has not been uploaded: StorageException", localFile.FullName), ex);
                            return;
                        }

                        throw;
                    }

                    mappedObject.LastRemoteWriteTimeUtc = remoteDocument.LastModificationDate;
                    mappedObject.LastLocalWriteTimeUtc  = localFile.LastWriteTimeUtc;
                    mappedObject.LastContentSize        = localFile.Length;

                    OperationsLogger.Info(string.Format("Local changed file \"{0}\" has been uploaded", localFile.FullName));
                }

                mappedObject.LastChangeToken       = remoteDocument.ChangeToken;
                mappedObject.LastLocalWriteTimeUtc = localFile.LastWriteTimeUtc;
                this.Storage.SaveMappedObject(mappedObject);
            }
            else
            {
                this.folderOrFileContentUnchangedSolver.Solve(localFileSystemInfo, remoteId, localContent, remoteContent);
            }

            return;
        }
示例#16
0
        /// <summary>
        /// Renames the specified localFile to the name of the given remoteId object by using the storage, localFile and remoteId.
        /// </summary>
        /// <param name="localFile">Local file or folder. It is the source file/folder reference, which should be renamed.</param>
        /// <param name="remoteId">Remote identifier. Should be an instance of IFolder or IDocument.</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)
            {
                // Rename local folder
                IFolder        remoteFolder = remoteId as IFolder;
                IDirectoryInfo dirInfo      = localFile as IDirectoryInfo;
                string         oldPath      = dirInfo.FullName;
                try {
                    dirInfo.MoveTo(Path.Combine(dirInfo.Parent.FullName, remoteFolder.Name));
                    obj.Name = remoteFolder.Name;
                } catch (IOException) {
                    if (dirInfo.Name.Equals(remoteFolder.Name, StringComparison.OrdinalIgnoreCase))
                    {
                        obj.Name = dirInfo.Name;
                    }
                    else
                    {
                        throw;
                    }
                }

                if (remoteFolder.LastModificationDate != null)
                {
                    dirInfo.LastWriteTimeUtc = (DateTime)remoteFolder.LastModificationDate;
                }


                obj.LastChangeToken        = remoteFolder.ChangeToken;
                obj.LastRemoteWriteTimeUtc = remoteFolder.LastModificationDate;
                obj.LastLocalWriteTimeUtc  = dirInfo.LastWriteTimeUtc;
                this.Storage.SaveMappedObject(obj);
                OperationsLogger.Info(string.Format("Renamed local folder {0} to {1}", oldPath, remoteFolder.Name));
            }
            else if (remoteId is IDocument)
            {
                // Rename local file
                IDocument remoteDocument = remoteId as IDocument;
                IFileInfo fileInfo       = localFile as IFileInfo;
                string    oldPath        = fileInfo.FullName;
                fileInfo.MoveTo(Path.Combine(fileInfo.Directory.FullName, remoteDocument.Name));
                if (remoteDocument.LastModificationDate != null)
                {
                    fileInfo.LastWriteTimeUtc = (DateTime)remoteDocument.LastModificationDate;
                }

                obj.Name                   = remoteDocument.Name;
                obj.LastChangeToken        = remoteContent == ContentChangeType.NONE ? remoteDocument.ChangeToken : obj.LastChangeToken;
                obj.LastRemoteWriteTimeUtc = remoteContent == ContentChangeType.NONE ? remoteDocument.LastModificationDate : obj.LastRemoteWriteTimeUtc;
                obj.LastLocalWriteTimeUtc  = fileInfo.LastWriteTimeUtc;
                this.Storage.SaveMappedObject(obj);
                OperationsLogger.Info(string.Format("Renamed local file {0} to {1}", oldPath, remoteDocument.Name));
                if (remoteContent != ContentChangeType.NONE)
                {
                    throw new ArgumentException("Remote documents content is also changed => force crawl sync.");
                }
            }
            else
            {
                throw new ArgumentException("Given remote Id is not an IFolder nor an IDocument instance");
            }
        }
示例#17
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.NONE,
            ContentChangeType remoteContent = ContentChangeType.NONE)
        {
            Stopwatch completewatch = new Stopwatch();

            completewatch.Start();
            Logger.Debug("Starting LocalObjectAdded");
            localFileSystemInfo.Refresh();
            if (!localFileSystemInfo.Exists)
            {
                throw new FileNotFoundException(string.Format("Local file/folder {0} has been renamed/moved/deleted", localFileSystemInfo.FullName));
            }

            string parentId = Storage.GetRemoteId(this.GetParent(localFileSystemInfo));

            if (parentId == null)
            {
                if (this.IsParentReadOnly(localFileSystemInfo))
                {
                    return;
                }
                else
                {
                    throw new ArgumentException("ParentId is null => invoke crawl sync to create parent first");
                }
            }

            ICmisObject addedObject;

            try {
                addedObject = this.AddCmisObject(localFileSystemInfo, parentId, this.Session);
            } catch (CmisConstraintException e) {
                this.EnsureThatLocalFileNameContainsLegalCharacters(localFileSystemInfo, e);
                throw;
            } catch (CmisPermissionDeniedException e) {
                OperationsLogger.Warn(string.Format("Permission denied while trying to Create the locally added object {0} on the server ({1}).", localFileSystemInfo.FullName, e.Message));
                return;
            }

            Guid uuid = this.WriteOrUseUuidIfSupported(localFileSystemInfo);

            OperationsLogger.Info(string.Format("Created remote {2} {0} for {1}", addedObject.Id, localFileSystemInfo.FullName, addedObject is IFolder ? "folder" : "document"));

            MappedObject mapped = new MappedObject(
                localFileSystemInfo.Name,
                addedObject.Id,
                localFileSystemInfo is IDirectoryInfo ? MappedObjectType.Folder : MappedObjectType.File,
                parentId,
                addedObject.ChangeToken)
            {
                Guid = uuid,
                LastRemoteWriteTimeUtc = addedObject.LastModificationDate,
                LastLocalWriteTimeUtc  = localFileSystemInfo is IFileInfo && (localFileSystemInfo as IFileInfo).Length > 0 ? (DateTime?)null : (DateTime?)localFileSystemInfo.LastWriteTimeUtc,
                LastChangeToken        = addedObject.ChangeToken,
                LastContentSize        = localFileSystemInfo is IDirectoryInfo ? -1 : 0,
                ChecksumAlgorithmName  = localFileSystemInfo is IDirectoryInfo ? null : "SHA-1",
                LastChecksum           = localFileSystemInfo is IDirectoryInfo ? null : SHA1.Create().ComputeHash(new byte[0])
            };

            this.Storage.SaveMappedObject(mapped);

            var localFile = localFileSystemInfo as IFileInfo;

            if (localFile != null)
            {
                var transmission = this.transmissionManager.CreateTransmission(TransmissionType.UPLOAD_NEW_FILE, localFile.FullName);
                if (localFile.Length > 0)
                {
                    Stopwatch watch = new Stopwatch();
                    OperationsLogger.Debug(string.Format("Uploading file content of {0}", localFile.FullName));
                    watch.Start();
                    try {
                        mapped.LastChecksum          = this.UploadFile(localFile, addedObject as IDocument, transmission);
                        mapped.ChecksumAlgorithmName = "SHA-1";
                    } catch (Exception ex) {
                        if (ex is UploadFailedException && (ex as UploadFailedException).InnerException is CmisStorageException)
                        {
                            OperationsLogger.Warn(string.Format("Could not upload file content of {0}:", localFile.FullName), (ex as UploadFailedException).InnerException);
                            return;
                        }

                        throw;
                    }

                    watch.Stop();

                    if (this.ServerCanModifyDateTimes)
                    {
                        (addedObject as IDocument).UpdateLastWriteTimeUtc(localFile.LastWriteTimeUtc);
                    }

                    mapped.LastContentSize        = localFile.Length;
                    mapped.LastChangeToken        = addedObject.ChangeToken;
                    mapped.LastRemoteWriteTimeUtc = addedObject.LastModificationDate;
                    mapped.LastLocalWriteTimeUtc  = localFileSystemInfo.LastWriteTimeUtc;

                    this.Storage.SaveMappedObject(mapped);
                    OperationsLogger.Info(string.Format("Uploaded file content of {0} in [{1} msec]", localFile.FullName, watch.ElapsedMilliseconds));
                }
                else
                {
                    transmission.Length   = 0;
                    transmission.Position = 0;
                    transmission.Status   = TransmissionStatus.FINISHED;
                }
            }

            completewatch.Stop();
            Logger.Debug(string.Format("Finished LocalObjectAdded after [{0} msec]", completewatch.ElapsedMilliseconds));
        }
        /// <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.NONE,
            ContentChangeType remoteContent = ContentChangeType.NONE)
        {
            if (localFileSystemInfo is IFileInfo)
            {
                IFileInfo localFile = localFileSystemInfo as IFileInfo;
                localFile.Refresh();
                if (!localFile.Exists)
                {
                    throw new FileNotFoundException(string.Format("Local file {0} has been renamed/moved/deleted", localFile.FullName));
                }

                if (localFile.Length == 0)
                {
                    this.folderOrEmptyFileAddedSolver.Solve(localFileSystemInfo, null, localContent, remoteContent);
                    return;
                }

                string parentId = this.Storage.GetRemoteId(localFile.Directory);
                if (parentId == null)
                {
                    if (this.IsParentReadOnly(localFile))
                    {
                        return;
                    }
                    else
                    {
                        throw new ArgumentException("ParentId is null => invoke crawl sync to create parent first");
                    }
                }

                IDocument remoteDocument;
                try {
                    remoteDocument = this.CreateOrLoadExistingRemoteDocument(localFile, new ObjectId(parentId));
                } catch (CmisPermissionDeniedException e) {
                    OperationsLogger.Warn(string.Format("Permission denied while trying to Create the locally added object {0} on the server ({1}).", localFile.FullName, e.Message));
                    return;
                }

                Guid uuid = this.WriteOrUseUuidIfSupported(localFile);

                var transmission = this.transmissionManager.CreateTransmission(TransmissionType.UPLOAD_NEW_FILE, localFile.FullName);

                MappedObject mapped = new MappedObject(
                    localFile.Name,
                    remoteDocument.Id,
                    MappedObjectType.File,
                    parentId,
                    remoteDocument.ChangeToken)
                {
                    Guid = uuid,
                    LastRemoteWriteTimeUtc = remoteDocument.LastModificationDate,
                    LastLocalWriteTimeUtc  = (DateTime?)localFileSystemInfo.LastWriteTimeUtc,
                    LastChangeToken        = remoteDocument.ChangeToken,
                    LastContentSize        = 0,
                    ChecksumAlgorithmName  = "SHA-1",
                    LastChecksum           = SHA1.Create().ComputeHash(new byte[0])
                };

                Stopwatch watch = new Stopwatch();
                OperationsLogger.Debug(string.Format("Uploading file content of {0}", localFile.FullName));
                watch.Start();
                try {
                    mapped.LastChecksum          = this.UploadFileWithPWC(localFile, ref remoteDocument, transmission);
                    mapped.ChecksumAlgorithmName = "SHA-1";
                    mapped.RemoteObjectId        = remoteDocument.Id;
                } catch (Exception ex) {
                    if (ex is UploadFailedException && (ex as UploadFailedException).InnerException is CmisStorageException)
                    {
                        OperationsLogger.Warn(string.Format("Could not upload file content of {0}:", localFile.FullName), (ex as UploadFailedException).InnerException);
                        return;
                    }

                    throw;
                }
                watch.Stop();

                mapped.LastContentSize        = localFile.Length;
                mapped.LastChangeToken        = remoteDocument.ChangeToken;
                mapped.LastRemoteWriteTimeUtc = remoteDocument.LastModificationDate;
                mapped.LastLocalWriteTimeUtc  = localFileSystemInfo.LastWriteTimeUtc;

                this.Storage.SaveMappedObject(mapped);
                OperationsLogger.Info(string.Format("Uploaded file content of {0} in [{1} msec]", localFile.FullName, watch.ElapsedMilliseconds));
            }
            else
            {
                this.folderOrEmptyFileAddedSolver.Solve(localFileSystemInfo, remoteId, localContent, remoteContent);
            }
        }
        /// <summary>
        /// Solve the specified situation by using localFile and remote object if the local file content is the only changed content. Otherwise the given fallback will be used.
        /// </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 IFileInfo))
            {
                this.fallbackSolver.Solve(localFileSystemInfo, remoteId, localContent, remoteContent);
                return;
            }

            IFileInfo localFile      = localFileSystemInfo as IFileInfo;
            IDocument remoteDocument = remoteId as IDocument;

            if (remoteContent != ContentChangeType.NONE)
            {
                this.fallbackSolver.Solve(localFile, remoteId, localContent, remoteContent);
                return;
            }

            bool updateLocalDate  = false;
            bool updateRemoteDate = false;
            var  obj = this.Storage.GetObjectByRemoteId(remoteDocument.Id);

            if (localFile.IsContentChangedTo(obj, true))
            {
                updateRemoteDate = true;
                try {
                    var transmission = this.transmissionManager.CreateTransmission(TransmissionType.UPLOAD_MODIFIED_FILE, localFile.FullName);
                    obj.LastChecksum          = UploadFileWithPWC(localFile, ref remoteDocument, transmission);
                    obj.ChecksumAlgorithmName = "SHA-1";
                    obj.LastContentSize       = remoteDocument.ContentStreamLength ?? localFile.Length;
                    if (remoteDocument.Id != obj.RemoteObjectId)
                    {
                        this.TransmissionStorage.RemoveObjectByRemoteObjectId(obj.RemoteObjectId);
                        obj.RemoteObjectId = remoteDocument.Id;
                    }
                } catch (Exception ex) {
                    if (ex.InnerException is CmisPermissionDeniedException)
                    {
                        OperationsLogger.Warn(string.Format("Local changed file \"{0}\" has not been uploaded: PermissionDenied", localFile.FullName));
                        return;
                    }
                    else if (ex.InnerException is CmisStorageException)
                    {
                        OperationsLogger.Warn(string.Format("Local changed file \"{0}\" has not been uploaded: StorageException", localFile.FullName), ex);
                        return;
                    }

                    throw;
                }
            }
            else
            {
                //  just date sync
                if (remoteDocument.LastModificationDate != null && localFile.LastWriteTimeUtc < remoteDocument.LastModificationDate)
                {
                    updateLocalDate = true;
                }
                else
                {
                    updateRemoteDate = true;
                }
            }

            if (this.ServerCanModifyDateTimes)
            {
                if (updateLocalDate)
                {
                    localFile.LastWriteTimeUtc = (DateTime)remoteDocument.LastModificationDate;
                }
                else if (updateRemoteDate)
                {
                    remoteDocument.UpdateLastWriteTimeUtc(localFile.LastWriteTimeUtc);
                }
                else
                {
                    throw new ArgumentException();
                }
            }

            obj.LastChangeToken        = remoteDocument.ChangeToken;
            obj.LastLocalWriteTimeUtc  = localFileSystemInfo.LastWriteTimeUtc;
            obj.LastRemoteWriteTimeUtc = remoteDocument.LastModificationDate;
            this.Storage.SaveMappedObject(obj);
        }
示例#20
0
        /// <summary>
        /// Solve the specified situation by using localFile and remote object.
        /// </summary>
        /// <param name="localFile">Local file.</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 localFile,
            IObjectId remoteId,
            ContentChangeType localContent  = ContentChangeType.NONE,
            ContentChangeType remoteContent = ContentChangeType.NONE)
        {
            var obj = this.Storage.GetObjectByRemoteId(remoteId.Id);

            // Rename remote object
            if (remoteId is ICmisObject)
            {
                if ((remoteId as ICmisObject).ChangeToken != obj.LastChangeToken)
                {
                    throw new ArgumentException("Last changetoken is invalid => force crawl sync");
                }

                string oldName = (remoteId as ICmisObject).Name;
                try {
                    (remoteId as ICmisObject).Rename(localFile.Name, true);
                } catch (CmisNameConstraintViolationException e) {
                    if (!Utils.IsValidISO885915(localFile.Name))
                    {
                        OperationsLogger.Warn(string.Format("The server denies the renaming of {2} from {0} to {1}, perhaps because the new name contains UTF-8 characters", oldName, localFile.Name, localFile.FullName));
                        throw new InteractionNeededException(string.Format("Server denied renaming of {0}", oldName), e)
                              {
                                  Title       = string.Format("Server denied renaming of {0}", oldName),
                                  Description = string.Format("The server denies the renaming of {2} from {0} to {1}, perhaps because the new name contains UTF-8 characters", oldName, localFile.Name, localFile.FullName)
                              };
                    }
                    else
                    {
                        try {
                            string wishedRemotePath        = this.Storage.Matcher.CreateRemotePath(localFile.FullName);
                            var    conflictingRemoteObject = this.Session.GetObjectByPath(wishedRemotePath) as IFileableCmisObject;
                            if (conflictingRemoteObject != null && conflictingRemoteObject.AreAllChildrenIgnored())
                            {
                                OperationsLogger.Warn(string.Format("The server denies the renaming of {2} from {0} to {1}, because there is an ignored file/folder with this name already, trying to create conflict file/folder name", oldName, localFile.Name, localFile.FullName), e);
                                string newName = localFile.Name;
                                if (localFile is IDirectoryInfo)
                                {
                                    (localFile as IDirectoryInfo).MoveTo(Path.Combine((localFile as IDirectoryInfo).Parent.FullName, newName + "_Conflict"));
                                }
                                else if (localFile is IFileInfo)
                                {
                                    (localFile as IFileInfo).MoveTo(Path.Combine((localFile as IFileInfo).Directory.FullName, newName + "_Conflict"));
                                }

                                return;
                            }
                        } catch (CmisObjectNotFoundException) {
                        }

                        OperationsLogger.Warn(string.Format("The server denies the renaming of {2} from {0} to {1}", oldName, localFile.Name, localFile.FullName), e);
                    }

                    throw;
                } catch (CmisPermissionDeniedException) {
                    OperationsLogger.Warn(string.Format("Unable to renamed remote object from {0} to {1}: Permission Denied", oldName, localFile.Name));
                    return;
                }

                OperationsLogger.Info(string.Format("Renamed remote object {0} from {1} to {2}", remoteId.Id, oldName, localFile.Name));
            }
            else
            {
                throw new ArgumentException("Given remoteId type is unknown: " + remoteId.GetType().Name);
            }

            bool isContentChanged = localFile is IFileInfo ? (localFile as IFileInfo).IsContentChangedTo(obj) : false;

            obj.Name = (remoteId as ICmisObject).Name;
            obj.LastRemoteWriteTimeUtc = (remoteId as ICmisObject).LastModificationDate;
            obj.LastLocalWriteTimeUtc  = isContentChanged ? obj.LastLocalWriteTimeUtc : localFile.LastWriteTimeUtc;
            obj.LastChangeToken        = (remoteId as ICmisObject).ChangeToken;
            obj.Ignored = (remoteId as ICmisObject).AreAllChildrenIgnored();
            this.Storage.SaveMappedObject(obj);
            if (isContentChanged)
            {
                throw new ArgumentException("Local file content is also changed => force crawl sync.");
            }
        }
示例#21
0
        /// <summary>
        /// Solve the specified situation by taking renaming the local or remote object to the name of the last changed object.
        /// </summary>
        /// <param name="localFileSystemInfo">Local file system info.</param>
        /// <param name="remoteId">Remote 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.NONE,
            ContentChangeType remoteContent = ContentChangeType.NONE)
        {
            if (localFileSystemInfo is IDirectoryInfo)
            {
                var localFolder  = localFileSystemInfo as IDirectoryInfo;
                var remoteFolder = remoteId as IFolder;
                var mappedObject = this.Storage.GetObjectByRemoteId(remoteFolder.Id);
                if (localFolder.Name.Equals(remoteFolder.Name))
                {
                    mappedObject.Name = localFolder.Name;
                }
                else if (localFolder.LastWriteTimeUtc.CompareTo((DateTime)remoteFolder.LastModificationDate) > 0)
                {
                    string oldName = remoteFolder.Name;
                    try {
                        remoteFolder.Rename(localFolder.Name, true);
                    } catch (CmisConstraintException e) {
                        if (!Utils.IsValidISO885915(localFolder.Name))
                        {
                            OperationsLogger.Warn(string.Format("Server denied to rename {0} to {1}, perhaps because it contains UTF-8 characters", oldName, localFolder.Name));
                            throw new InteractionNeededException(string.Format("Server denied renaming of {0}", oldName), e)
                                  {
                                      Title       = string.Format("Server denied renaming of {0}", oldName),
                                      Description = string.Format("Server denied to rename {0} to {1}, perhaps because it contains UTF-8 characters", oldName, localFolder.Name)
                                  };
                        }

                        throw;
                    }

                    mappedObject.Name = remoteFolder.Name;
                    OperationsLogger.Info(string.Format("Renamed remote folder {0} with id {2} to {1}", oldName, remoteFolder.Id, remoteFolder.Name));
                }
                else
                {
                    string oldName = localFolder.Name;
                    localFolder.MoveTo(Path.Combine(localFolder.Parent.FullName, remoteFolder.Name));
                    mappedObject.Name = remoteFolder.Name;
                    OperationsLogger.Info(string.Format("Renamed local folder {0} to {1}", Path.Combine(localFolder.Parent.FullName, oldName), remoteFolder.Name));
                }

                mappedObject.LastLocalWriteTimeUtc  = localFolder.LastWriteTimeUtc;
                mappedObject.LastRemoteWriteTimeUtc = (DateTime)remoteFolder.LastModificationDate;
                mappedObject.LastChangeToken        = remoteFolder.ChangeToken;
                mappedObject.Ignored = remoteFolder.AreAllChildrenIgnored();
                this.Storage.SaveMappedObject(mappedObject);
            }
            else if (localFileSystemInfo is IFileInfo)
            {
                var localFile    = localFileSystemInfo as IFileInfo;
                var remoteFile   = remoteId as IDocument;
                var mappedObject = this.Storage.GetObjectByRemoteId(remoteFile.Id);
                if (localFile.Name.Equals(remoteFile.Name))
                {
                    mappedObject.Name = localFile.Name;
                    this.Storage.SaveMappedObject(mappedObject);
                    this.changeChangeSolver.Solve(localFileSystemInfo, remoteId, localContent, remoteContent);
                }
                else
                {
                    string desc = string.Format(
                        "The local file {0} has been locally renamed from {1} to {2} and remotely to {3}. " +
                        "Fix this conflict by renaming the remote file to {2} or the local file to {3}.",
                        localFile.FullName,
                        mappedObject.Name,
                        localFile.Name,
                        remoteFile.Name);
                    OperationsLogger.Warn("Synchronization Conflict: " + desc);
                    throw new InteractionNeededException("Synchronization Conflict")
                          {
                              Title       = "Synchronization Conflict",
                              Description = desc
                          };
                }
            }
        }
        /// <summary>
        /// Solve the specified situation by using the storage, localFile and remoteId.
        /// Uploads the file content if content has been changed. Otherwise simply saves the
        /// last modification date.
        /// </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.NONE,
            ContentChangeType remoteContent = ContentChangeType.NONE)
        {
            if (!localFileSystemInfo.Exists)
            {
                throw new ArgumentException("Given local path does not exists: " + localFileSystemInfo.FullName);
            }

            // Match local changes to remote changes and updated them remotely
            IMappedObject mappedObject = this.Storage.GetObject(localFileSystemInfo);

            if (mappedObject == null)
            {
                throw new ArgumentException(string.Format("Could not find db entry for {0} => invoke crawl sync", localFileSystemInfo.FullName));
            }

            if (mappedObject.LastChangeToken != (remoteId as ICmisObjectProperties).ChangeToken)
            {
                throw new ArgumentException(string.Format("remote {1} {0} has also been changed since last sync => invoke crawl sync", remoteId.Id, remoteId is IDocument ? "document" : "folder"));
            }

            IFileInfo localFile = localFileSystemInfo as IFileInfo;

            if (localFile != null && localFile.IsContentChangedTo(mappedObject, scanOnlyIfModificationDateDiffers: true))
            {
                Logger.Debug(string.Format("\"{0}\" is different from {1}", localFile.FullName, mappedObject.ToString()));
                OperationsLogger.Debug(string.Format("Local file \"{0}\" has been changed", localFile.FullName));
                var doc = remoteId as IDocument;
                try {
                    var transmission = this.transmissionManager.CreateTransmission(TransmissionType.UPLOAD_MODIFIED_FILE, localFile.FullName);
                    mappedObject.LastChecksum = UploadFile(localFile, doc, transmission);
                } catch (Exception ex) {
                    if (ex.InnerException is CmisPermissionDeniedException)
                    {
                        OperationsLogger.Warn(string.Format("Local changed file \"{0}\" has not been uploaded: PermissionDenied", localFile.FullName));
                        return;
                    }
                    else if (ex.InnerException is CmisStorageException)
                    {
                        OperationsLogger.Warn(string.Format("Local changed file \"{0}\" has not been uploaded: StorageException", localFile.FullName), ex);
                        return;
                    }

                    throw;
                }

                mappedObject.LastRemoteWriteTimeUtc = doc.LastModificationDate;
                mappedObject.LastLocalWriteTimeUtc  = localFile.LastWriteTimeUtc;
                mappedObject.LastContentSize        = localFile.Length;

                OperationsLogger.Info(string.Format("Local changed file \"{0}\" has been uploaded", localFile.FullName));
            }

            if (this.ServerCanModifyDateTimes)
            {
                try {
                    if (remoteId is IDocument)
                    {
                        var doc = remoteId as IDocument;
                        doc.UpdateLastWriteTimeUtc(localFileSystemInfo.LastWriteTimeUtc);
                        mappedObject.LastRemoteWriteTimeUtc = doc.LastModificationDate ?? localFileSystemInfo.LastWriteTimeUtc;
                    }
                    else if (remoteId is IFolder)
                    {
                        var folder = remoteId as IFolder;
                        folder.UpdateLastWriteTimeUtc(localFileSystemInfo.LastWriteTimeUtc);
                        mappedObject.LastRemoteWriteTimeUtc = folder.LastModificationDate ?? localFileSystemInfo.LastWriteTimeUtc;
                    }
                } catch (CmisPermissionDeniedException) {
                    Logger.Debug(string.Format("Locally changed modification date \"{0}\"is not uploaded to the server: PermissionDenied", localFileSystemInfo.LastWriteTimeUtc));
                }
            }

            mappedObject.LastChangeToken       = (remoteId as ICmisObjectProperties).ChangeToken;
            mappedObject.LastLocalWriteTimeUtc = localFileSystemInfo.LastWriteTimeUtc;
            this.Storage.SaveMappedObject(mappedObject);
        }
        public override void Solve(
            IFileSystemInfo localFileSystemInfo,
            IObjectId remoteId,
            ContentChangeType localContent,
            ContentChangeType remoteContent)
        {
            var    savedObject   = this.Storage.GetObjectByRemoteId(remoteId.Id);
            Guid?  newParentUuid = localFileSystemInfo is IFileInfo ? (localFileSystemInfo as IFileInfo).Directory.Uuid : (localFileSystemInfo as IDirectoryInfo).Parent.Uuid;
            string newParentId   = this.Storage.GetObjectByGuid((Guid)newParentUuid).RemoteObjectId;

            savedObject.Ignored = (remoteId as ICmisObject).AreAllChildrenIgnored();
            if (localFileSystemInfo.Name == (remoteId as ICmisObject).Name)
            {
                // Both names are equal => only move to new remote parent
                try {
                    (remoteId as IFileableCmisObject).Move(this.Session.GetObject(savedObject.ParentId), this.Session.GetObject(newParentId));
                } catch (CmisPermissionDeniedException) {
                    OperationsLogger.Info(string.Format("Permission Denied: Cannot move remote object {0} from {1} to {2}", remoteId.Id, savedObject.ParentId, newParentId));
                    return;
                }

                savedObject.Name     = localFileSystemInfo.Name;
                savedObject.ParentId = newParentId;
                this.Storage.SaveMappedObject(savedObject);
                this.changeChangeSolver.Solve(localFileSystemInfo, remoteId, localContent, remoteContent);
            }
            else
            {
                // Names are different to each other
                if (localFileSystemInfo.Name == savedObject.Name)
                {
                    // Remote rename and local move => Move remote and rename locally => change change solver
                    try {
                        remoteId = (remoteId as IFileableCmisObject).Move(this.Session.GetObject(savedObject.ParentId), this.Session.GetObject(newParentId));
                    } catch (CmisPermissionDeniedException) {
                        OperationsLogger.Info(string.Format("Permission Denied: Cannot move remote object {0} from {1} to {2}", remoteId.Id, savedObject.ParentId, newParentId));
                        return;
                    }

                    var    localParentPath = localFileSystemInfo is IFileInfo ? (localFileSystemInfo as IFileInfo).Directory.FullName : (localFileSystemInfo as IDirectoryInfo).Parent.FullName;
                    string newPath         = Path.Combine(localParentPath, (remoteId as ICmisObject).Name);
                    this.MoveTo(localFileSystemInfo, localFileSystemInfo.FullName, newPath);
                    savedObject.Name     = localFileSystemInfo.Name;
                    savedObject.ParentId = newParentId;
                    this.Storage.SaveMappedObject(savedObject);
                    this.changeChangeSolver.Solve(localFileSystemInfo, remoteId, localContent, remoteContent);
                }
                else
                {
                    // Both sides have been renamed => Move remote => rename rename solver
                    try {
                        (remoteId as IFileableCmisObject).Move(this.Session.GetObject(savedObject.ParentId), this.Session.GetObject(newParentId));
                    } catch (CmisPermissionDeniedException) {
                        OperationsLogger.Info(string.Format("Permission Denied: Cannot move remote object {0} from {1} to {2}", remoteId.Id, savedObject.ParentId, newParentId));
                        return;
                    }

                    savedObject.ParentId = newParentId;
                    this.Storage.SaveMappedObject(savedObject);
                    this.renameRenameSolver.Solve(localFileSystemInfo, remoteId, localContent, remoteContent);
                }
            }
        }
示例#24
0
        /// <summary>
        /// Adds the Object to Disk and Database
        /// </summary>
        /// <param name='localFile'>
        /// Local file.
        /// </param>
        /// <param name='remoteId'>
        /// Remote Object (already fetched).
        /// </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>
        /// <exception cref='ArgumentException'>
        /// Is thrown when remoteId is not prefetched.
        /// </exception>
        public override void Solve(
            IFileSystemInfo localFile,
            IObjectId remoteId,
            ContentChangeType localContent  = ContentChangeType.NONE,
            ContentChangeType remoteContent = ContentChangeType.NONE)
        {
            if (localFile is IDirectoryInfo)
            {
                if (!(remoteId is IFolder))
                {
                    throw new ArgumentException("remoteId has to be a prefetched Folder");
                }

                var            remoteFolder = remoteId as IFolder;
                IDirectoryInfo localFolder  = localFile as IDirectoryInfo;
                localFolder.Create();

                Guid uuid = Guid.Empty;
                if (localFolder.IsExtendedAttributeAvailable())
                {
                    uuid = Guid.NewGuid();
                    try {
                        localFolder.Uuid = uuid;
                    } catch (RestoreModificationDateException) {
                    }
                }

                if (remoteFolder.LastModificationDate != null)
                {
                    try {
                        localFolder.LastWriteTimeUtc = (DateTime)remoteFolder.LastModificationDate;
                    } catch (IOException e) {
                        Logger.Info("Directory modification date could not be synced", e);
                    }
                }

                var mappedObject = new MappedObject(remoteFolder);
                mappedObject.Guid = uuid;
                mappedObject.LastRemoteWriteTimeUtc = remoteFolder.LastModificationDate;
                mappedObject.LastLocalWriteTimeUtc  = localFolder.LastWriteTimeUtc;
                mappedObject.Ignored = remoteFolder.AreAllChildrenIgnored();
                this.Storage.SaveMappedObject(mappedObject);
                OperationsLogger.Info(string.Format("New local folder {0} created and mapped to remote folder {1}", localFolder.FullName, remoteId.Id));
            }
            else if (localFile is IFileInfo)
            {
                if (!(remoteId is IDocument))
                {
                    throw new ArgumentException("remoteId has to be a prefetched Document");
                }

                Guid     guid          = Guid.NewGuid();
                byte[]   localFileHash = null;
                DateTime?lastLocalFileModificationDate = null;
                var      file = localFile as IFileInfo;
                if (file.Exists)
                {
                    Guid?uuid = file.Uuid;
                    if (uuid != null)
                    {
                        if (this.Storage.GetObjectByGuid((Guid)uuid) != null)
                        {
                            throw new ArgumentException("This file has already been synced => force crawl sync");
                        }
                    }

                    lastLocalFileModificationDate = file.LastWriteTimeUtc;
                    if (this.MergeExistingFileWithRemoteFile(file, remoteId as IDocument, guid, out localFileHash))
                    {
                        return;
                    }

                    Logger.Debug(string.Format("This file {0} conflicts with remote file => conflict file will could be produced after download", file.FullName));
                }

                var cacheFile = this.fsFactory.CreateDownloadCacheFileInfo(guid);

                IDocument remoteDoc    = remoteId as IDocument;
                var       transmission = this.manager.CreateTransmission(TransmissionType.DOWNLOAD_NEW_FILE, localFile.FullName, cacheFile.FullName);
                byte[]    hash         = DownloadCacheFile(cacheFile, remoteDoc, transmission, this.fsFactory);

                try {
                    cacheFile.Uuid = guid;
                } catch (RestoreModificationDateException e) {
                    Logger.Debug("Could not retore the last modification date of " + cacheFile.FullName, e);
                }

                try {
                    cacheFile.MoveTo(file.FullName);
                } catch (IOException e) {
                    file.Refresh();
                    if (file.Exists)
                    {
                        if (localFileHash == null ||
                            lastLocalFileModificationDate == null ||
                            !lastLocalFileModificationDate.Equals(file.LastWriteTimeUtc))
                        {
                            lastLocalFileModificationDate = file.LastWriteTimeUtc;
                            using (var f = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) {
                                localFileHash = SHA1Managed.Create().ComputeHash(f);
                            }
                        }

                        if (localFileHash.SequenceEqual(hash))
                        {
                            file.Uuid = guid;
                            try {
                                cacheFile.Delete();
                            } catch (IOException) {
                            }
                        }
                        else
                        {
                            IFileInfo conflictFile = this.fsFactory.CreateConflictFileInfo(file);
                            try {
                                IFileInfo targetFile = cacheFile.Replace(file, conflictFile, true);
                                try {
                                    targetFile.Uuid = guid;
                                } catch (RestoreModificationDateException restoreException) {
                                    Logger.Debug("Could not retore the last modification date of " + targetFile.FullName, restoreException);
                                }
                            } catch (Exception ex) {
                                transmission.FailedException = ex;
                                throw;
                            }

                            try {
                                conflictFile.Uuid = null;
                            } catch (RestoreModificationDateException restoreException) {
                                Logger.Debug("Could not retore the last modification date of " + conflictFile.FullName, restoreException);
                            }
                        }
                    }
                    else
                    {
                        transmission.FailedException = e;
                        throw;
                    }
                }

                file.Refresh();
                if (remoteDoc.LastModificationDate != null)
                {
                    try {
                        file.LastWriteTimeUtc = (DateTime)remoteDoc.LastModificationDate;
                    } catch (IOException e) {
                        Logger.Debug("Cannot set last modification date", e);
                    }
                }

                MappedObject mappedObject = new MappedObject(
                    file.Name,
                    remoteDoc.Id,
                    MappedObjectType.File,
                    remoteDoc.Parents[0].Id,
                    remoteDoc.ChangeToken,
                    remoteDoc.ContentStreamLength ?? 0)
                {
                    Guid = guid,
                    LastLocalWriteTimeUtc  = file.LastWriteTimeUtc,
                    LastRemoteWriteTimeUtc = remoteDoc.LastModificationDate,
                    LastChecksum           = hash,
                    ChecksumAlgorithmName  = "SHA-1"
                };
                this.Storage.SaveMappedObject(mappedObject);
                OperationsLogger.Info(string.Format("New local file {0} created and mapped to remote file {1}", file.FullName, remoteId.Id));
                transmission.Status = TransmissionStatus.FINISHED;
            }
        }
示例#25
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.NONE,
            ContentChangeType remoteContent = ContentChangeType.NONE)
        {
            Stopwatch completewatch = new Stopwatch();

            completewatch.Start();
            Logger.Debug("Starting LocalObjectAdded");
            string parentId = this.GetParentId(localFileSystemInfo, this.Storage);

            ICmisObject addedObject;

            try {
                addedObject = this.AddCmisObject(localFileSystemInfo, parentId, this.Session);
            } catch (CmisConstraintException e) {
                if (!Utils.IsValidISO885915(localFileSystemInfo.Name))
                {
                    OperationsLogger.Warn(string.Format("Server denied creation of {0}, perhaps because it contains a UTF-8 character", localFileSystemInfo.Name), e);
                    throw new InteractionNeededException(string.Format("Server denied creation of {0}", localFileSystemInfo.Name), e)
                          {
                              Title       = string.Format("Server denied creation of {0}", localFileSystemInfo.Name),
                              Description = string.Format("Server denied creation of {0}, perhaps because it contains a UTF-8 character", localFileSystemInfo.FullName)
                          };
                }

                throw;
            } catch (CmisPermissionDeniedException e) {
                OperationsLogger.Warn(string.Format("Permission denied while trying to Create the locally added object {0} on the server ({1}).", localFileSystemInfo.FullName, e.Message));
                return;
            }

            Guid uuid = this.WriteOrUseUuidIfSupported(localFileSystemInfo);

            OperationsLogger.Info(string.Format("Created remote {2} {0} for {1}", addedObject.Id, localFileSystemInfo.FullName, addedObject is IFolder ? "folder" : "document"));

            MappedObject mapped = new MappedObject(
                localFileSystemInfo.Name,
                addedObject.Id,
                localFileSystemInfo is IDirectoryInfo ? MappedObjectType.Folder : MappedObjectType.File,
                parentId,
                addedObject.ChangeToken)
            {
                Guid = uuid,
                LastRemoteWriteTimeUtc = addedObject.LastModificationDate,
                LastLocalWriteTimeUtc  = localFileSystemInfo is IFileInfo && (localFileSystemInfo as IFileInfo).Length > 0 ? (DateTime?)null : (DateTime?)localFileSystemInfo.LastWriteTimeUtc,
                LastChangeToken        = addedObject.ChangeToken,
                LastContentSize        = localFileSystemInfo is IDirectoryInfo ? -1 : 0,
                ChecksumAlgorithmName  = localFileSystemInfo is IDirectoryInfo ? null : "SHA-1",
                LastChecksum           = localFileSystemInfo is IDirectoryInfo ? null : SHA1.Create().ComputeHash(new byte[0])
            };

            this.Storage.SaveMappedObject(mapped);

            var localFile = localFileSystemInfo as IFileInfo;

            if (localFile != null)
            {
                FileTransmissionEvent transmissionEvent = new FileTransmissionEvent(FileTransmissionType.UPLOAD_NEW_FILE, localFile.FullName);
                this.transmissionManager.AddTransmission(transmissionEvent);
                if (localFile.Length > 0)
                {
                    Stopwatch watch = new Stopwatch();
                    OperationsLogger.Debug(string.Format("Uploading file content of {0}", localFile.FullName));
                    watch.Start();
                    IFileUploader uploader = ContentTaskUtils.CreateUploader();
                    using (SHA1 hashAlg = new SHA1Managed()) {
                        try {
                            using (var fileStream = localFile.Open(FileMode.Open, FileAccess.Read)) {
                                uploader.UploadFile(addedObject as IDocument, fileStream, transmissionEvent, hashAlg);
                                mapped.ChecksumAlgorithmName = "SHA-1";
                                mapped.LastChecksum          = hashAlg.Hash;
                            }
                        } catch (Exception ex) {
                            if (ex is UploadFailedException && (ex as UploadFailedException).InnerException is CmisStorageException)
                            {
                                OperationsLogger.Warn(string.Format("Could not upload file content of {0}:", localFile.FullName), (ex as UploadFailedException).InnerException);
                                transmissionEvent.ReportProgress(new TransmissionProgressEventArgs {
                                    FailedException = ex
                                });
                                return;
                            }

                            transmissionEvent.ReportProgress(new TransmissionProgressEventArgs {
                                FailedException = ex
                            });
                            throw;
                        }
                    }

                    watch.Stop();

                    if (this.ServerCanModifyDateTimes)
                    {
                        (addedObject as IDocument).UpdateLastWriteTimeUtc(localFile.LastWriteTimeUtc);
                    }

                    mapped.LastContentSize        = localFile.Length;
                    mapped.LastChangeToken        = addedObject.ChangeToken;
                    mapped.LastRemoteWriteTimeUtc = addedObject.LastModificationDate;
                    mapped.LastLocalWriteTimeUtc  = localFileSystemInfo.LastWriteTimeUtc;
                    if (mapped.RemoteObjectId != addedObject.Id)
                    {
                        this.Storage.RemoveObject(mapped);
                        mapped.RemoteObjectId = addedObject.Id;
                    }

                    this.Storage.SaveMappedObject(mapped);
                    OperationsLogger.Info(string.Format("Uploaded file content of {0} in [{1} msec]", localFile.FullName, watch.ElapsedMilliseconds));
                }

                transmissionEvent.ReportProgress(new TransmissionProgressEventArgs {
                    Completed = true
                });
            }

            completewatch.Stop();
            Logger.Debug(string.Format("Finished LocalObjectAdded after [{0} msec]", completewatch.ElapsedMilliseconds));
        }
        /// <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)
        {
            var obj = this.Storage.GetObjectByRemoteId(remoteId.Id);

            if (localFileSystemInfo is IDirectoryInfo)
            {
                obj.LastLocalWriteTimeUtc  = localFileSystemInfo.LastWriteTimeUtc;
                obj.LastRemoteWriteTimeUtc = (remoteId as IFolder).LastModificationDate;
                obj.LastChangeToken        = (remoteId as IFolder).ChangeToken;
                this.Storage.SaveMappedObject(obj);
            }
            else if (localFileSystemInfo is IFileInfo)
            {
                var  fileInfo         = localFileSystemInfo as IFileInfo;
                var  doc              = remoteId as IDocument;
                bool updateLocalDate  = false;
                bool updateRemoteDate = false;
                if (remoteContent == ContentChangeType.NONE)
                {
                    if (fileInfo.IsContentChangedTo(obj, true))
                    {
                        // Upload local content
                        updateRemoteDate = true;
                        try {
                            obj.LastChecksum    = LocalObjectChanged.UploadFile(fileInfo, doc, this.transmissionManager);
                            obj.LastContentSize = doc.ContentStreamLength ?? fileInfo.Length;
                        } catch (Exception ex) {
                            if (ex.InnerException is CmisPermissionDeniedException)
                            {
                                OperationsLogger.Warn(string.Format("Local changed file \"{0}\" has not been uploaded: PermissionDenied", fileInfo.FullName), ex.InnerException);
                                return;
                            }

                            throw;
                        }
                    }
                    else
                    {
                        // Just date sync
                        if (doc.LastModificationDate != null && fileInfo.LastWriteTimeUtc < (DateTime)doc.LastModificationDate)
                        {
                            updateLocalDate = true;
                        }
                        else
                        {
                            updateRemoteDate = true;
                        }
                    }
                }
                else
                {
                    byte[] actualLocalHash;
                    if (fileInfo.IsContentChangedTo(obj, out actualLocalHash, true))
                    {
                        // Check if both are changed to the same value
                        if (actualLocalHash == null)
                        {
                            using (var f = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) {
                                actualLocalHash = SHA1Managed.Create().ComputeHash(f);
                            }
                        }

                        byte[] remoteHash = doc.ContentStreamHash();
                        if (remoteHash != null && actualLocalHash.SequenceEqual(remoteHash))
                        {
                            // Both files are equal
                            obj.LastChecksum    = remoteHash;
                            obj.LastContentSize = fileInfo.Length;

                            // Sync dates
                            if (doc.LastModificationDate != null && fileInfo.LastWriteTimeUtc < (DateTime)doc.LastModificationDate)
                            {
                                updateLocalDate = true;
                            }
                            else
                            {
                                updateRemoteDate = true;
                            }
                        }
                        else
                        {
                            // Both are different => Check modification dates
                            // Download remote version and create conflict file
                            updateLocalDate     = true;
                            obj.LastChecksum    = DownloadChanges(fileInfo, doc, obj, this.fsFactory, this.transmissionManager, Logger);
                            obj.LastContentSize = doc.ContentStreamLength ?? 0;
                        }
                    }
                    else
                    {
                        // Download remote content
                        updateLocalDate     = true;
                        obj.LastChecksum    = DownloadChanges(fileInfo, doc, obj, this.fsFactory, this.transmissionManager, Logger);
                        obj.LastContentSize = doc.ContentStreamLength ?? 0;
                    }
                }

                if (this.ServerCanModifyDateTimes)
                {
                    if (updateLocalDate)
                    {
                        fileInfo.LastWriteTimeUtc = (DateTime)doc.LastModificationDate;
                    }
                    else if (updateRemoteDate)
                    {
                        doc.UpdateLastWriteTimeUtc(fileInfo.LastWriteTimeUtc);
                    }
                    else
                    {
                        throw new ArgumentException();
                    }
                }

                obj.LastChangeToken        = doc.ChangeToken;
                obj.LastLocalWriteTimeUtc  = localFileSystemInfo.LastWriteTimeUtc;
                obj.LastRemoteWriteTimeUtc = doc.LastModificationDate;
                this.Storage.SaveMappedObject(obj);
            }
        }