using System; using System.Collections.Generic; using System.IO; using AppLimit.CloudComputing.SharpBox.Common.IO; using AppLimit.CloudComputing.SharpBox.StorageProvider.API; using AppLimit.CloudComputing.SharpBox.Exceptions; namespace AppLimit.CloudComputing.SharpBox.StorageProvider { /// /// This class has to be used in combination with the GenericStorageProvider class /// and supports all generic logic on the service level /// public abstract class GenericStorageProviderService : IStorageProviderService { internal const string TokenGenericCredUsername = "TokenCredGenericUsername"; internal const string TokenGenericCredPassword = "TokenCredGenericPassword"; /// /// This method verifies if the given configuration is compatible to the implemented /// service provider. /// /// /// public abstract bool VerifyAccessTokenType(ICloudStorageAccessToken token); /// /// This method generates a session to a webdav share via access token /// /// /// /// public abstract IStorageProviderSession CreateSession(ICloudStorageAccessToken token, ICloudStorageConfiguration configuration); /// /// This method closes the session /// /// public virtual void CloseSession(IStorageProviderSession session) { // nothing to do here } public virtual CloudStorageLimits GetLimits(IStorageProviderSession session) { return session.ServiceConfiguration.Limits; } /// /// This method request a directory entry from the storage provider service /// /// /// /// /// public abstract ICloudFileSystemEntry RequestResource(IStorageProviderSession session, string name, ICloudDirectoryEntry parent); /// /// This method updates the locally cache resource metadata from the storage service /// /// /// public abstract void RefreshResource(IStorageProviderSession session, ICloudFileSystemEntry resource); /// /// This method removes a resource in the storage provider service /// /// /// /// public abstract bool DeleteResource(IStorageProviderSession session, ICloudFileSystemEntry entry); /// /// This method deletes a resource in the storage provider service /// /// /// /// /// public abstract bool MoveResource(IStorageProviderSession session, ICloudFileSystemEntry fsentry, ICloudDirectoryEntry newParent); /// /// This method deletes a resource in the storage provider service /// /// /// /// /// public virtual bool CopyResource(IStorageProviderSession session, ICloudFileSystemEntry fsentry, ICloudDirectoryEntry newParent) { throw new NotSupportedException("This operation is not supported"); } /// /// Writes a generic token onto the storage collection /// /// /// /// public virtual void StoreToken(IStorageProviderSession session, Dictionary tokendata, ICloudStorageAccessToken token) { if (token is GenericNetworkCredentials) { var creds = token as GenericNetworkCredentials; tokendata.Add(TokenGenericCredUsername, creds.UserName); tokendata.Add(TokenGenericCredPassword, creds.Password); } } /// /// Reads the token information /// /// /// public virtual ICloudStorageAccessToken LoadToken(Dictionary tokendata) { ICloudStorageAccessToken at = null; var type = tokendata[CloudStorage.TokenCredentialType]; if (type.Equals(typeof (GenericNetworkCredentials).ToString())) { var username = tokendata[TokenGenericCredUsername]; var password = tokendata[TokenGenericCredPassword]; var bc = new GenericNetworkCredentials { UserName = username, Password = password }; at = bc; } else if (type.Equals(typeof (GenericCurrentCredentials).ToString())) { at = new GenericCurrentCredentials(); } return at; } /// /// This method build up a valid resource url /// /// /// /// /// public virtual string GetResourceUrl(IStorageProviderSession session, ICloudFileSystemEntry fileSystemEntry, string additionalPath) { additionalPath = !string.IsNullOrEmpty(additionalPath) ? additionalPath.Trim('/') : string.Empty; var url = session.ServiceConfiguration.ServiceLocator.AbsoluteUri.Trim('/'); var entryPath = fileSystemEntry != null ? GenericHelper.GetResourcePath(fileSystemEntry).Trim('/') : string.Empty; if (!string.IsNullOrEmpty(entryPath)) { url += "/" + entryPath; } if (!string.IsNullOrEmpty(additionalPath)) { url += "/" + additionalPath; } return url; } /// /// This methid download the content of a file resource into a target download stream /// /// /// /// /// /// public virtual void DownloadResourceContent(IStorageProviderSession session, ICloudFileSystemEntry fileSystemEntry, Stream targetDataStream, FileOperationProgressChanged progressCallback, object progressContext) { // build the download stream using (var data = CreateDownloadStream(session, fileSystemEntry)) { // copy the data var res = StreamHelper.CopyStreamData(this, data, targetDataStream, CloudStorage.FileStreamCopyCallback, progressCallback, fileSystemEntry, progressContext); if (res.ResultCode == StreamHelperResultCodes.Aborted) throw new SharpBoxException(SharpBoxErrorCodes.ErrorTransferAbortedManually); // commit everything CommitStreamOperation(session, fileSystemEntry, nTransferDirection.nDownload, data); } } /// /// This method establishes a download stream with the storage service /// /// /// /// public abstract Stream CreateDownloadStream(IStorageProviderSession session, ICloudFileSystemEntry fileSystemEntry); /// /// This method establishes an upload stream with the storage service /// /// /// /// /// public abstract Stream CreateUploadStream(IStorageProviderSession session, ICloudFileSystemEntry fileSystemEntry, long uploadSize); public abstract bool SupportsDirectRetrieve { get; } #region resumable upload public virtual bool SupportsChunking { get { return false; } } public virtual IResumableUploadSession CreateUploadSession(IStorageProviderSession session, ICloudFileSystemEntry fileSystemEntry, long bytesToTransfer) { throw ResumableUploadNotSupported(); } public virtual void AbortUploadSession(IStorageProviderSession session, IResumableUploadSession uploadSession) { throw ResumableUploadNotSupported(); } public virtual void UploadChunk(IStorageProviderSession session, IResumableUploadSession uploadSession, Stream stream, long chunkLength) { throw ResumableUploadNotSupported(); } private static NotSupportedException ResumableUploadNotSupported() { return new NotSupportedException("Provider does not supports resumable uploads."); } #endregion /// /// This method commits a stream operation before the disposabl method of the stream will be called /// /// /// /// /// public abstract void CommitStreamOperation(IStorageProviderSession session, ICloudFileSystemEntry fileSystemEntry, nTransferDirection direction, Stream notDisposedStream); /// /// This method uploads data into a file resource /// /// /// /// /// /// public virtual void UploadResourceContent(IStorageProviderSession session, ICloudFileSystemEntry fileSystemEntry, Stream targetDataStream, FileOperationProgressChanged progressCallback, object progressContext) { // build the stream stream using (var data = CreateUploadStream(session, fileSystemEntry, targetDataStream.Length)) { // copy the data var res = StreamHelper.CopyStreamData(this, targetDataStream, data, CloudStorage.FileStreamCopyCallback, progressCallback, fileSystemEntry, progressContext); if (res.ResultCode == StreamHelperResultCodes.Aborted) throw new SharpBoxException(SharpBoxErrorCodes.ErrorTransferAbortedManually); // flush the upload stream to clean the caches data.Flush(); // commit everything CommitStreamOperation(session, fileSystemEntry, nTransferDirection.nUpload, data); } } /// /// This methid creates a directory object in the storage service /// /// /// /// /// public abstract ICloudFileSystemEntry CreateResource(IStorageProviderSession session, string name, ICloudDirectoryEntry parent); /// /// This method renames a resource in the storage service /// /// /// /// /// public abstract bool RenameResource(IStorageProviderSession session, ICloudFileSystemEntry fsentry, string newName); } }