Statistics
| Branch: | Revision:

root / trunk / Pithos.Network / CloudFilesClient.cs @ 3c43ec9b

History | View | Annotate | Download (26.5 kB)

1 d78cbf09 Panagiotis Kanavos
using System;
2 d78cbf09 Panagiotis Kanavos
using System.Collections.Generic;
3 d78cbf09 Panagiotis Kanavos
using System.ComponentModel.Composition;
4 5bcf6d70 Panagiotis Kanavos
using System.Diagnostics;
5 d78cbf09 Panagiotis Kanavos
using System.Diagnostics.Contracts;
6 d78cbf09 Panagiotis Kanavos
using System.IO;
7 d78cbf09 Panagiotis Kanavos
using System.Linq;
8 d78cbf09 Panagiotis Kanavos
using System.Net;
9 d78cbf09 Panagiotis Kanavos
using System.Security.Cryptography;
10 d78cbf09 Panagiotis Kanavos
using System.Text;
11 b5061ac8 Panagiotis Kanavos
using System.Threading.Tasks;
12 d78cbf09 Panagiotis Kanavos
using Hammock;
13 d78cbf09 Panagiotis Kanavos
using Hammock.Caching;
14 d78cbf09 Panagiotis Kanavos
using Hammock.Retries;
15 d78cbf09 Panagiotis Kanavos
using Hammock.Serialization;
16 5bcf6d70 Panagiotis Kanavos
using Hammock.Tasks;
17 d78cbf09 Panagiotis Kanavos
using Hammock.Web;
18 d78cbf09 Panagiotis Kanavos
using Newtonsoft.Json;
19 d78cbf09 Panagiotis Kanavos
using Pithos.Interfaces;
20 d78cbf09 Panagiotis Kanavos
21 d78cbf09 Panagiotis Kanavos
namespace Pithos.Network
22 d78cbf09 Panagiotis Kanavos
{
23 d78cbf09 Panagiotis Kanavos
    [Export(typeof(ICloudClient))]
24 d78cbf09 Panagiotis Kanavos
    public class CloudFilesClient:ICloudClient
25 d78cbf09 Panagiotis Kanavos
    {
26 1482f9ad Panagiotis Kanavos
        string _rackSpaceAuthUrl = "https://auth.api.rackspacecloud.com";
27 3c43ec9b Panagiotis Kanavos
        private string _pithosAuthUrl = "https://pithos.dev.grnet.gr";
28 2c053915 Panagiotis Kanavos
29 d78cbf09 Panagiotis Kanavos
        private RestClient _client;
30 5bcf6d70 Panagiotis Kanavos
        private readonly TimeSpan _shortTimeout = TimeSpan.FromSeconds(10);
31 d78cbf09 Panagiotis Kanavos
        private readonly int _retries = 5;
32 b5061ac8 Panagiotis Kanavos
        private RetryPolicy _retryPolicy;
33 d78cbf09 Panagiotis Kanavos
        public string ApiKey { get; set; }
34 d78cbf09 Panagiotis Kanavos
        public string UserName { get; set; }
35 b6c72f62 Panagiotis Kanavos
        public Uri StorageUrl { get; set; }
36 d78cbf09 Panagiotis Kanavos
        public string Token { get; set; }
37 5bcf6d70 Panagiotis Kanavos
        public Uri Proxy { get; set; }
38 b5061ac8 Panagiotis Kanavos
39 b5061ac8 Panagiotis Kanavos
        public double DownloadPercentLimit { get; set; }
40 b5061ac8 Panagiotis Kanavos
        public double UploadPercentLimit { get; set; }
41 2c053915 Panagiotis Kanavos
        
42 2c053915 Panagiotis Kanavos
        public string AuthUrl
43 2c053915 Panagiotis Kanavos
        {
44 2c053915 Panagiotis Kanavos
            get { return UsePithos ? _pithosAuthUrl : _rackSpaceAuthUrl; }
45 2c053915 Panagiotis Kanavos
        }
46 1482f9ad Panagiotis Kanavos
 
47 1482f9ad Panagiotis Kanavos
        public string VersionPath
48 1482f9ad Panagiotis Kanavos
        {
49 1482f9ad Panagiotis Kanavos
            get { return UsePithos ? "v1" : "v1.0"; }
50 1482f9ad Panagiotis Kanavos
        }
51 2c053915 Panagiotis Kanavos
52 2c053915 Panagiotis Kanavos
        public bool UsePithos { get; set; }
53 d78cbf09 Panagiotis Kanavos
54 3c43ec9b Panagiotis Kanavos
        private bool _authenticated = false;
55 3c43ec9b Panagiotis Kanavos
56 d78cbf09 Panagiotis Kanavos
        public void Authenticate(string userName,string apiKey)
57 d78cbf09 Panagiotis Kanavos
        {
58 0eea575a Panagiotis Kanavos
            Trace.TraceInformation("[AUTHENTICATE] Start for {0}", userName);
59 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(userName))
60 0eea575a Panagiotis Kanavos
                throw new ArgumentNullException("userName", "The userName property can't be empty");
61 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(apiKey))
62 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("apiKey", "The apiKey property can't be empty");
63 d78cbf09 Panagiotis Kanavos
64 3c43ec9b Panagiotis Kanavos
            if (_authenticated)
65 3c43ec9b Panagiotis Kanavos
                return;
66 3c43ec9b Panagiotis Kanavos
67 d78cbf09 Panagiotis Kanavos
            UserName = userName;
68 d78cbf09 Panagiotis Kanavos
            ApiKey = apiKey;
69 d78cbf09 Panagiotis Kanavos
            
70 0eea575a Panagiotis Kanavos
            var proxy = Proxy != null ? Proxy.ToString() : null;
71 0eea575a Panagiotis Kanavos
            if (UsePithos)
72 0eea575a Panagiotis Kanavos
            {
73 3c43ec9b Panagiotis Kanavos
                Token = ApiKey;
74 0eea575a Panagiotis Kanavos
                string storageUrl = String.Format("{0}/{1}/{2}", AuthUrl, VersionPath, UserName);
75 0eea575a Panagiotis Kanavos
                StorageUrl = new Uri(storageUrl);
76 0eea575a Panagiotis Kanavos
            }
77 0eea575a Panagiotis Kanavos
            else
78 0eea575a Panagiotis Kanavos
            {
79 d78cbf09 Panagiotis Kanavos
80 0eea575a Panagiotis Kanavos
                string authUrl = String.Format("{0}/{1}", AuthUrl, VersionPath);
81 0eea575a Panagiotis Kanavos
                var authClient = new RestClient {Path = authUrl, Proxy = proxy};                
82 d78cbf09 Panagiotis Kanavos
83 0eea575a Panagiotis Kanavos
                authClient.AddHeader("X-Auth-User", UserName);
84 0eea575a Panagiotis Kanavos
                authClient.AddHeader("X-Auth-Key", ApiKey);
85 0eea575a Panagiotis Kanavos
86 0eea575a Panagiotis Kanavos
                var response = authClient.Request();
87 0eea575a Panagiotis Kanavos
88 0eea575a Panagiotis Kanavos
                ThrowIfNotStatusOK(response, "Authentication failed");
89 0eea575a Panagiotis Kanavos
90 0eea575a Panagiotis Kanavos
                var keys = response.Headers.AllKeys.AsQueryable();
91 0eea575a Panagiotis Kanavos
92 0eea575a Panagiotis Kanavos
                string storageUrl = GetHeaderValue("X-Storage-Url", response, keys);
93 0eea575a Panagiotis Kanavos
                if (String.IsNullOrWhiteSpace(storageUrl))
94 0eea575a Panagiotis Kanavos
                    throw new InvalidOperationException("Failed to obtain storage url");
95 0eea575a Panagiotis Kanavos
                StorageUrl = new Uri(storageUrl);
96 d78cbf09 Panagiotis Kanavos
97 b6c72f62 Panagiotis Kanavos
                var token = GetHeaderValue("X-Auth-Token", response, keys);
98 b6c72f62 Panagiotis Kanavos
                if (String.IsNullOrWhiteSpace(token))
99 b6c72f62 Panagiotis Kanavos
                    throw new InvalidOperationException("Failed to obtain token url");
100 b6c72f62 Panagiotis Kanavos
                Token = token;
101 b6c72f62 Panagiotis Kanavos
            }
102 d78cbf09 Panagiotis Kanavos
103 b5061ac8 Panagiotis Kanavos
            _retryPolicy = new RetryPolicy { RetryCount = _retries };
104 b5061ac8 Panagiotis Kanavos
            _retryPolicy.RetryConditions.Add(new TimeoutRetryCondition());
105 1482f9ad Panagiotis Kanavos
106 b5061ac8 Panagiotis Kanavos
            _client = new RestClient { Authority = StorageUrl.AbsoluteUri, Path = UserName, Proxy = proxy };
107 b5061ac8 Panagiotis Kanavos
            _client.FileProgress += OnFileProgress;
108 1482f9ad Panagiotis Kanavos
            
109 d78cbf09 Panagiotis Kanavos
            _client.AddHeader("X-Auth-Token", Token);
110 0eea575a Panagiotis Kanavos
            /*if (UsePithos)
111 2c053915 Panagiotis Kanavos
            {
112 2c053915 Panagiotis Kanavos
                _client.AddHeader("X-Auth-User", UserName);
113 1482f9ad Panagiotis Kanavos
                _client.AddHeader("X-Auth-Key",ApiKey);                
114 0eea575a Panagiotis Kanavos
            }*/
115 2c053915 Panagiotis Kanavos
116 b5061ac8 Panagiotis Kanavos
            Trace.TraceInformation("[AUTHENTICATE] End for {0}", userName);
117 b5061ac8 Panagiotis Kanavos
        }
