/// <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); }
/// <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."); } }
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)); } }
/// <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)); } } }
/// <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."); } }
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); }
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); } } }
/// <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); }
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); }
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); } }
/// <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."); } }
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; }
/// <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; } }
/// <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="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."); } }
/// <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> /// 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"); } }
/// <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. /// </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)); }