/// <summary>
        /// Called when a file or folder is created in the remote storage.
        /// </summary>
        /// <remarks>In this method we create a new file/folder in user file system.</remarks>
        private async void CreatedAsync(object sender, FileSystemEventArgs e)
        {
            LogMessage(e.ChangeType.ToString(), e.FullPath);
            string remoteStoragePath = e.FullPath;

            try
            {
                string userFileSystemPath       = Mapping.ReverseMapPath(remoteStoragePath);
                string userFileSystemParentPath = Path.GetDirectoryName(userFileSystemPath);

                // Because of the on-demand population the file or folder placeholder may not exist in the user file system.
                // Here we also check that the folder content was loaded into user file system (the folder is not offline).
                if (Directory.Exists(userFileSystemParentPath) &&
                    !new DirectoryInfo(userFileSystemParentPath).Attributes.HasFlag(System.IO.FileAttributes.Offline))
                {
                    if (!FsPath.AvoidSync(remoteStoragePath))
                    {
                        FileSystemInfo remoteStorageItem = FsPath.GetFileSystemItem(remoteStoragePath);
                        await UserFileSystemItem.CreateAsync(userFileSystemParentPath, remoteStorageItem);

                        LogMessage("Created succesefully:", userFileSystemPath);
                    }
                }
            }
            catch (Exception ex)
            {
                LogError($"{e.ChangeType} failed:", remoteStoragePath, ex);
            }
        }
        /// <inheritdoc/>
        public async Task DeleteCompletionAsync(IOperationContext operationContext, IResultContext resultContext)
        {
            // On Windows, for move with overwrite on folders to function correctly,
            // the deletion of the folder in the remote storage must be done in DeleteCompletionAsync()
            // Otherwise the folder will be deleted before files in it can be moved.

            Logger.LogMessage($"{nameof(IFileSystemItem)}.{nameof(DeleteCompletionAsync)}()", UserFileSystemPath);

            FileSystemInfo remoteStorageItem = FsPath.GetFileSystemItem(RemoteStoragePath);

            if (remoteStorageItem != null)
            {
                if (remoteStorageItem is FileInfo)
                {
                    remoteStorageItem.Delete();
                }
                else
                {
                    (remoteStorageItem as DirectoryInfo).Delete(true);
                }
                Logger.LogMessage("Deleted item in remote storage succesefully", UserFileSystemPath);
            }

            Engine.CustomDataManager(UserFileSystemPath, Logger).Delete();
        }
        /// <summary>
        /// Called when a file content changed or file/folder attributes changed in the remote storage.
        /// </summary>
        /// <remarks>
        /// In this method we update corresponding file/folder information in user file system.
        /// We also dehydrate the file if it is not blocked.
        /// </remarks>
        private async void ChangedAsync(object sender, FileSystemEventArgs e)
        {
            LogMessage(e.ChangeType.ToString(), e.FullPath);
            string remoteStoragePath = e.FullPath;

            try
            {
                string userFileSystemPath = Mapping.ReverseMapPath(remoteStoragePath);

                // Because of the on-demand population the file or folder placeholder may not exist in the user file system.
                if (FsPath.Exists(userFileSystemPath))
                {
                    FileSystemInfo remoteStorageItem = FsPath.GetFileSystemItem(remoteStoragePath);

                    if (!FsPath.AvoidSync(remoteStoragePath))
                    {
                        // This check is only required because we can not prevent circular calls because of the simplicity of this example.
                        if (!await new UserFileSystemItem(userFileSystemPath).EqualsAsync(remoteStorageItem))
                        {
                            LogMessage("Item modified:", remoteStoragePath);
                            await new UserFileSystemItem(userFileSystemPath).UpdateAsync(remoteStorageItem);
                            LogMessage("Updated succesefully:", userFileSystemPath);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogError($"{e.ChangeType} failed:", remoteStoragePath, ex);
            }
        }
        /// <summary>
        /// Called when a file or folder is created in the remote storage.
        /// </summary>
        /// <remarks>In this method we create a new file/folder in user file system.</remarks>
        private async void CreatedAsync(object sender, FileSystemEventArgs e)
        {
            LogMessage(e.ChangeType.ToString(), e.FullPath);
            string remoteStoragePath = e.FullPath;

            try
            {
                // We do not want to sync MS Office temp files from remote storage.
                if (!FsPath.AvoidSync(remoteStoragePath))
                {
                    string userFileSystemPath       = Mapping.ReverseMapPath(remoteStoragePath);
                    string userFileSystemParentPath = Path.GetDirectoryName(userFileSystemPath);

                    // Because of the on-demand population the file or folder placeholder may not exist in the user file system
                    // or the folder may be offline.
                    if (Directory.Exists(userFileSystemParentPath) &&
                        !new DirectoryInfo(userFileSystemParentPath).Attributes.HasFlag(System.IO.FileAttributes.Offline))
                    {
                        FileSystemInfo          remoteStorageItem = FsPath.GetFileSystemItem(remoteStoragePath);
                        FileSystemItemBasicInfo newItemInfo       = Mapping.GetUserFileSysteItemBasicInfo(remoteStorageItem);
                        await UserFileSystemRawItem.CreateAsync(userFileSystemParentPath, new[] { newItemInfo });

                        LogMessage($"Created succesefully", userFileSystemPath);
                    }
                }
            }
            catch (Exception ex)
            {
                LogError($"{e.ChangeType} failed", remoteStoragePath, null, ex);
            }
        }
        ///<inheritdoc>
        public async Task MoveToAsync(string userFileSystemNewPath, byte[] targetParentItemId, IOperationContext operationContext, IConfirmationResultContext resultContext)
        {
            string userFileSystemOldPath = this.UserFileSystemPath;

            Logger.LogMessage($"{nameof(IFileSystemItem)}.{nameof(MoveToAsync)}()", userFileSystemOldPath, userFileSystemNewPath);

            string remoteStorageOldPath = RemoteStoragePath;
            string remoteStorageNewPath = Mapping.MapPath(userFileSystemNewPath);

            FileSystemInfo remoteStorageOldItem = FsPath.GetFileSystemItem(remoteStorageOldPath);

            if (remoteStorageOldItem != null)
            {
                if (remoteStorageOldItem is FileInfo)
                {
                    (remoteStorageOldItem as FileInfo).MoveTo(remoteStorageNewPath, true);
                }
                else
                {
                    (remoteStorageOldItem as DirectoryInfo).MoveTo(remoteStorageNewPath);
                }
                Logger.LogMessage("Moved item in remote storage succesefully", userFileSystemOldPath, userFileSystemNewPath);
            }

            await Engine.CustomDataManager(userFileSystemOldPath, Logger).MoveToAsync(userFileSystemNewPath);
        }
예제 #6
0
        /// <summary>
        /// Called when a file or folder is created in the remote storage.
        /// </summary>
        /// <remarks>In this method we create a new file/folder in the user file system.</remarks>
        private async void CreatedAsync(object sender, FileSystemEventArgs e)
        {
            LogMessage(e.ChangeType.ToString(), e.FullPath);
            string remoteStoragePath = e.FullPath;

            try
            {
                string userFileSystemPath = Mapping.ReverseMapPath(remoteStoragePath);

                // This check is only required because we can not prevent circular calls because of the simplicity of this example.
                // In your real-life application you will not sent updates from server back to client that issued the update.
                if (!FsPath.Exists(userFileSystemPath))
                {
                    string userFileSystemParentPath = Path.GetDirectoryName(userFileSystemPath);

                    // Because of the on-demand population the file or folder placeholder may not exist in the user file system
                    // or the folder may be offline.
                    FileSystemInfo remoteStorageItem = FsPath.GetFileSystemItem(remoteStoragePath);
                    if (remoteStorageItem != null)
                    {
                        IFileSystemItemMetadata newItemInfo = Mapping.GetUserFileSysteItemMetadata(remoteStorageItem);
                        if (await engine.ServerNotifications(userFileSystemParentPath).CreateAsync(new[] { newItemInfo }) > 0)
                        {
                            LogMessage($"Created succesefully", userFileSystemPath);
                            engine.CustomDataManager(userFileSystemPath, this).IsNew = false;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogError($"{e.ChangeType} failed", remoteStoragePath, null, ex);
            }
        }
예제 #7
0
        /// <summary>
        /// Called when a file content changed or file/folder attributes changed in the remote storage.
        /// </summary>
        /// <remarks>
        /// In this method we update corresponding file/folder information in user file system.
        /// We also dehydrate the file if it is not blocked.
        /// </remarks>
        private async void ChangedAsync(object sender, FileSystemEventArgs e)
        {
            LogMessage(e.ChangeType.ToString(), e.FullPath);
            string remoteStoragePath  = e.FullPath;
            string userFileSystemPath = null;

            try
            {
                userFileSystemPath = Mapping.ReverseMapPath(remoteStoragePath);

                // This check is only required because we can not prevent circular calls because of the simplicity of this example.
                // In your real-life application you will not sent updates from server back to client that issued the update.
                if (IsModified(userFileSystemPath, remoteStoragePath))
                {
                    FileSystemInfo          remoteStorageItem = FsPath.GetFileSystemItem(remoteStoragePath);
                    IFileSystemItemMetadata itemInfo          = Mapping.GetUserFileSysteItemMetadata(remoteStorageItem);

                    // Because of the on-demand population the file or folder placeholder may not exist in the user file system.
                    if (await engine.ServerNotifications(userFileSystemPath).UpdateAsync(itemInfo))
                    {
                        LogMessage("Updated succesefully", userFileSystemPath);
                    }
                }
            }
            catch (IOException ex)
            {
                // The file is blocked in the user file system. This is a normal behaviour.
                LogMessage(ex.Message);
            }
            catch (Exception ex)
            {
                LogError($"{e.ChangeType} failed", remoteStoragePath, null, ex);
            }
        }
예제 #8
0
        /// <summary>
        /// Updates information about the file or folder placeholder in the user file system.
        /// This method automatically hydrates and dehydrate files.
        /// </summary>
        /// <remarks>This method failes if the file or folder in user file system is modified (not in-sync with the remote storage).</remarks>
        /// <param name="itemInfo">New file or folder info.</param>
        /// <returns>True if the file was updated. False - otherwise.</returns>
        public async Task <bool> UpdateAsync(IFileSystemItemMetadata itemInfo)
        {
            FileSystemItemMetadataExt itemInfoExt = itemInfo as FileSystemItemMetadataExt ?? throw new NotImplementedException($"{nameof(FileSystemItemMetadataExt)}");

            try
            {
                // Because of the on-demand population the file or folder placeholder may not exist in the user file system.
                if (FsPath.Exists(userFileSystemPath))
                {
                    PlaceholderItem placeholderItem = PlaceholderItem.GetItem(userFileSystemPath);

                    // To be able to update the item we need to remove the read-only attribute.
                    if ((FsPath.GetFileSystemItem(userFileSystemPath).Attributes | System.IO.FileAttributes.ReadOnly) != 0)
                    {
                        FsPath.GetFileSystemItem(userFileSystemPath).Attributes &= ~System.IO.FileAttributes.ReadOnly;
                    }

                    // Dehydrate/hydrate the file, update file size, custom data, creation date, modification date, attributes.
                    await virtualDrive.Engine.ServerNotifications(userFileSystemPath).UpdateAsync(itemInfoExt);

                    // Set ETag.
                    await eTagManager.SetETagAsync(itemInfoExt.ETag);

                    // Clear icon.
                    //await ClearStateAsync();

                    // Set the read-only attribute and all custom columns data.
                    await SetLockedByAnotherUserAsync(itemInfoExt.LockedByAnotherUser);
                    await SetCustomColumnsDataAsync(itemInfoExt.CustomProperties);

                    return(true);
                }
            }
            catch (Exception ex)
            {
                await SetDownloadErrorStateAsync(ex);

                // Rethrow the exception preserving stack trace of the original exception.
                System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw();
            }
            return(false);
        }
예제 #9
0
        //$>

        //$<PlaceholderItem.SetItemInfo
        /// <summary>
        /// Updates information about the file or folder placeholder in the user file system.
        /// This method automatically hydrates and dehydrate files.
        /// </summary>
        /// <remarks>This method failes if the file or folder in user file system is modified (not in-sync with the remote storage).</remarks>
        /// <param name="itemInfo">New file or folder info.</param>
        /// <returns>True if the file was updated. False - otherwise.</returns>
        public async Task <bool> UpdateAsync(FileSystemItemBasicInfo itemInfo)
        {
            try
            {
                // Because of the on-demand population the file or folder placeholder may not exist in the user file system.
                if (FsPath.Exists(userFileSystemPath))
                {
                    PlaceholderItem placeholderItem = PlaceholderItem.GetItem(userFileSystemPath);

                    // To be able to update the item we need to remove the read-only attribute.
                    if ((FsPath.GetFileSystemItem(userFileSystemPath).Attributes | System.IO.FileAttributes.ReadOnly) != 0)
                    {
                        FsPath.GetFileSystemItem(userFileSystemPath).Attributes &= ~System.IO.FileAttributes.ReadOnly;
                    }

                    // Dehydrate/hydrate the file, update file size, custom data, creation date, modification date, attributes.
                    placeholderItem.SetItemInfo(itemInfo);

                    // Set ETag.
                    await ETag.SetETagAsync(userFileSystemPath, itemInfo.ETag);

                    // Clear icon.
                    //await ClearStateAsync();

                    // Set the "locked by another user" icon and all custom columns data.
                    await SetLockedByAnotherUserAsync(itemInfo.LockedByAnotherUser);
                    await SetCustomColumnsDataAsync(itemInfo.CustomProperties);

                    return(true);
                }
            }
            catch (Exception ex)
            {
                await SetDownloadErrorStateAsync(ex);

                // Rethrow the exception preserving stack trace of the original exception.
                System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw();
            }
            return(false);
        }
        /// <summary>
        /// Called when a file content changed or file/folder attributes changed in the remote storage.
        /// </summary>
        /// <remarks>
        /// In this method we update corresponding file/folder information in user file system.
        /// We also dehydrate the file if it is not blocked.
        /// </remarks>
        private async void ChangedAsync(object sender, FileSystemEventArgs e)
        {
            LogMessage(e.ChangeType.ToString(), e.FullPath);
            string remoteStoragePath = e.FullPath;

            try
            {
                // We do not want to sync MS Office temp files, etc. from remote storage.
                if (!FsPath.AvoidSync(remoteStoragePath))
                {
                    string userFileSystemPath = Mapping.ReverseMapPath(remoteStoragePath);

                    // Because of the on-demand population the file or folder placeholder may not exist in the user file system.
                    if (FsPath.Exists(userFileSystemPath))
                    {
                        FileSystemInfo remoteStorageItem = FsPath.GetFileSystemItem(remoteStoragePath);

                        // This check is only required because we can not prevent circular calls because of the simplicity of this example.
                        // In your real-life application you will not sent updates from server back to client that issued the update.
                        FileSystemItemBasicInfo itemInfo = Mapping.GetUserFileSysteItemBasicInfo(remoteStorageItem);
                        if (!await ETag.ETagEqualsAsync(userFileSystemPath, itemInfo))
                        {
                            await new UserFileSystemRawItem(userFileSystemPath).UpdateAsync(itemInfo);
                            LogMessage("Updated succesefully", userFileSystemPath);
                        }

                        // Update "locked by another user" icon.
                        await new UserFileSystemRawItem(userFileSystemPath).SetLockedByAnotherUserAsync(itemInfo.LockedByAnotherUser);
                    }
                }
            }
            catch (Exception ex)
            {
                LogError($"{e.ChangeType} failed", remoteStoragePath, null, ex);
            }
        }
        /// <summary>
        /// Creates or updates the item in the remote storage.
        /// </summary>
        /// <param name="mode">
        /// Indicates if the file should created or updated.
        /// Supported modes are <see cref="FileMode.CreateNew"/> and <see cref="FileMode.Open"/>
        /// </param>
        /// <param name="lockInfo">Information about the lock. Pass null if the item is not locked.</param>
        private async Task CreateOrUpdateAsync(FileMode mode, ServerLockInfo lockInfo = null)
        {
            if ((mode != FileMode.CreateNew) && (mode != FileMode.Open))
            {
                throw new ArgumentOutOfRangeException("mode", $"Must be {FileMode.CreateNew} or {FileMode.Open}");
            }

            FileSystemInfo userFileSystemItem = FsPath.GetFileSystemItem(userFileSystemPath);

            using (WindowsFileSystemItem userFileSystemWinItem = WindowsFileSystemItem.OpenReadAttributes(userFileSystemPath, FileMode.Open, FileShare.Read))
            //await using (FileStream userFileSystemStream = userFileSystemFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                // Create the new file/folder in the remote storage only if the file/folder in the user file system was not moved.
                // If the file is moved in user file system, move must first be syched to remote storage.
                if ((mode == FileMode.CreateNew) && PlaceholderItem.GetItem(userFileSystemPath).IsMoved())
                {
                    string originalPath = PlaceholderItem.GetItem(userFileSystemPath).GetOriginalPath();
                    throw new ConflictException(Modified.Client, $"The item was moved. Original path: {originalPath}");
                }

                // Ensures LastWriteTimeUtc is in sync with file content after Open() was called.
                userFileSystemItem.Refresh();

                IFileSystemItemBasicInfo info = GetBasicInfo(userFileSystemItem);

                // Update remote storage file.
                FileStream userFileSystemStream = null;
                try
                {
                    string eTag = null;
                    if (FsPath.IsFile(userFileSystemPath))
                    {
                        // File is marked as not in-sync when updated OR moved.
                        // Opening a file for reading triggers hydration, make sure to open only if content is modified.
                        if (PlaceholderFile.GetFileDataSizeInfo(userFileSystemWinItem.SafeHandle).ModifiedDataSize > 0)
                        {
                            //userFileSystemStream = new FileStream(userFileSystemWinItem.SafeHandle, FileAccess.Read);
                            userFileSystemStream = ((FileInfo)userFileSystemItem).Open(FileMode.Open, FileAccess.Read, FileShare.Read);
                        }
                        if (mode == FileMode.CreateNew)
                        {
                            string      userFileSystemParentPath = Path.GetDirectoryName(userFileSystemPath);
                            IUserFolder userFolder = await virtualDrive.GetItemAsync <IUserFolder>(userFileSystemParentPath);

                            eTag = await userFolder.CreateFileAsync((IFileBasicInfo)info, userFileSystemStream);
                        }
                        else
                        {
                            IUserFile userFile = await virtualDrive.GetItemAsync <IUserFile>(userFileSystemPath);

                            eTag = await userFile.UpdateAsync((IFileBasicInfo)info, userFileSystemStream, lockInfo);
                        }
                    }
                    else
                    {
                        if (mode == FileMode.CreateNew)
                        {
                            string      userFileSystemParentPath = Path.GetDirectoryName(userFileSystemPath);
                            IUserFolder userFolder = await virtualDrive.GetItemAsync <IUserFolder>(userFileSystemParentPath);

                            eTag = await userFolder.CreateFolderAsync((IFolderBasicInfo)info);
                        }
                        else
                        {
                            IUserFolder userFolder = await virtualDrive.GetItemAsync <IUserFolder>(userFileSystemPath);

                            eTag = await userFolder.UpdateAsync((IFolderBasicInfo)info, lockInfo);
                        }
                    }
                    await ETag.SetETagAsync(userFileSystemPath, eTag);

                    if (mode == FileMode.CreateNew)
                    {
                        PlaceholderItem.GetItem(userFileSystemPath).SetOriginalPath(userFileSystemPath);
                    }
                }
                finally
                {
                    if (userFileSystemStream != null)
                    {
                        userFileSystemStream.Close();
                    }
                }

                PlaceholderItem.SetInSync(userFileSystemWinItem.SafeHandle, true);
            }
        }