118 d78cbf09 Panagiotis Kanavos
119 b5061ac8 Panagiotis Kanavos
        private void OnFileProgress(object sender, FileProgressEventArgs e)
120 b5061ac8 Panagiotis Kanavos
        {
121 b5061ac8 Panagiotis Kanavos
            Trace.TraceInformation("[PROGRESS] {0} {1:p} {2} of {3}",e.FileName,(double)e.BytesWritten/e.TotalBytes, e.BytesWritten,e.TotalBytes);            
122 d78cbf09 Panagiotis Kanavos
        }
123 d78cbf09 Panagiotis Kanavos
124 d78cbf09 Panagiotis Kanavos
        public IList<ContainerInfo> ListContainers()
125 d78cbf09 Panagiotis Kanavos
        {                        
126 1482f9ad Panagiotis Kanavos
            //Workaround for Hammock quirk: Hammock always
127 1482f9ad Panagiotis Kanavos
            //appends a / unless a Path is specified.
128 1482f9ad Panagiotis Kanavos
            
129 1482f9ad Panagiotis Kanavos
            //Create a request with a complete path
130 b5061ac8 Panagiotis Kanavos
            var request = new RestRequest { Path = StorageUrl.ToString(), RetryPolicy = _retryPolicy,Timeout = _shortTimeout };
131 d78cbf09 Panagiotis Kanavos
            request.AddParameter("format","json");
132 1482f9ad Panagiotis Kanavos
            //Create a client clone
133 5bcf6d70 Panagiotis Kanavos
            var client = new RestClient{Proxy=Proxy.ToString()};
134 1482f9ad Panagiotis Kanavos
            foreach (var header in _client.GetAllHeaders())
135 1482f9ad Panagiotis Kanavos
            {
136 1482f9ad Panagiotis Kanavos
                client.AddHeader(header.Name,header.Value);
137 1482f9ad Panagiotis Kanavos
            }            
138 1482f9ad Panagiotis Kanavos
139 1482f9ad Panagiotis Kanavos
            var response = client.Request(request);
140 d78cbf09 Panagiotis Kanavos
141 d78cbf09 Panagiotis Kanavos
            if (response.StatusCode == HttpStatusCode.NoContent)
142 d78cbf09 Panagiotis Kanavos
                return new List<ContainerInfo>();
143 d78cbf09 Panagiotis Kanavos
144 5bcf6d70 Panagiotis Kanavos
            ThrowIfNotStatusOK(response, "List Containers failed");
145 5bcf6d70 Panagiotis Kanavos
146 5bcf6d70 Panagiotis Kanavos
147 d78cbf09 Panagiotis Kanavos
            var infos=JsonConvert.DeserializeObject<IList<ContainerInfo>>(response.Content);
148 d78cbf09 Panagiotis Kanavos
            
149 d78cbf09 Panagiotis Kanavos
            return infos;
150 d78cbf09 Panagiotis Kanavos
        }
