Revision cfed7823 trunk/Pithos.Network/CloudFilesClient.cs

b/trunk/Pithos.Network/CloudFilesClient.cs
29 29
        //RestClient provides a REST-friendly interface over the standard WebClient.
30 30
        private RestClient _baseClient;
31 31
        
32
        //Some operations can specify a Timeout. The default value of all timeouts is 10 seconds
33
        private readonly TimeSpan _shortTimeout = TimeSpan.FromSeconds(10);
34
        
35
        //Some operations can be retried before failing. The default number of retries is 5
36
        private readonly int _retries = 5;        
37
        
38 32
        //During authentication the client provides a UserName 
39 33
        public string UserName { get; set; }
40 34
        
......
48 42
        //The client also receives a StorageUrl after authentication. All subsequent operations must
49 43
        //use this url
50 44
        public Uri StorageUrl { get; set; }
51
        
45

  
46
        protected Uri RootAddressUri { get; set; }
47

  
52 48
        public Uri Proxy { get; set; }
53 49

  
54 50
        public double DownloadPercentLimit { get; set; }
......
69 65
        //
70 66
        public void Authenticate(string userName,string apiKey)
71 67
        {
72
            Trace.TraceInformation("[AUTHENTICATE] Start for {0}", userName);
73 68
            if (String.IsNullOrWhiteSpace(userName))
74 69
                throw new ArgumentNullException("userName", "The userName property can't be empty");
75 70
            if (String.IsNullOrWhiteSpace(apiKey))
76 71
                throw new ArgumentNullException("apiKey", "The apiKey property can't be empty");
72
            Contract.Ensures(_baseClient != null);
73
            Contract.EndContractBlock();
74

  
75
            Trace.TraceInformation("[AUTHENTICATE] Start for {0}", userName);
77 76

  
78 77
            if (_authenticated)
79 78
                return;
......
87 86
                if (Proxy != null)
88 87
                    authClient.Proxy = new WebProxy(Proxy);
89 88

  
89
                Contract.Assume(authClient.Headers!=null);
90

  
90 91
                authClient.Headers.Add("X-Auth-User", UserName);
91 92
                authClient.Headers.Add("X-Auth-Key", ApiKey);
92 93

  
......
99 100
                    throw new InvalidOperationException("Failed to obtain storage url");
100 101
                StorageUrl = new Uri(storageUrl);
101 102
                
103
                //Get the root address (StorageUrl without the account)
104
                var usernameIndex=storageUrl.LastIndexOf(UserName);
105
                var rootUrl = storageUrl.Substring(0, usernameIndex);
106
                RootAddressUri = new Uri(rootUrl);
107
                
102 108
                var token = authClient.GetHeaderValue("X-Auth-Token");
103 109
                if (String.IsNullOrWhiteSpace(token))
104 110
                    throw new InvalidOperationException("Failed to obtain token url");
......
112 118
            if (Proxy!=null)
113 119
                _baseClient.Proxy = new WebProxy(Proxy);
114 120

  
121
            
122
            
123
            Contract.Assume(_baseClient.Headers!=null);
115 124
            _baseClient.Headers.Add("X-Auth-Token", Token);
116 125

  
117 126
            Trace.TraceInformation("[AUTHENTICATE] End for {0}", userName);
118 127
        }
119 128

  
120 129

  
121
        public IList<ContainerInfo> ListContainers()
130

  
131
        public IList<ContainerInfo> ListContainers(string account)
