/// <inheritdoc/>
        public async Task<StorageObject> CopyStorageObject(StorageObject obj, string destinationContainerName, string destinationObjectName = null)
        {
            obj.AssertIsNotNull("obj", "Cannot create a null storage object.");
            obj.ContainerName.AssertIsNotNullOrEmpty("obj.ContainerName", "Cannot copy a storage object with a null or empty container name.");
            obj.Name.AssertIsNotNullOrEmpty("obj.Name", "Cannot copy a storage object without a name.");
            destinationContainerName.AssertIsNotNullOrEmpty("destinationContainerName", "Cannot copy a storage object to a null or empty destination container name.");

            string localDestinationObjectName = null;

            if(!string.IsNullOrEmpty(destinationObjectName))
            {
                localDestinationObjectName = destinationObjectName;
            }
            else
            {
                localDestinationObjectName = obj.FullName;
            }
            
            var client = this.GetRestClient();
            var resp = await client.CopyObject(obj.ContainerName, obj.FullName, destinationContainerName, localDestinationObjectName);

            if (resp.StatusCode != HttpStatusCode.Created)
            {
                throw new InvalidOperationException(string.Format("Failed to copy storage object '{0}'. The remote server returned the following status code: '{1}'.", obj.Name, resp.StatusCode));
            }

            var converter = this.ServiceLocator.Locate<IStorageObjectPayloadConverter>();
            var respObj = converter.Convert(obj.ContainerName, obj.FullName, resp.Headers);

            return respObj;
        }
        /// <inheritdoc/>
        public async Task <StorageObject> CopyStorageObject(StorageObject obj, string destinationContainerName, string destinationObjectName = null)
        {
            obj.AssertIsNotNull("obj", "Cannot create a null storage object.");
            obj.ContainerName.AssertIsNotNullOrEmpty("obj.ContainerName", "Cannot copy a storage object with a null or empty container name.");
            obj.Name.AssertIsNotNullOrEmpty("obj.Name", "Cannot copy a storage object without a name.");
            destinationContainerName.AssertIsNotNullOrEmpty("destinationContainerName", "Cannot copy a storage object to a null or empty destination container name.");

            string localDestinationObjectName = null;

            if (!string.IsNullOrEmpty(destinationObjectName))
            {
                localDestinationObjectName = destinationObjectName;
            }
            else
            {
                localDestinationObjectName = obj.FullName;
            }

            var client = this.GetRestClient();
            var resp   = await client.CopyObject(obj.ContainerName, obj.FullName, destinationContainerName, localDestinationObjectName);

            if (resp.StatusCode != HttpStatusCode.Created)
            {
                throw new InvalidOperationException(string.Format("Failed to copy storage object '{0}'. The remote server returned the following status code: '{1}'.", obj.Name, resp.StatusCode));
            }

            var converter = this.ServiceLocator.Locate <IStorageObjectPayloadConverter>();
            var respObj   = converter.Convert(obj.ContainerName, obj.FullName, resp.Headers);

            return(respObj);
        }
        /// <inheritdoc/>
        public async Task UpdateStorageObject(StorageObject obj)
        {
            obj.AssertIsNotNull("container", "Cannot update a storage object with a null object.");

            var client = this.GetPocoClient();
            await client.UpdateStorageObject(obj);
        }
        /// <inheritdoc/>
        public async Task <StorageObject> CopyStorageObject(string containerName, string objectName, string destinationContainerName, string destinationObjectName = null)
        {
            containerName.AssertIsNotNullOrEmpty("containerName", "Cannot copy a storage object with a container name that is null or empty.");
            objectName.AssertIsNotNullOrEmpty("objectName", "Cannot copy a storage object with a name that is null or empty.");
            destinationContainerName.AssertIsNotNullOrEmpty("destinationContainerName", "Cannot copy a storage object with null or empty destination container.");

            var requestObject = new StorageObject(objectName, containerName);
            var client        = this.GetPocoClient();

            return(await client.CopyStorageObject(requestObject, destinationContainerName, destinationObjectName));
        }
        /// <inheritdoc/>
        public async Task UpdateStorageObject(StorageObject item)
        {
            item.ContainerName.AssertIsNotNullOrEmpty("containerName", "Cannot update a storage object with a container name that is null or empty.");
            item.Name.AssertIsNotNullOrEmpty("objectName", "Cannot update a storage object with a name that is null or empty.");

            var client = this.GetRestClient();
            var resp   = await client.UpdateObject(item.ContainerName, item.Name, item.Metadata);

            if (resp.StatusCode != HttpStatusCode.Accepted)
            {
                throw new InvalidOperationException(string.Format("Failed to update storage object '{0}'. The remote server returned the following status code: '{1}'.", item.Name, resp.StatusCode));
            }
        }
        /// <inheritdoc/>
        public async Task<StorageObject> CreateStorageObject(string containerName, string objectName, IDictionary<string, string> metadata, Stream content)
        {
            containerName.AssertIsNotNullOrEmpty("containerName", "Cannot create a storage object with a container name that is null or empty.");
            objectName.AssertIsNotNullOrEmpty("objectName", "Cannot create a storage object with a name that is null or empty.");
            content.AssertIsNotNull("content", "Cannot create a storage object with null content");

            if (content.Length > this.LargeObjectThreshold)
            {
                return await this.CreateLargeStorageObject(containerName, objectName, metadata, content, this.LargeObjectSegments);
            }

            //TODO: handle the content type better... 
            var requestObject = new StorageObject(objectName, containerName, "application/octet-stream", metadata);
            var client = this.GetPocoClient();
            return await client.CreateStorageObject(requestObject, content);
        }
        /// <inheritdoc/>
        public async Task <StorageObject> CreateStorageObject(string containerName, string objectName, IDictionary <string, string> metadata, Stream content)
        {
            containerName.AssertIsNotNullOrEmpty("containerName", "Cannot create a storage object with a container name that is null or empty.");
            objectName.AssertIsNotNullOrEmpty("objectName", "Cannot create a storage object with a name that is null or empty.");
            content.AssertIsNotNull("content", "Cannot create a storage object with null content");

            if (content.Length > this.LargeObjectThreshold)
            {
                return(await this.CreateLargeStorageObject(containerName, objectName, metadata, content, this.LargeObjectSegments));
            }

            //TODO: handle the content type better...
            var requestObject = new StorageObject(objectName, containerName, "application/octet-stream", metadata);
            var client        = this.GetPocoClient();

            return(await client.CreateStorageObject(requestObject, content));
        }
        /// <inheritdoc/>
        public async Task<StorageObject> CreateStorageObject(StorageObject obj, Stream content)
        {
            obj.AssertIsNotNull("obj", "Cannot create a null storage object.");
            obj.ContainerName.AssertIsNotNullOrEmpty("obj.ContainerName", "Cannot create a storage object with a null or empty container name.");
            obj.Name.AssertIsNotNullOrEmpty("obj.Name","Cannot create a storage object without a name.");
            
            var contentLength = content.Length;
            var client = this.GetRestClient();
            var resp = await client.CreateObject(obj.ContainerName, obj.FullName, obj.Metadata, content);

            if (resp.StatusCode != HttpStatusCode.Created)
            {
                throw new InvalidOperationException(string.Format("Failed to create storage object '{0}'. The remote server returned the following status code: '{1}'.", obj.Name, resp.StatusCode));
            }

            var converter = this.ServiceLocator.Locate<IStorageObjectPayloadConverter>();
            var respObj = converter.Convert(obj.ContainerName, obj.FullName, resp.Headers, contentLength);

            return respObj;
        }
        /// <inheritdoc/>
        public async Task <StorageObject> CreateStorageObject(StorageObject obj, Stream content)
        {
            obj.AssertIsNotNull("obj", "Cannot create a null storage object.");
            obj.ContainerName.AssertIsNotNullOrEmpty("obj.ContainerName", "Cannot create a storage object with a null or empty container name.");
            obj.Name.AssertIsNotNullOrEmpty("obj.Name", "Cannot create a storage object without a name.");

            var contentLength = content.Length;
            var client        = this.GetRestClient();
            var resp          = await client.CreateObject(obj.ContainerName, obj.FullName, obj.Metadata, content);

            if (resp.StatusCode != HttpStatusCode.Created)
            {
                throw new InvalidOperationException(string.Format("Failed to create storage object '{0}'. The remote server returned the following status code: '{1}'.", obj.Name, resp.StatusCode));
            }

            var converter = this.ServiceLocator.Locate <IStorageObjectPayloadConverter>();
            var respObj   = converter.Convert(obj.ContainerName, obj.FullName, resp.Headers, contentLength);

            return(respObj);
        }
 /// <summary>
 /// Gets the Id of the segment that the given storage object represents.
 /// </summary>
 /// <param name="storageObject">The storage object to extract the Id from.</param>
 /// <returns>The Id of the segment that the file represents.</returns>
 internal int GetSegmentIdFromKey(StorageObject storageObject)
 {
     try
     {
         var segmentId = Convert.ToInt32(storageObject.Name);
         if (segmentId < 0)
         {
             throw new System.FormatException("Cannot get segment Id from key. Segment number cannot be negative.");
         }
         return(segmentId);
     }
     catch (System.OverflowException)
     {
         //if the segment number is bigger than an int32, then it's an invalid format
         throw new System.FormatException("Segment number is too large. The segment number must be a valid Int32.");
     }
     catch (System.FormatException)
     {
         //if the segment number is bigger than an int32, then it's an invalid format
         throw new System.FormatException(string.Format("The segment's file name does not have the correct format. '{0}' is invalid.", storageObject.FullName));
     }
 }
        /// <summary>
        /// Gets the Id of the segment that the given storage object represents.
        /// </summary>
        /// <param name="storageObject">The storage object to extract the Id from.</param>
        /// <returns>The Id of the segment that the file represents.</returns>
        internal int GetSegmentIdFromKey(StorageObject storageObject)
        {
            try
            {
                var segmentId = Convert.ToInt32(storageObject.Name);
                if (segmentId < 0)
                {
                    throw new System.FormatException("Cannot get segment Id from key. Segment number cannot be negative.");
                }
                return segmentId;

            }
            catch (System.OverflowException)
            {
                //if the segment number is bigger than an int32, then it's an invalid format
                throw new System.FormatException("Segment number is too large. The segment number must be a valid Int32.");
            }
            catch (System.FormatException)
            {
                //if the segment number is bigger than an int32, then it's an invalid format
                throw new System.FormatException(string.Format("The segment's file name does not have the correct format. '{0}' is invalid.", storageObject.FullName));
            }
        }
        /// <inheritdoc/>
        public async Task UpdateStorageObject(StorageObject item)
        {
            item.ContainerName.AssertIsNotNullOrEmpty("containerName", "Cannot update a storage object with a container name that is null or empty.");
            item.Name.AssertIsNotNullOrEmpty("objectName", "Cannot update a storage object with a name that is null or empty.");

            var client = this.GetRestClient();
            var resp = await client.UpdateObject(item.ContainerName, item.Name, item.Metadata);

            if (resp.StatusCode != HttpStatusCode.Accepted)
            {
                throw new InvalidOperationException(string.Format("Failed to update storage object '{0}'. The remote server returned the following status code: '{1}'.", item.Name, resp.StatusCode));
            }
        }
        /// <inheritdoc/>
        public async Task<StorageObject> CopyStorageObject(string containerName, string objectName, string destinationContainerName, string destinationObjectName = null)
        {
            containerName.AssertIsNotNullOrEmpty("containerName", "Cannot copy a storage object with a container name that is null or empty.");
            objectName.AssertIsNotNullOrEmpty("objectName", "Cannot copy a storage object with a name that is null or empty.");
            destinationContainerName.AssertIsNotNullOrEmpty("destinationContainerName", "Cannot copy a storage object with null or empty destination container.");
 
            var requestObject = new StorageObject(objectName, containerName);
            var client = this.GetPocoClient();
            return await client.CopyStorageObject(requestObject, destinationContainerName, destinationObjectName);
        }
 public async Task UpdateStorageObject(StorageObject obj)
 {
     await UpdateStorageObject(obj);
 }
        /// <inheritdoc/>
        public async Task UpdateStorageObject(StorageObject obj)
        {
            obj.AssertIsNotNull("container", "Cannot update a storage object with a null object.");

            var client = this.GetPocoClient();
            await client.UpdateStorageObject(obj);
        }
        public async Task ExceptionThrownWhenCreatingaStorageObjectHasInternalServerError()
        {
            var containerName = "TestContainer";
            var objectName = "TestObject";

            var objRequest = new StorageObject(objectName, containerName);
            var content = TestHelper.CreateStream("Some Content");

            var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
            this.StorageServiceRestClient.Responses.Enqueue(restResp);

            var client = new StorageServicePocoClient(GetValidContext(), this.ServiceLocator);
            await client.CreateStorageObject(objRequest, content);
        }
 public async Task<StorageObject> CopyStorageObject(StorageObject obj, string destinationContainerName, string destinationObjectName = null)
 {
     return await this.CopyStorageObjectDelegate(obj, destinationContainerName, destinationObjectName);
 }
 public async Task<StorageObject> CreateStorageObject(StorageObject obj, Stream content)
 {
     return await this.CreateStorageObjectDelegate(obj, content);
 }
        public async Task CanCopyStorageObjectWithFoldersAndCreatedResponse()
        {
            var containerName = "TestContainer";
            var objectName = "a/b/TestObject";
            var targetContainerName = "TargetTestContainer";

            var headers = new HttpHeadersAbstraction()
            {
                {"Content-Length", "0"},
                {"Content-Type", "application/octet-stream"},
                {"X-Copied-From-Last-Modified","Wed, 12 Mar 2014 22:42:23 GMT"},
                {"X-Copied-From" , "TestContainer/a/b/TestObject"},
                {"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
                {"ETag", "d41d8cd98f00b204e9800998ecf8427e"}
            };

            var objRequest = new StorageObject(objectName, containerName);
    
            var restResp = new HttpResponseAbstraction(new MemoryStream(), headers, HttpStatusCode.Created);
            this.StorageServiceRestClient.Responses.Enqueue(restResp);

            var client = new StorageServicePocoClient(GetValidContext(), this.ServiceLocator);
            var result = await client.CopyStorageObject(objRequest, targetContainerName);

            Assert.IsNotNull(result);
            Assert.AreEqual(objectName, result.FullName);
            Assert.AreEqual(containerName, result.ContainerName);
            Assert.AreEqual(0, result.Length);
            Assert.AreEqual("application/octet-stream", result.ContentType);
            Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", result.ETag);
            Assert.AreEqual(DateTime.Parse("Wed, 12 Mar 2014 23:42:23 GMT"), result.LastModified);
        }
        public async Task ExceptionThrownWhenCopyingaStorageObjectTimesOut()
        {
            var containerName = "TestContainer";
            var objectName = "TestObject";
            var targetContainerName = "TargetTestContainer";

            var objRequest = new StorageObject(objectName, containerName);
       
            var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.RequestTimeout);
            this.StorageServiceRestClient.Responses.Enqueue(restResp);

            var client = new StorageServicePocoClient(GetValidContext(), this.ServiceLocator);
            await client.CopyStorageObject(objRequest, targetContainerName);
        }
        public async Task ExceptionThrownWhenUpdatingAStorageObjectWithInternalServerError()
        {
            var containerName = "TestContainer";
            var objectName = "TestObject";

            var objectReq = new StorageObject(containerName, objectName);

            var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
            this.StorageServiceRestClient.Responses.Enqueue(restResp);

            var client = new StorageServicePocoClient(GetValidContext(), this.ServiceLocator);
            await client.UpdateStorageObject(objectReq);
        }
        public void CanConvertMultipleStorageObjectToJson()
        {
            var obj = new StorageObject("a/b/c", "TestContainer", DateTime.UtcNow, "12345", 54321, string.Empty,
                new Dictionary<string, string>());

            var obj2 = new StorageObject("a/b/d", "TestContainer", DateTime.UtcNow, "00000", 11111, string.Empty,
                new Dictionary<string, string>());

            var converter = new StorageObjectPayloadConverter();
            var payload = converter.Convert(new List<StorageObject>() { obj, obj2 });

            var result = JArray.Parse(payload);
            Assert.AreEqual(2, result.Count);

            var item = result[0];
            Assert.AreEqual("TestContainer/a/b/c", item["path"]);
            Assert.AreEqual(54321, item["size_bytes"]);
            Assert.AreEqual("12345", item["etag"]);

            var item2 = result[1];
            Assert.AreEqual("TestContainer/a/b/d", item2["path"]);
            Assert.AreEqual(11111, item2["size_bytes"]);
            Assert.AreEqual("00000", item2["etag"]);
        }
 public async Task UpdateStorageObject(StorageObject item)
 {
     await this.UpdateStorageObjectDelegate(item);
 }