151 d78cbf09 Panagiotis Kanavos
152 d78cbf09 Panagiotis Kanavos
        public IList<ObjectInfo> ListObjects(string container)
153 d78cbf09 Panagiotis Kanavos
        {
154 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(container))
155 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("container", "The container property can't be empty");
156 d78cbf09 Panagiotis Kanavos
157 b5061ac8 Panagiotis Kanavos
            Trace.TraceInformation("[START] ListObjects");
158 b5061ac8 Panagiotis Kanavos
159 b5061ac8 Panagiotis Kanavos
            var request = new RestRequest { Path = container, RetryPolicy = _retryPolicy, Timeout = TimeSpan.FromMinutes(1) };
160 d78cbf09 Panagiotis Kanavos
            request.AddParameter("format", "json");
161 d78cbf09 Panagiotis Kanavos
            var response = _client.Request(request);
162 d78cbf09 Panagiotis Kanavos
            
163 5bcf6d70 Panagiotis Kanavos
            var infos = InfosFromContent(response);
164 d78cbf09 Panagiotis Kanavos
165 b5061ac8 Panagiotis Kanavos
            Trace.TraceInformation("[END] ListObjects");
166 d78cbf09 Panagiotis Kanavos
            return infos;
167 d78cbf09 Panagiotis Kanavos
        }
168 d78cbf09 Panagiotis Kanavos
169 637bc368 Panagiotis Kanavos
170 5bcf6d70 Panagiotis Kanavos
171 637bc368 Panagiotis Kanavos
        public IList<ObjectInfo> ListObjects(string container,string folder)
172 637bc368 Panagiotis Kanavos
        {
173 637bc368 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(container))
174 637bc368 Panagiotis Kanavos
                throw new ArgumentNullException("container", "The container property can't be empty");
175 637bc368 Panagiotis Kanavos
176 b5061ac8 Panagiotis Kanavos
            Trace.TraceInformation("[START] ListObjects");
177 b5061ac8 Panagiotis Kanavos
178 b5061ac8 Panagiotis Kanavos
            var request = new RestRequest { Path = container,RetryPolicy = _retryPolicy, Timeout = TimeSpan.FromMinutes(1) };
179 637bc368 Panagiotis Kanavos
            request.AddParameter("format", "json");
180 637bc368 Panagiotis Kanavos
            request.AddParameter("path", folder);
181 637bc368 Panagiotis Kanavos
            var response = _client.Request(request);
182 5bcf6d70 Panagiotis Kanavos
            
183 5bcf6d70 Panagiotis Kanavos
            var infos = InfosFromContent(response);
184 5bcf6d70 Panagiotis Kanavos
185 b5061ac8 Panagiotis Kanavos
            Trace.TraceInformation("[END] ListObjects");
186 5bcf6d70 Panagiotis Kanavos
            return infos;
187 5bcf6d70 Panagiotis Kanavos
        }
188 5bcf6d70 Panagiotis Kanavos
189 5bcf6d70 Panagiotis Kanavos
        private static IList<ObjectInfo> InfosFromContent(RestResponse response)
190 5bcf6d70 Panagiotis Kanavos
        {
191 637bc368 Panagiotis Kanavos
            if (response.TimedOut)
192 637bc368 Panagiotis Kanavos
                return new List<ObjectInfo>();
193 637bc368 Panagiotis Kanavos
194 5bcf6d70 Panagiotis Kanavos
            if (response.StatusCode == 0)
195 5bcf6d70 Panagiotis Kanavos
                return new List<ObjectInfo>();
196 637bc368 Panagiotis Kanavos
197 637bc368 Panagiotis Kanavos
            if (response.StatusCode == HttpStatusCode.NoContent)
198 637bc368 Panagiotis Kanavos
                return new List<ObjectInfo>();
199 637bc368 Panagiotis Kanavos
200 637bc368 Panagiotis Kanavos
201 5bcf6d70 Panagiotis Kanavos
            var statusCode = (int)response.StatusCode;
202 5bcf6d70 Panagiotis Kanavos
            if (statusCode < 200 || statusCode >= 300)
203 5bcf6d70 Panagiotis Kanavos
            {
204 0eea575a Panagiotis Kanavos
                Trace.TraceWarning("ListObjects failed with code {0} - {1}", response.StatusCode, response.StatusDescription);
205 5bcf6d70 Panagiotis Kanavos
                return new List<ObjectInfo>();
206 5bcf6d70 Panagiotis Kanavos
            }
207 5bcf6d70 Panagiotis Kanavos
208 5bcf6d70 Panagiotis Kanavos
            var infos = JsonConvert.DeserializeObject<IList<ObjectInfo>>(response.Content);
209 637bc368 Panagiotis Kanavos
            return infos;
210 637bc368 Panagiotis Kanavos
        }
211 637bc368 Panagiotis Kanavos
212 d78cbf09 Panagiotis Kanavos
        public bool ContainerExists(string container)
213 d78cbf09 Panagiotis Kanavos
        {
214 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(container))
215 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("container", "The container property can't be empty");
216 d78cbf09 Panagiotis Kanavos
217 b5061ac8 Panagiotis Kanavos
            var request = new RestRequest { Path = container, Method = WebMethod.Head, RetryPolicy = _retryPolicy,Timeout = _shortTimeout };
218 d78cbf09 Panagiotis Kanavos
            var response = _client.Request(request);
219 d78cbf09 Panagiotis Kanavos
220 d78cbf09 Panagiotis Kanavos
            switch(response.StatusCode)
221 d78cbf09 Panagiotis Kanavos
            {
222 3c43ec9b Panagiotis Kanavos
                case HttpStatusCode.OK:
223 d78cbf09 Panagiotis Kanavos
                case HttpStatusCode.NoContent:
224 d78cbf09 Panagiotis Kanavos
                    return true;
225 d78cbf09 Panagiotis Kanavos
                case HttpStatusCode.NotFound:
226 3c43ec9b Panagiotis Kanavos
                    return false;          
227 d78cbf09 Panagiotis Kanavos
                default:
228 3c43ec9b Panagiotis Kanavos
                    throw CreateWebException("ContainerExists",response.StatusCode);
229 d78cbf09 Panagiotis Kanavos
            }