122 132
        {
133

  
123 134
            using (var client = new RestClient(_baseClient))
124 135
            {
136
                if (!String.IsNullOrWhiteSpace(account))
137
                    client.BaseAddress = GetAccountUrl(account);
138
                
125 139
                client.Parameters.Clear();
126 140
                client.Parameters.Add("format", "json");
127 141
                var content = client.DownloadStringWithRetry("", 3);
......
135 149

  
136 150
        }
137 151

  
152
        private string GetAccountUrl(string account)
153
        {
154
            return new Uri(this.RootAddressUri, new Uri(account,UriKind.Relative)).AbsoluteUri;
155
        }
156

  
157
        public IList<ShareAccountInfo> ListSharingAccounts(DateTime? since=null)
158
        {
159
            Trace.TraceInformation("[START] ListSharingAccounts");
160

  
161
            using (var client = new RestClient(_baseClient))
162
            {
163
                client.Parameters.Clear();
164
                client.Parameters.Add("format", "json");
165
                client.IfModifiedSince = since;
166

  
167
                //Extract the username from the base address
168
                client.BaseAddress = RootAddressUri.AbsoluteUri;
169
                
170
                var content = client.DownloadStringWithRetry(@"", 3);
171

  
172
                client.AssertStatusOK("ListSharingAccounts failed");
173

  
174
                //If the result is empty, return an empty list,
175
                var infos = String.IsNullOrWhiteSpace(content)
176
                    ? new List<ShareAccountInfo>()
177
                    //Otherwise deserialize the account list into a list of ShareAccountInfos
178
                    : JsonConvert.DeserializeObject<IList<ShareAccountInfo>>(content);
179

  
180
                Trace.TraceInformation("[END] ListSharingAccounts");
181
                return infos;
182
            }
183
        }
184

  
138 185
        //Request listing of all objects in a container modified since a specific time.
139 186
        //If the *since* value is missing, return all objects
140
        public IList<ObjectInfo> ListObjects(string container, DateTime? since = null)
187
        public IList<ObjectInfo> ListSharedObjects(DateTime? since = null)
188
        {
189

  
190
            Trace.TraceInformation("[START] ListSharedObjects");
191

  
192
            var objects=new List<ObjectInfo>();
193
            var accounts=ListSharingAccounts(since);
194
            foreach (var account in accounts)
195
            {
196
                var containers=ListContainers(account.name);
197
                foreach (var container in containers)
198
                {
199
                    var containerObjects=ListObjects(account.name, container.Name, account.last_modified);
200
                    objects.AddRange(containerObjects);
201
                }
202
            }
203
            return objects;
204
        }
205

  
206
        public void ShareObject(string account, string container, string objectName, string shareTo, bool read, bool write)
207
        {
208
            if (String.IsNullOrWhiteSpace(Token))
209
                throw new InvalidOperationException("The Token is not set");
210
            if (StorageUrl==null)
211
                throw new InvalidOperationException("The StorageUrl is not set");
212
            if (String.IsNullOrWhiteSpace(container))
213
                throw new ArgumentNullException("container");
214
            if (String.IsNullOrWhiteSpace(objectName))
215
                throw new ArgumentNullException("objectName");
216
            if (String.IsNullOrWhiteSpace(account))
217
                throw new ArgumentNullException("account");
218
            if (String.IsNullOrWhiteSpace(shareTo))
219
                throw new ArgumentNullException("shareTo");
220
            Contract.EndContractBlock();
221

  
222
            using (var client = new RestClient(_baseClient))
223
            {
224
            
225
                client.BaseAddress = GetAccountUrl(account);
226

  
227
                client.Parameters.Clear();
228
                client.Parameters.Add("format", "json");
229

  
230
                string permission = "";
231
                if (write)
232
                    permission = String.Format("write={0}", shareTo); 
233
                else if (read)
234
                    permission=String.Format("read={0}", shareTo);                
235
                client.Headers.Add("X-Object-Sharing",permission);
236
                
237
                var content = client.DownloadStringWithRetry(container, 3);
238

  
239
                client.AssertStatusOK("ShareObject failed");
240

  
241
                //If the result is empty, return an empty list,
242
                var infos = String.IsNullOrWhiteSpace(content)
243
                    ? new List<ObjectInfo>()
244
                    //Otherwise deserialize the object list into a list of ObjectInfos
245
                    : JsonConvert.DeserializeObject<IList<ObjectInfo>>(content);
246

  
247
                Trace.TraceInformation("[END] ListObjects");                
248
            }
249

  
250
            
251
        }
252

  
253

  
254
        public IList<ObjectInfo> ListObjects(string account, string container, DateTime? since = null)
141 255
        {
142 256
            if (String.IsNullOrWhiteSpace(container))
143 257
                throw new ArgumentNullException("container");
......
147 261

  
148 262
            using (var client = new RestClient(_baseClient))
149 263
            {
264
                if (!String.IsNullOrWhiteSpace(account))
265
                    client.BaseAddress = GetAccountUrl(account);
266

  
150 267
                client.Parameters.Clear();
151 268
                client.Parameters.Add("format", "json");
152 269
                client.IfModifiedSince = since;
......
160 277
                    //Otherwise deserialize the object list into a list of ObjectInfos
161 278
                    : JsonConvert.DeserializeObject<IList<ObjectInfo>>(content);
162 279

  
280
                foreach (var info in infos)
281
                {
282
                    info.Container = container;
283
                    info.Account = account;
284
                }
163 285
                Trace.TraceInformation("[END] ListObjects");
164 286
                return infos;
165 287
            }
......
167 289

  
168 290

  
169 291

  
170
        public IList<ObjectInfo> ListObjects(string container, string folder, DateTime? since = null)
292
        public IList<ObjectInfo> ListObjects(string account, string container, string folder, DateTime? since = null)
171 293
        {
172 294
            if (String.IsNullOrWhiteSpace(container))
173 295
                throw new ArgumentNullException("container");
......
179 301

  
180 302
            using (var client = new RestClient(_baseClient))
181 303
            {
304
                if (!String.IsNullOrWhiteSpace(account))
305
                    client.BaseAddress = GetAccountUrl(account);
306

  
182 307
                client.Parameters.Clear();
183 308
                client.Parameters.Add("format", "json");
184 309
                client.Parameters.Add("path", folder);
......
194 319
        }
195 320

  
196 321
 
197
        public bool ContainerExists(string container)
322
        public bool ContainerExists(string account, string container)
198 323
        {
199 324
            if (String.IsNullOrWhiteSpace(container))
200 325
                throw new ArgumentNullException("container", "The container property can't be empty");
326
            Contract.EndContractBlock();
327

  
201 328
            using (var client = new RestClient(_baseClient))
202 329
            {
330
                if (!String.IsNullOrWhiteSpace(account))
331
                    client.BaseAddress = GetAccountUrl(account);
332

  
203 333
                client.Parameters.Clear();
204 334
                client.Head(container, 3);
205 335

  
......
216 346
            }
217 347
        }
218 348

  
219
        public bool ObjectExists(string container,string objectName)
349
        public bool ObjectExists(string account, string container, string objectName)
220 350
        {
221 351
            if (String.IsNullOrWhiteSpace(container))
222 352
                throw new ArgumentNullException("container", "The container property can't be empty");
223 353
            if (String.IsNullOrWhiteSpace(objectName))
224 354
                throw new ArgumentNullException("objectName", "The objectName property can't be empty");
355
            Contract.EndContractBlock();
356

  
225 357
            using (var client = new RestClient(_baseClient))
226 358
            {
359
                if (!String.IsNullOrWhiteSpace(account))
360
                    client.BaseAddress = GetAccountUrl(account);
361

  
227 362
                client.Parameters.Clear();
228 363
                client.Head(container + "/" + objectName, 3);
229 364

  
......
241 376

  
242 377
        }
243 378

  
244
        public ObjectInfo GetObjectInfo(string container, string objectName)
379
        public ObjectInfo GetObjectInfo(string account, string container, string objectName)
245 380
        {
246 381
            if (String.IsNullOrWhiteSpace(container))
247 382
                throw new ArgumentNullException("container", "The container property can't be empty");
248 383
            if (String.IsNullOrWhiteSpace(objectName))
249 384
                throw new ArgumentNullException("objectName", "The objectName property can't be empty");
385
            Contract.EndContractBlock();
250 386

  
251 387
            using (var client = new RestClient(_baseClient))
252 388
            {
389
                if (!String.IsNullOrWhiteSpace(account))
390
                    client.BaseAddress = GetAccountUrl(account);                    
253 391
                try
254 392
                {
255 393
                    client.Parameters.Clear();
......
308 446

  
309 447
        }
310 448

  
311
        public void CreateFolder(string container, string folder)
449
        public void CreateFolder(string account, string container, string folder)
312 450
        {
313 451
            if (String.IsNullOrWhiteSpace(container))
314 452
                throw new ArgumentNullException("container", "The container property can't be empty");
315 453
            if (String.IsNullOrWhiteSpace(folder))
316 454
                throw new ArgumentNullException("folder", "The folder property can't be empty");
455
            Contract.EndContractBlock();
317 456

  
318 457
            var folderUrl=String.Format("{0}/{1}",container,folder);
319 458
            using (var client = new RestClient(_baseClient))
320 459
            {
460
                if (!String.IsNullOrWhiteSpace(account))
461
                    client.BaseAddress = GetAccountUrl(account);
462

  
321 463
                client.Parameters.Clear();
322 464
                client.Headers.Add("Content-Type", @"application/directory");
323 465
                client.Headers.Add("Content-Length", "0");
......
328 470
            }
329 471
        }
330 472

  
331
        public ContainerInfo GetContainerInfo(string container)
473
        public ContainerInfo GetContainerInfo(string account, string container)
332 474
        {
333 475
            if (String.IsNullOrWhiteSpace(container))
334 476
                throw new ArgumentNullException("container", "The container property can't be empty");
477
            Contract.EndContractBlock();
478

  
335 479
            using (var client = new RestClient(_baseClient))
336 480
            {
481
                if (!String.IsNullOrWhiteSpace(account))
482
                    client.BaseAddress = GetAccountUrl(account);                
483

  
337 484
                client.Head(container);
338 485
                switch (client.StatusCode)
339 486
                {
......
357 504
            }
358 505
        }
359 506

  
360
        public void CreateContainer(string container)
361
        {
507
        public void CreateContainer(string account, string container)
508
        {            
362 509
            if (String.IsNullOrWhiteSpace(container))
363 510
                throw new ArgumentNullException("container", "The container property can't be empty");
511
            Contract.EndContractBlock();
512

  
364 513
            using (var client = new RestClient(_baseClient))
365 514
            {
515
                if (!String.IsNullOrWhiteSpace(account))
516
                    client.BaseAddress = GetAccountUrl(account);
517

  
366 518
                client.PutWithRetry(container, 3);
367 519
                var expectedCodes = new[] {HttpStatusCode.Created, HttpStatusCode.Accepted, HttpStatusCode.OK};
368 520
                if (!expectedCodes.Contains(client.StatusCode))
......
370 522
            }
371 523
        }
372 524

  
373
        public void DeleteContainer(string container)
525
        public void DeleteContainer(string account, string container)
374 526
        {
375 527
            if (String.IsNullOrWhiteSpace(container))
376 528
                throw new ArgumentNullException("container", "The container property can't be empty");
529
            Contract.EndContractBlock();
530

  
377 531
            using (var client = new RestClient(_baseClient))
378 532
            {
533
                if (!String.IsNullOrWhiteSpace(account))
534
                    client.BaseAddress = GetAccountUrl(account);
535

  
379 536
                client.DeleteWithRetry(container, 3);
380 537
                var expectedCodes = new[] {HttpStatusCode.NotFound, HttpStatusCode.NoContent};
381 538
                if (!expectedCodes.Contains(client.StatusCode))
......
387 544
        /// <summary>
388 545
        /// 
389 546
        /// </summary>
547
        /// <param name="account"></param>
390 548
        /// <param name="container"></param>
391 549
        /// <param name="objectName"></param>
392 550
        /// <param name="fileName"></param>
......
394 552
        /// <remarks>This method should have no timeout or a very long one</remarks>
395 553
        //Asynchronously download the object specified by *objectName* in a specific *container* to 
396 554
        // a local file
397
        public Task GetObject(string container, string objectName, string fileName)
555
        public Task GetObject(string account, string container, string objectName, string fileName)
398 556
        {
399 557
            if (String.IsNullOrWhiteSpace(container))
400 558
                throw new ArgumentNullException("container", "The container property can't be empty");
......
404 562

  
405 563
            try
406 564
            {
407
                //The container and objectName are relative names. They are joined with the client's
408
                //BaseAddress to create the object's absolute address
409
                var builder = GetAddressBuilder(container, objectName);
410
                var uri = builder.Uri;
411 565
                //WebClient, and by extension RestClient, are not thread-safe. Create a new RestClient
412 566
                //object to avoid concurrency errors.
413 567
                //
414 568
                //Download operations take a long time therefore they have no timeout.
415 569
                var client = new RestClient(_baseClient) { Timeout = 0 };
416
               
570
                if (!String.IsNullOrWhiteSpace(account))
571
                    client.BaseAddress = GetAccountUrl(account);
572

  
573
                //The container and objectName are relative names. They are joined with the client's
574
                //BaseAddress to create the object's absolute address
575
                var builder = client.GetAddressBuilder(container, objectName);
576
                var uri = builder.Uri;
577

  
417 578
                //Download progress is reported to the Trace log
418 579
                Trace.TraceInformation("[GET] START {0}", objectName);
419 580
                client.DownloadProgressChanged += (sender, args) => 
......
453 614

  
454 615
        }
455 616

  
456
        public Task<IList<string>> PutHashMap(string container, string objectName, TreeHash hash)
617
        public Task<IList<string>> PutHashMap(string account, string container, string objectName, TreeHash hash)
457 618
        {
458 619
            if (String.IsNullOrWhiteSpace(container))
459 620
                throw new ArgumentNullException("container");
......
466 627
            if (StorageUrl == null)
467 628
                throw new InvalidOperationException("Invalid Storage Url");
468 629
            Contract.EndContractBlock();
630

  
631

  
632
            //Don't use a timeout because putting the hashmap may be a long process
633
            var client = new RestClient(_baseClient) { Timeout = 0 };
634
            if (!String.IsNullOrWhiteSpace(account))
635
                client.BaseAddress = GetAccountUrl(account);
636

  
469 637
            //The container and objectName are relative names. They are joined with the client's
470 638
            //BaseAddress to create the object's absolute address
471
            var builder = GetAddressBuilder(container, objectName);
639
            var builder = client.GetAddressBuilder(container, objectName);
472 640
            builder.Query = "format=json&hashmap";
473 641
            var uri = builder.Uri;
474 642

  
475
            //Don't use a timeout because putting the hashmap may be a long process
476
            var client = new RestClient(_baseClient) { Timeout = 0 };
477 643

  
478 644
            //Send the tree hash as Json to the server            
479 645
            client.Headers[HttpRequestHeader.ContentType] = "application/octet-stream";
......
533 699

  
534 700
        }
535 701

  
536
        public Task<byte[]> GetBlock(string container, Uri relativeUrl, long start, long? end=null)
702
        public Task<byte[]> GetBlock(string account, string container, Uri relativeUrl, long start, long? end)
537 703
        {
538 704
            if (String.IsNullOrWhiteSpace(Token))
539 705
                throw new InvalidOperationException("Invalid Token");
......
549 715
                throw new ArgumentOutOfRangeException("start");
550 716
            Contract.EndContractBlock();
551 717

  
552
            var builder = GetAddressBuilder(container, relativeUrl.ToString());
553

  
554
            var uri = builder.Uri;
555 718

  
556 719
            //Don't use a timeout because putting the hashmap may be a long process
557 720
            var client = new RestClient(_baseClient) {Timeout = 0, RangeFrom = start, RangeTo = end};
721
            if (!String.IsNullOrWhiteSpace(account))
722
                client.BaseAddress = GetAccountUrl(account);
723

  
724
            var builder = client.GetAddressBuilder(container, relativeUrl.ToString());
725
            var uri = builder.Uri;
726

  
558 727
            return client.DownloadDataTask(uri)
559 728
                .ContinueWith(t=>
560 729
                                  {
......
564 733
        }
565 734

  
566 735

  
567
        public Task PostBlock(string container,byte[] block,int offset,int count)
736
        public Task PostBlock(string account, string container, byte[] block, int offset, int count)
568 737
        {
569 738
            if (String.IsNullOrWhiteSpace(container))
570 739
                throw new ArgumentNullException("container");
......
580 749
                throw new InvalidOperationException("Invalid Storage Url");                        
581 750
            Contract.EndContractBlock();
582 751

  
583
            var builder = GetAddressBuilder(container, "");
752
                        
753
            //Don't use a timeout because putting the hashmap may be a long process
754
            var client = new RestClient(_baseClient) { Timeout = 0 };
755
            if (!String.IsNullOrWhiteSpace(account))
756
                client.BaseAddress = GetAccountUrl(account);
757

  
758
            var builder = client.GetAddressBuilder(container, "");
584 759
            //We are doing an update
585 760
            builder.Query = "update";
586 761
            var uri = builder.Uri;
587
                        
588
            //Don't use a timeout because putting the hashmap may be a long process
589
            var client = new RestClient(_baseClient) { Timeout = 0 };                                   
762

  
590 763
            client.Headers[HttpRequestHeader.ContentType] = "application/octet-stream";
591 764

  
592 765
            Trace.TraceInformation("[BLOCK POST] START");
......
618 791
        }
619 792

  
620 793

  
621
        public Task<TreeHash> GetHashMap(string container, string objectName)
794
        public Task<TreeHash> GetHashMap(string account, string container, string objectName)
622 795
        {
623 796
            if (String.IsNullOrWhiteSpace(container))
624 797
                throw new ArgumentNullException("container");
......
632 805

  
633 806
            try
634 807
            {
635
                //The container and objectName are relative names. They are joined with the client's
636
                //BaseAddress to create the object's absolute address
637
                var builder = GetAddressBuilder(container, objectName);
638
                builder.Query="format=json&hashmap";
639
                var uri = builder.Uri;                
640 808
                //WebClient, and by extension RestClient, are not thread-safe. Create a new RestClient
641 809
                //object to avoid concurrency errors.
642 810
                //
643 811
                //Download operations take a long time therefore they have no timeout.
644 812
                //TODO: Do we really? this is a hashmap operation, not a download
645 813
                var client = new RestClient(_baseClient) { Timeout = 0 };
646
               
814
                if (!String.IsNullOrWhiteSpace(account))
815
                    client.BaseAddress = GetAccountUrl(account);
816

  
647 817

  
818
                //The container and objectName are relative names. They are joined with the client's
819
                //BaseAddress to create the object's absolute address
820
                var builder = client.GetAddressBuilder(container, objectName);
821
                builder.Query = "format=json&hashmap";
822
                var uri = builder.Uri;
823
                
648 824
                //Start downloading the object asynchronously
649 825
                var downloadTask = client.DownloadStringTask(uri);
650 826
                
......
678 854

  
679 855
        }
680 856

  
681
        private UriBuilder GetAddressBuilder(string container, string objectName)
682
        {
683
            var builder = new UriBuilder(String.Join("/", _baseClient.BaseAddress, container, objectName));
684
            return builder;
685
        }
686

  
687 857

  
688 858
        /// <summary>
689 859
        /// 
690 860
        /// </summary>
861
        /// <param name="account"></param>
691 862
        /// <param name="container"></param>
692 863
        /// <param name="objectName"></param>
693 864
        /// <param name="fileName"></param>
694 865
        /// <param name="hash">Optional hash value for the file. If no hash is provided, the method calculates a new hash</param>
695 866
        /// <remarks>>This method should have no timeout or a very long one</remarks>
696
        public Task PutObject(string container, string objectName, string fileName, string hash = null)
867
        public Task PutObject(string account, string container, string objectName, string fileName, string hash = null)
697 868
        {
698 869
            if (String.IsNullOrWhiteSpace(container))
699 870
                throw new ArgumentNullException("container", "The container property can't be empty");
......
703 874
                throw new ArgumentNullException("fileName", "The fileName property can't be empty");
704 875
            if (!File.Exists(fileName))
705 876
                throw new FileNotFoundException("The file does not exist",fileName);
706

  
877
            Contract.EndContractBlock();
707 878
            
708 879
            try
709 880
            {
710
                var builder= GetAddressBuilder(container,objectName);
881

  
882
                var client = new RestClient(_baseClient){Timeout=0};
883
                if (!String.IsNullOrWhiteSpace(account))
884
                    client.BaseAddress = GetAccountUrl(account);
885

  
886
                var builder = client.GetAddressBuilder(container, objectName);
711 887
                var uri = builder.Uri;
712 888

  
713
                var client = new RestClient(_baseClient){Timeout=0};           
714 889
                string etag = hash ?? CalculateHash(fileName);
715 890

  
716 891
                client.Headers.Add("Content-Type", "application/octet-stream");
......
765 940
            return hash;
766 941
        }
767 942

  
768
        public void DeleteObject(string container, string objectName)
943
       /* public void DeleteObject(string container, string objectName,string account)
769 944
        {
770 945
            if (String.IsNullOrWhiteSpace(container))
771 946
                throw new ArgumentNullException("container", "The container property can't be empty");
772 947
            if (String.IsNullOrWhiteSpace(objectName))
773 948
                throw new ArgumentNullException("objectName", "The objectName property can't be empty");
949
            Contract.EndContractBlock();
950

  
774 951
            using (var client = new RestClient(_baseClient))
775 952
            {
776

  
953
                if (!String.IsNullOrWhiteSpace(account))
954
                    client.BaseAddress = GetAccountUrl(account);
955
                );
777 956
                client.DeleteWithRetry(container + "/" + objectName, 3);
778 957

  
779 958
                var expectedCodes = new[] {HttpStatusCode.NotFound, HttpStatusCode.NoContent};
......
781 960
                    throw CreateWebException("DeleteObject", client.StatusCode);
782 961
            }
783 962

  
784
        }
963
        }*/
785 964

  
786
        public void MoveObject(string sourceContainer, string oldObjectName, string targetContainer,string newObjectName)
965
        public void MoveObject(string account, string sourceContainer, string oldObjectName, string targetContainer, string newObjectName)
787 966
        {
788 967
            if (String.IsNullOrWhiteSpace(sourceContainer))
789 968
                throw new ArgumentNullException("sourceContainer", "The container property can't be empty");
......
793 972
                throw new ArgumentNullException("targetContainer", "The container property can't be empty");
794 973
            if (String.IsNullOrWhiteSpace(newObjectName))
795 974
                throw new ArgumentNullException("newObjectName", "The newObjectName property can't be empty");
975
            Contract.EndContractBlock();
796 976

  
797 977
            var targetUrl = targetContainer + "/" + newObjectName;
798 978
            var sourceUrl = String.Format("/{0}/{1}", sourceContainer, oldObjectName);
799 979

  
800 980
            using (var client = new RestClient(_baseClient))
801 981
            {
982
                if (!String.IsNullOrWhiteSpace(account))
983
                    client.BaseAddress = GetAccountUrl(account);
984

  
802 985
                client.Headers.Add("X-Move-From", sourceUrl);
803 986
                client.PutWithRetry(targetUrl, 3);
804 987

  
......
808 991
            }
809 992
        }
810 993

  
811
        public void DeleteObject(string sourceContainer, string objectName, string targetContainer)
994
        public void DeleteObject(string account, string sourceContainer, string objectName, string targetContainer)
812 995
        {            
813 996
            if (String.IsNullOrWhiteSpace(sourceContainer))
814 997
                throw new ArgumentNullException("sourceContainer", "The container property can't be empty");
......
816 999
                throw new ArgumentNullException("objectName", "The oldObjectName property can't be empty");
817 1000
            if (String.IsNullOrWhiteSpace(targetContainer))
818 1001
                throw new ArgumentNullException("targetContainer", "The container property can't be empty");
1002
            Contract.EndContractBlock();
819 1003

  
820 1004
            var targetUrl = targetContainer + "/" + objectName;
821 1005
            var sourceUrl = String.Format("/{0}/{1}", sourceContainer, objectName);
822 1006

  
823 1007
            using (var client = new RestClient(_baseClient))
824 1008
            {
1009
                if (!String.IsNullOrWhiteSpace(account))
1010
                    client.BaseAddress = GetAccountUrl(account);
1011

  
825 1012
                client.Headers.Add("X-Move-From", sourceUrl);
826 1013
                client.PutWithRetry(targetUrl, 3);
827 1014

  
......
839 1026

  
840 1027
        
841 1028
    }
1029

  
1030
    public class ShareAccountInfo
1031
    {
1032
        public DateTime? last_modified { get; set; }
1033
        public string name { get; set; }
1034
    }
842 1035
}

Also available in: Unified diff