230 d78cbf09 Panagiotis Kanavos
        }
231 d78cbf09 Panagiotis Kanavos
232 d78cbf09 Panagiotis Kanavos
        public bool ObjectExists(string container,string objectName)
233 d78cbf09 Panagiotis Kanavos
        {
234 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(container))
235 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("container", "The container property can't be empty");
236 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(objectName))
237 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("objectName", "The objectName property can't be empty");
238 d78cbf09 Panagiotis Kanavos
239 5bcf6d70 Panagiotis Kanavos
240 b5061ac8 Panagiotis Kanavos
            var request = new RestRequest { Path = container + "/" + objectName, Method = WebMethod.Head,RetryPolicy = _retryPolicy, Timeout = _shortTimeout };
241 d78cbf09 Panagiotis Kanavos
            var response = _client.Request(request);
242 d78cbf09 Panagiotis Kanavos
243 d78cbf09 Panagiotis Kanavos
            switch (response.StatusCode)
244 d78cbf09 Panagiotis Kanavos
            {
245 d78cbf09 Panagiotis Kanavos
                case HttpStatusCode.OK:
246 d78cbf09 Panagiotis Kanavos
                case HttpStatusCode.NoContent:
247 d78cbf09 Panagiotis Kanavos
                    return true;
248 d78cbf09 Panagiotis Kanavos
                case HttpStatusCode.NotFound:
249 d78cbf09 Panagiotis Kanavos
                    return false;
250 d78cbf09 Panagiotis Kanavos
                default:
251 3c43ec9b Panagiotis Kanavos
                    throw CreateWebException("ObjectExists",response.StatusCode);
252 d78cbf09 Panagiotis Kanavos
            }
253 d78cbf09 Panagiotis Kanavos
            
254 d78cbf09 Panagiotis Kanavos
        }
255 d78cbf09 Panagiotis Kanavos
256 d78cbf09 Panagiotis Kanavos
        public ObjectInfo GetObjectInfo(string container, string objectName)
257 d78cbf09 Panagiotis Kanavos
        {
258 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(container))
259 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("container", "The container property can't be empty");
260 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(objectName))
261 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("objectName", "The objectName property can't be empty");
262 d78cbf09 Panagiotis Kanavos
263 d78cbf09 Panagiotis Kanavos
264 b5061ac8 Panagiotis Kanavos
            var request = new RestRequest { Path = container + "/" + objectName, Method = WebMethod.Head, RetryPolicy = _retryPolicy,Timeout = _shortTimeout };
265 d78cbf09 Panagiotis Kanavos
            var response = _client.Request(request);
266 d78cbf09 Panagiotis Kanavos
267 d78cbf09 Panagiotis Kanavos
            if (response.TimedOut)
268 d78cbf09 Panagiotis Kanavos
                return ObjectInfo.Empty;
269 d78cbf09 Panagiotis Kanavos
270 d78cbf09 Panagiotis Kanavos
            switch (response.StatusCode)
271 d78cbf09 Panagiotis Kanavos
            {
272 d78cbf09 Panagiotis Kanavos
                case HttpStatusCode.OK:
273 d78cbf09 Panagiotis Kanavos
                case HttpStatusCode.NoContent:
274 d78cbf09 Panagiotis Kanavos
                    var keys = response.Headers.AllKeys.AsQueryable();
275 0050438e Panagiotis Kanavos
                    var tags=(from key in keys
276 0050438e Panagiotis Kanavos
                             where key.StartsWith("X-Object-Meta-")
277 0050438e Panagiotis Kanavos
                             let name=key.Substring(14)
278 0050438e Panagiotis Kanavos
                             select new {Name=name,Value=response.Headers[name]})
279 0050438e Panagiotis Kanavos
                             .ToDictionary(t=>t.Name,t=>t.Value);
280 3c43ec9b Panagiotis Kanavos
                    var extensions = (from key in keys
281 3c43ec9b Panagiotis Kanavos
                                      where key.StartsWith("X-Object-") && !key.StartsWith("X-Object-Meta-")
282 3c43ec9b Panagiotis Kanavos
                                      let name = key.Substring(9)
283 3c43ec9b Panagiotis Kanavos
                                      select new { Name = name, Value = response.Headers[name] })
284 3c43ec9b Panagiotis Kanavos
                             .ToDictionary(t => t.Name, t => t.Value);
285 d78cbf09 Panagiotis Kanavos
                    return new ObjectInfo
286 d78cbf09 Panagiotis Kanavos
                               {
287 b5061ac8 Panagiotis Kanavos
                                   Name = objectName,
288 d78cbf09 Panagiotis Kanavos
                                   Bytes = long.Parse(GetHeaderValue("Content-Length", response, keys)),
289 d78cbf09 Panagiotis Kanavos
                                   Hash = GetHeaderValue("ETag", response, keys),
290 0050438e Panagiotis Kanavos
                                   Content_Type = GetHeaderValue("Content-Type", response, keys),
291 3c43ec9b Panagiotis Kanavos
                                   Tags=tags,
292 3c43ec9b Panagiotis Kanavos
                                   Extensions=extensions
293 d78cbf09 Panagiotis Kanavos
                               };
294 d78cbf09 Panagiotis Kanavos
                case HttpStatusCode.NotFound:
295 d78cbf09 Panagiotis Kanavos
                    return ObjectInfo.Empty;
296 d78cbf09 Panagiotis Kanavos
                default:
297 b5061ac8 Panagiotis Kanavos
                    if (request.RetryState.RepeatCount > 0)
298 b5061ac8 Panagiotis Kanavos
                    {
299 b5061ac8 Panagiotis Kanavos
                        Trace.TraceWarning("[RETRY FAIL] GetObjectInfo for {0} failed after {1} retries",
300 b5061ac8 Panagiotis Kanavos
                                                      objectName, request.RetryState.RepeatCount);
301 b5061ac8 Panagiotis Kanavos
                        return ObjectInfo.Empty;
302 b5061ac8 Panagiotis Kanavos
                    }
303 b5061ac8 Panagiotis Kanavos
                    if (response.InnerException != null)
304 b5061ac8 Panagiotis Kanavos
                        throw new WebException(String.Format("[FAIL] GetObjectInfo for {0} failed with unexpected status code {1}", objectName, response.StatusCode), response.InnerException);
305 b5061ac8 Panagiotis Kanavos
                    throw new WebException(String.Format("[FAIL] GetObjectInfo for {0} failed with unexpected status code {1}", objectName, response.StatusCode));
306 d78cbf09 Panagiotis Kanavos
            }
307 d78cbf09 Panagiotis Kanavos
        }
308 d78cbf09 Panagiotis Kanavos
309 10523ad9 Panagiotis Kanavos
        public void CreateFolder(string container, string folder)
310 10523ad9 Panagiotis Kanavos
        {
311 10523ad9 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(container))
312 10523ad9 Panagiotis Kanavos
                throw new ArgumentNullException("container", "The container property can't be empty");
313 10523ad9 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(folder))
314 10523ad9 Panagiotis Kanavos
                throw new ArgumentNullException("folder", "The folder property can't be empty");
315 10523ad9 Panagiotis Kanavos
316 10523ad9 Panagiotis Kanavos
            var folderUrl=String.Format("{0}/{1}",container,folder);
317 b5061ac8 Panagiotis Kanavos
            var request = new RestRequest { Path = folderUrl, Method = WebMethod.Put, RetryPolicy = _retryPolicy,Timeout = _shortTimeout };
318 10523ad9 Panagiotis Kanavos
            request.AddHeader("Content-Type", @"application/directory");
319 10523ad9 Panagiotis Kanavos
            request.AddHeader("Content-Length", "0");
320 10523ad9 Panagiotis Kanavos
321 10523ad9 Panagiotis Kanavos
            var response = _client.Request(request);
322 10523ad9 Panagiotis Kanavos
323 10523ad9 Panagiotis Kanavos
            if (response.StatusCode != HttpStatusCode.Created && response.StatusCode != HttpStatusCode.Accepted)
324 3c43ec9b Panagiotis Kanavos
                throw CreateWebException("CreateFolder", response.StatusCode);
325 10523ad9 Panagiotis Kanavos
326 10523ad9 Panagiotis Kanavos
        }
327 10523ad9 Panagiotis Kanavos
328 d78cbf09 Panagiotis Kanavos
        public ContainerInfo GetContainerInfo(string container)
329 d78cbf09 Panagiotis Kanavos
        {
330 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(container))
331 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("container", "The container property can't be empty");
332 d78cbf09 Panagiotis Kanavos
333 b5061ac8 Panagiotis Kanavos
            var request = new RestRequest { Path = container, Method = WebMethod.Head, RetryPolicy = _retryPolicy,Timeout = _shortTimeout };
334 d78cbf09 Panagiotis Kanavos
            var response = _client.Request(request);
335 d78cbf09 Panagiotis Kanavos
336 d78cbf09 Panagiotis Kanavos
            switch(response.StatusCode)
337 d78cbf09 Panagiotis Kanavos
            {
338 d78cbf09 Panagiotis Kanavos
                case HttpStatusCode.NoContent:
339 d78cbf09 Panagiotis Kanavos
                    var keys = response.Headers.AllKeys.AsQueryable();
340 d78cbf09 Panagiotis Kanavos
                    var containerInfo = new ContainerInfo
341 d78cbf09 Panagiotis Kanavos
                                            {
342 d78cbf09 Panagiotis Kanavos
                                                Name = container,
343 d78cbf09 Panagiotis Kanavos
                                                Count =long.Parse(GetHeaderValue("X-Container-Object-Count", response, keys)),
344 d78cbf09 Panagiotis Kanavos
                                                Bytes =long.Parse(GetHeaderValue("X-Container-Bytes-Used", response, keys))
345 d78cbf09 Panagiotis Kanavos
                                            };
346 d78cbf09 Panagiotis Kanavos
                    return containerInfo;
347 d78cbf09 Panagiotis Kanavos
                case HttpStatusCode.NotFound:
348 d78cbf09 Panagiotis Kanavos
                    return ContainerInfo.Empty;                    
349 d78cbf09 Panagiotis Kanavos
                default:
350 3c43ec9b Panagiotis Kanavos
                    throw CreateWebException("GetContainerInfo", response.StatusCode);
351 d78cbf09 Panagiotis Kanavos
            }
352 d78cbf09 Panagiotis Kanavos
        }
353 d78cbf09 Panagiotis Kanavos
354 d78cbf09 Panagiotis Kanavos
        public void CreateContainer(string container)
355 d78cbf09 Panagiotis Kanavos
        {
356 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(container))
357 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("container", "The container property can't be empty");
358 d78cbf09 Panagiotis Kanavos
359 b5061ac8 Panagiotis Kanavos
            var request = new RestRequest { Path = container, Method = WebMethod.Put, RetryPolicy = _retryPolicy,Timeout = _shortTimeout };
360 d78cbf09 Panagiotis Kanavos
            
361 b6c72f62 Panagiotis Kanavos
            var response = _client.Request(request);
362 3c43ec9b Panagiotis Kanavos
363 3c43ec9b Panagiotis Kanavos
            var expectedCodes = new[]{HttpStatusCode.Created ,HttpStatusCode.Accepted , HttpStatusCode.OK};
364 3c43ec9b Panagiotis Kanavos
            if (!expectedCodes.Contains(response.StatusCode))
365 3c43ec9b Panagiotis Kanavos
                throw CreateWebException("CreateContainer", response.StatusCode);
366 d78cbf09 Panagiotis Kanavos
        }
367 d78cbf09 Panagiotis Kanavos
368 2c053915 Panagiotis Kanavos
        public void DeleteContainer(string container)
369 2c053915 Panagiotis Kanavos
        {
370 2c053915 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(container))
371 2c053915 Panagiotis Kanavos
                throw new ArgumentNullException("container", "The container property can't be empty");
372 2c053915 Panagiotis Kanavos
373 b5061ac8 Panagiotis Kanavos
            var request = new RestRequest { Path = container, Method = WebMethod.Delete, RetryPolicy = _retryPolicy,Timeout = _shortTimeout };
374 2c053915 Panagiotis Kanavos
            var response = _client.Request(request);
375 2c053915 Panagiotis Kanavos
376 3c43ec9b Panagiotis Kanavos
            var expectedCodes = new[] { HttpStatusCode.NotFound, HttpStatusCode.NoContent};
377 3c43ec9b Panagiotis Kanavos
            if (!expectedCodes.Contains(response.StatusCode))
378 3c43ec9b Panagiotis Kanavos
                throw CreateWebException("DeleteContainer", response.StatusCode);
379 2c053915 Panagiotis Kanavos
380 2c053915 Panagiotis Kanavos
        }
381 2c053915 Panagiotis Kanavos
382 5bcf6d70 Panagiotis Kanavos
        /// <summary>
383 5bcf6d70 Panagiotis Kanavos
        /// 
384 5bcf6d70 Panagiotis Kanavos
        /// </summary>
385 5bcf6d70 Panagiotis Kanavos
        /// <param name="container"></param>
386 5bcf6d70 Panagiotis Kanavos
        /// <param name="objectName"></param>
387 283809f3 Panagiotis Kanavos
        /// <param name="fileName"></param>
388 5bcf6d70 Panagiotis Kanavos
        /// <returns></returns>
389 5bcf6d70 Panagiotis Kanavos
        /// <remarks>>This method should have no timeout or a very long one</remarks>
390 283809f3 Panagiotis Kanavos
        public Task GetObject(string container, string objectName, string fileName)
391 d78cbf09 Panagiotis Kanavos
        {
392 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(container))
393 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("container", "The container property can't be empty");
394 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(objectName))
395 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("objectName", "The objectName property can't be empty");
396 d78cbf09 Panagiotis Kanavos
397 283809f3 Panagiotis Kanavos
            var request = new RestRequest {Path = container + "/" + objectName, Method = WebMethod.Get};
398 283809f3 Panagiotis Kanavos
            /*
399 283809f3 Panagiotis Kanavos
                        if (DownloadPercentLimit > 0)
400 283809f3 Panagiotis Kanavos
                            request.TaskOptions = new TaskOptions<int> { RateLimitPercent = DownloadPercentLimit };
401 283809f3 Panagiotis Kanavos
            */
402 283809f3 Panagiotis Kanavos
            try
403 283809f3 Panagiotis Kanavos
            {
404 283809f3 Panagiotis Kanavos
                var url = String.Join("/", new[] {_client.Authority, container, objectName});
405 283809f3 Panagiotis Kanavos
                var uri = new Uri(url);
406 283809f3 Panagiotis Kanavos
407 283809f3 Panagiotis Kanavos
                var client = new WebClient();
408 283809f3 Panagiotis Kanavos
                if (!String.IsNullOrWhiteSpace(_client.Proxy))
409 283809f3 Panagiotis Kanavos
                    client.Proxy = new WebProxy(_client.Proxy);
410 283809f3 Panagiotis Kanavos
411 283809f3 Panagiotis Kanavos
                CopyHeaders(_client, client);
412 283809f3 Panagiotis Kanavos
413 283809f3 Panagiotis Kanavos
                Trace.TraceInformation("[GET] START {0}", objectName);
414 283809f3 Panagiotis Kanavos
                client.DownloadProgressChanged += (sender, args) => 
415 283809f3 Panagiotis Kanavos
                    Trace.TraceInformation("[GET PROGRESS] {0} {1}% {2} of {3}",
416 283809f3 Panagiotis Kanavos
                                    fileName, args.ProgressPercentage,
417 283809f3 Panagiotis Kanavos
                                    args.BytesReceived,
418 283809f3 Panagiotis Kanavos
                                    args.TotalBytesToReceive);
419 283809f3 Panagiotis Kanavos
                
420 283809f3 Panagiotis Kanavos
                return client.DownloadFileTask(uri, fileName)
421 283809f3 Panagiotis Kanavos
                    .ContinueWith(download =>
422 283809f3 Panagiotis Kanavos
                                      {
423 283809f3 Panagiotis Kanavos
                                          client.Dispose();
424 283809f3 Panagiotis Kanavos
425 283809f3 Panagiotis Kanavos
                                          if (download.IsFaulted)
426 283809f3 Panagiotis Kanavos
                                          {
427 283809f3 Panagiotis Kanavos
                                              Trace.TraceError("[GET] FAIL for {0} with \r{1}", objectName,
428 283809f3 Panagiotis Kanavos
                                                               download.Exception);
429 283809f3 Panagiotis Kanavos
                                          }
430 283809f3 Panagiotis Kanavos
                                          else
431 283809f3 Panagiotis Kanavos
                                          {
432 283809f3 Panagiotis Kanavos
                                              Trace.TraceInformation("[GET] END {0}", objectName);                                             
433 283809f3 Panagiotis Kanavos
                                          }
434 283809f3 Panagiotis Kanavos
                                      });
435 283809f3 Panagiotis Kanavos
            }
436 283809f3 Panagiotis Kanavos
            catch (Exception exc)
437 d78cbf09 Panagiotis Kanavos
            {
438 283809f3 Panagiotis Kanavos
                Trace.TraceError("[GET] END {0} with {1}", objectName, exc);
439 283809f3 Panagiotis Kanavos
                throw;
440 d78cbf09 Panagiotis Kanavos
            }
441 283809f3 Panagiotis Kanavos
442 283809f3 Panagiotis Kanavos
443 283809f3 Panagiotis Kanavos
444 d78cbf09 Panagiotis Kanavos
        }
445 d78cbf09 Panagiotis Kanavos
446 5bcf6d70 Panagiotis Kanavos
        /// <summary>
447 5bcf6d70 Panagiotis Kanavos
        /// 
448 5bcf6d70 Panagiotis Kanavos
        /// </summary>
449 5bcf6d70 Panagiotis Kanavos
        /// <param name="container"></param>
450 5bcf6d70 Panagiotis Kanavos
        /// <param name="objectName"></param>
451 5bcf6d70 Panagiotis Kanavos
        /// <param name="fileName"></param>
452 b5061ac8 Panagiotis Kanavos
        /// <param name="hash">Optional hash value for the file. If no hash is provided, the method calculates a new hash</param>
453 5bcf6d70 Panagiotis Kanavos
        /// <remarks>>This method should have no timeout or a very long one</remarks>
454 b5061ac8 Panagiotis Kanavos
        public Task PutObject(string container, string objectName, string fileName, string hash = null)
455 d78cbf09 Panagiotis Kanavos
        {
456 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(container))
457 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("container", "The container property can't be empty");
458 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(objectName))
459 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("objectName", "The objectName property can't be empty");
460 b6c72f62 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(fileName))
461 b6c72f62 Panagiotis Kanavos
                throw new ArgumentNullException("fileName", "The fileName property can't be empty");
462 637bc368 Panagiotis Kanavos
            if (!File.Exists(fileName))
463 637bc368 Panagiotis Kanavos
                throw new FileNotFoundException("The file does not exist",fileName);
464 d78cbf09 Panagiotis Kanavos
465 b6c72f62 Panagiotis Kanavos
            
466 b5061ac8 Panagiotis Kanavos
            try
467 b5061ac8 Panagiotis Kanavos
            {
468 0eea575a Panagiotis Kanavos
                var url = String.Join("/",new[]{_client.Authority,container,objectName});
469 0eea575a Panagiotis Kanavos
                var uri = new Uri(url);
470 0eea575a Panagiotis Kanavos
471 0eea575a Panagiotis Kanavos
                var client = new WebClient();                
472 0eea575a Panagiotis Kanavos
                string etag = hash ?? CalculateHash(fileName);
473 0eea575a Panagiotis Kanavos
474 0eea575a Panagiotis Kanavos
                client.Headers.Add("Content-Type", "application/octet-stream");
475 0eea575a Panagiotis Kanavos
                client.Headers.Add("ETag", etag);
476 0eea575a Panagiotis Kanavos
477 0eea575a Panagiotis Kanavos
                if(!String.IsNullOrWhiteSpace(_client.Proxy))
478 0eea575a Panagiotis Kanavos
                    client.Proxy = new WebProxy(_client.Proxy);
479 0eea575a Panagiotis Kanavos
480 0eea575a Panagiotis Kanavos
                CopyHeaders(_client, client);
481 0eea575a Panagiotis Kanavos
482 0eea575a Panagiotis Kanavos
                Trace.TraceInformation("[PUT] START {0}", objectName);
483 0eea575a Panagiotis Kanavos
                client.UploadProgressChanged += (sender, args) =>
484 0eea575a Panagiotis Kanavos
                {
485 283809f3 Panagiotis Kanavos
                    Trace.TraceInformation("[PUT PROGRESS] {0} {1}% {2} of {3}", fileName, args.ProgressPercentage, args.BytesSent, args.TotalBytesToSend);
486 0eea575a Panagiotis Kanavos
                };
487 0eea575a Panagiotis Kanavos
               
488 0eea575a Panagiotis Kanavos
                return client.UploadFileTask(uri, "PUT", fileName)
489 0eea575a Panagiotis Kanavos
                    .ContinueWith(upload=>
490 0eea575a Panagiotis Kanavos
                                      {
491 0eea575a Panagiotis Kanavos
                                          client.Dispose();
492 0eea575a Panagiotis Kanavos
493 0eea575a Panagiotis Kanavos
                                          if (upload.IsFaulted)
494 0eea575a Panagiotis Kanavos
                                          {                                              
495 0eea575a Panagiotis Kanavos
                                              Trace.TraceError("[PUT] FAIL for {0} with \r{1}",objectName,upload.Exception);
496 0eea575a Panagiotis Kanavos
                                          }
497 0eea575a Panagiotis Kanavos
                                          else
498 0eea575a Panagiotis Kanavos
                                            Trace.TraceInformation("[PUT] END {0}", objectName);
499 0eea575a Panagiotis Kanavos
                                      });
500 b5061ac8 Panagiotis Kanavos
            }
501 b5061ac8 Panagiotis Kanavos
            catch (Exception exc)
502 b5061ac8 Panagiotis Kanavos
            {
503 b5061ac8 Panagiotis Kanavos
                Trace.TraceError("[PUT] END {0} with {1}", objectName, exc);
504 b5061ac8 Panagiotis Kanavos
                throw;
505 b5061ac8 Panagiotis Kanavos
            }                
506 b5061ac8 Panagiotis Kanavos
507 0eea575a Panagiotis Kanavos
        }
508 0050438e Panagiotis Kanavos
       
509 0eea575a Panagiotis Kanavos
510 0eea575a Panagiotis Kanavos
        /// <summary>
511 0eea575a Panagiotis Kanavos
        /// Copies headers from a Hammock RestClient to a WebClient
512 0eea575a Panagiotis Kanavos
        /// </summary>
513 0eea575a Panagiotis Kanavos
        /// <param name="source">The RestClient from which the headers are copied</param>
514 0eea575a Panagiotis Kanavos
        /// <param name="target">The WebClient to which the headers are copied</param>
515 0eea575a Panagiotis Kanavos
        private static void CopyHeaders(RestClient source, WebClient target)
516 0eea575a Panagiotis Kanavos
        {
517 0eea575a Panagiotis Kanavos
            Contract.Requires(source!=null,"source can't be null");
518 0eea575a Panagiotis Kanavos
            Contract.Requires(target != null, "target can't be null");
519 0eea575a Panagiotis Kanavos
            if (source == null)
520 0eea575a Panagiotis Kanavos
                throw new ArgumentNullException("source", "source can't be null");
521 0eea575a Panagiotis Kanavos
            if (source == null)
522 0eea575a Panagiotis Kanavos
                throw new ArgumentNullException("target", "target can't be null");
523 0eea575a Panagiotis Kanavos
524 0eea575a Panagiotis Kanavos
            foreach (var header in source.GetAllHeaders())
525 0eea575a Panagiotis Kanavos
            {
526 0eea575a Panagiotis Kanavos
                target.Headers.Add(header.Name, header.Value);
527 0eea575a Panagiotis Kanavos
            }
528 d78cbf09 Panagiotis Kanavos
        }
529 d78cbf09 Panagiotis Kanavos
530 b6c72f62 Panagiotis Kanavos
        private static string CalculateHash(string fileName)
531 d78cbf09 Panagiotis Kanavos
        {
532 d78cbf09 Panagiotis Kanavos
            string hash;
533 d78cbf09 Panagiotis Kanavos
            using (var hasher = MD5.Create())
534 b6c72f62 Panagiotis Kanavos
            using(var stream=File.OpenRead(fileName))
535 d78cbf09 Panagiotis Kanavos
            {
536 d78cbf09 Panagiotis Kanavos
                var hashBuilder=new StringBuilder();
537 b6c72f62 Panagiotis Kanavos
                foreach (byte b in hasher.ComputeHash(stream))
538 d78cbf09 Panagiotis Kanavos
                    hashBuilder.Append(b.ToString("x2").ToLower());
539 d78cbf09 Panagiotis Kanavos
                hash = hashBuilder.ToString();                
540 d78cbf09 Panagiotis Kanavos
            }
541 d78cbf09 Panagiotis Kanavos
            return hash;
542 d78cbf09 Panagiotis Kanavos
        }
543 d78cbf09 Panagiotis Kanavos
544 d78cbf09 Panagiotis Kanavos
        public void DeleteObject(string container, string objectName)
545 d78cbf09 Panagiotis Kanavos
        {
546 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(container))
547 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("container", "The container property can't be empty");
548 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(objectName))
549 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("objectName", "The objectName property can't be empty");
550 d78cbf09 Panagiotis Kanavos
551 b5061ac8 Panagiotis Kanavos
            var request = new RestRequest { Path = container + "/" + objectName, Method = WebMethod.Delete, RetryPolicy = _retryPolicy,Timeout = _shortTimeout };
552 d78cbf09 Panagiotis Kanavos
            var response = _client.Request(request);
553 d78cbf09 Panagiotis Kanavos
554 3c43ec9b Panagiotis Kanavos
            var expectedCodes = new[] { HttpStatusCode.NotFound, HttpStatusCode.NoContent };
555 3c43ec9b Panagiotis Kanavos
            if (!expectedCodes.Contains(response.StatusCode))
556 3c43ec9b Panagiotis Kanavos
                throw CreateWebException("DeleteObject", response.StatusCode);
557 d78cbf09 Panagiotis Kanavos
   
558 d78cbf09 Panagiotis Kanavos
        }
559 d78cbf09 Panagiotis Kanavos
560 3c43ec9b Panagiotis Kanavos
        public void MoveObject(string sourceContainer, string oldObjectName, string targetContainer,string newObjectName)
561 d78cbf09 Panagiotis Kanavos
        {
562 3c43ec9b Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(sourceContainer))
563 3c43ec9b Panagiotis Kanavos
                throw new ArgumentNullException("sourceContainer", "The container property can't be empty");
564 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(oldObjectName))
565 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("oldObjectName", "The oldObjectName property can't be empty");
566 3c43ec9b Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(targetContainer))
567 3c43ec9b Panagiotis Kanavos
                throw new ArgumentNullException("targetContainer", "The container property can't be empty");
568 d78cbf09 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(newObjectName))
569 d78cbf09 Panagiotis Kanavos
                throw new ArgumentNullException("newObjectName", "The newObjectName property can't be empty");
570 d78cbf09 Panagiotis Kanavos
571 3c43ec9b Panagiotis Kanavos
            var targetUrl = targetContainer + "/" + newObjectName;
572 3c43ec9b Panagiotis Kanavos
            var sourceUrl = String.Format("/{0}/{1}", sourceContainer, oldObjectName);
573 3c43ec9b Panagiotis Kanavos
574 3c43ec9b Panagiotis Kanavos
            var request = new RestRequest { Path = targetUrl, Method = WebMethod.Put };
575 3c43ec9b Panagiotis Kanavos
            request.AddHeader("X-Copy-From",sourceUrl);
576 d78cbf09 Panagiotis Kanavos
            request.AddPostContent(new byte[]{});
577 d78cbf09 Panagiotis Kanavos
            var response = _client.Request(request);
578 d78cbf09 Panagiotis Kanavos
579 3c43ec9b Panagiotis Kanavos
580 3c43ec9b Panagiotis Kanavos
            var expectedCodes = new[] { HttpStatusCode.OK ,HttpStatusCode.NoContent ,HttpStatusCode.Created };
581 3c43ec9b Panagiotis Kanavos
            if (expectedCodes.Contains(response.StatusCode))
582 d78cbf09 Panagiotis Kanavos
            {
583 3c43ec9b Panagiotis Kanavos
                this.DeleteObject(sourceContainer,oldObjectName);
584 d78cbf09 Panagiotis Kanavos
            }                
585 d78cbf09 Panagiotis Kanavos
            else
586 3c43ec9b Panagiotis Kanavos
                throw CreateWebException("MoveObject", response.StatusCode);
587 d78cbf09 Panagiotis Kanavos
        }
588 d78cbf09 Panagiotis Kanavos
589 d78cbf09 Panagiotis Kanavos
        private string GetHeaderValue(string headerName, RestResponse response, IQueryable<string> keys)
590 d78cbf09 Panagiotis Kanavos
        {
591 d78cbf09 Panagiotis Kanavos
            if (keys.Any(key => key == headerName))
592 d78cbf09 Panagiotis Kanavos
                return response.Headers[headerName];
593 d78cbf09 Panagiotis Kanavos
            else
594 d78cbf09 Panagiotis Kanavos
                throw new WebException(String.Format("The {0}  header is missing",headerName));
595 d78cbf09 Panagiotis Kanavos
        }
596 d78cbf09 Panagiotis Kanavos
597 d78cbf09 Panagiotis Kanavos
        private static void ThrowIfNotStatusOK(RestResponse response, string message)
598 d78cbf09 Panagiotis Kanavos
        {
599 d78cbf09 Panagiotis Kanavos
            int status = (int)response.StatusCode;
600 d78cbf09 Panagiotis Kanavos
            if (status < 200 || status >= 300)
601 d78cbf09 Panagiotis Kanavos
                throw new WebException(String.Format("{0} with code {1}",message, status));
602 d78cbf09 Panagiotis Kanavos
        }
603 3c43ec9b Panagiotis Kanavos
604 3c43ec9b Panagiotis Kanavos
        private static WebException CreateWebException(string operation, HttpStatusCode statusCode)
605 3c43ec9b Panagiotis Kanavos
        {
606 3c43ec9b Panagiotis Kanavos
            return new WebException(String.Format("{0} failed with unexpected status code {1}", operation, statusCode));
607 3c43ec9b Panagiotis Kanavos
        }
608 3c43ec9b Panagiotis Kanavos
609 d78cbf09 Panagiotis Kanavos
    }
610 d78cbf09 Panagiotis Kanavos
}