~ubuntu-branches/debian/squeeze/gnome-do-plugins/squeeze

« back to all changes in this revision

Viewing changes to BundledLibraries/libgoogle-data-mono-1.4.0.2/src/core/service.cs

  • Committer: Bazaar Package Importer
  • Author(s): Christopher James Halse Rogers
  • Date: 2009-06-27 16:11:49 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20090627161149-b74nc297di2842u1
* New upstream release
  + Pidgin plugin now supports initial text for messages (LP: #338608)
  + Pidgin plugin opens conversations on the correct IM network (LP: #370965)
* debian/rules:
  + Update get-orig-source target.  Upstream no longer ships gdata* binaries,
    so we no longer need to strip them
* debian/patches/00_use_system_gdata
  + Drop.  Upstream now builds against system libgdata.
* debian/patches/04_fix_pidgin_dbus_ints
* debian/patches/10_fix_rhythmbox_file
* debian/patches/15_twitter_api
* debian/patches/20_twitter_overflow:
  + Drop.  Included upstream.
* debian/patches/01_firefox_iceweasel_rename:
  + Refresh for new version
* debian/patches/02_fix_banshee_plugin:
  + Drop refernce to /usr/lib/banshee-1/Banshee.CollectionIndexer.dll.
    This is unnecessary, and causes errors when Banshee isn't installed.
* debian/patches/00_debian_default_plugins:
  + Enable a bunch of useful plugins that do not require configuration from 
    the "Official" plugin set by default.  Makes Do more useful out of the 
    box.
* debian/control:
  + Bump versioned build-dep on gnome-do to 0.8.2
  + Split out gnome-do-plugin-evolution package, now that this is possible.
    libevolution5.0-cil has an annoyingly large dependency stack.
    (LP: #351535) (Closes: #524993).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2006 Google Inc.
2
 
 *
3
 
 * Licensed under the Apache License, Version 2.0 (the "License");
4
 
 * you may not use this file except in compliance with the License.
5
 
 * You may obtain a copy of the License at
6
 
 *
7
 
 *     http://www.apache.org/licenses/LICENSE-2.0
8
 
 *
9
 
 * Unless required by applicable law or agreed to in writing, software
10
 
 * distributed under the License is distributed on an "AS IS" BASIS,
11
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
 
 * See the License for the specific language governing permissions and
13
 
 * limitations under the License.
14
 
*/
15
 
/* Change history
16
 
* Oct 13 2008  Joe Feser       joseph.feser@gmail.com
17
 
* Removed warnings
18
 
19
 
*/
20
 
#region Using directives
21
 
 
22
 
#define USE_TRACING
23
 
 
24
 
using System;
25
 
using System.Xml;
26
 
using System.IO;
27
 
using System.Net;
28
 
using System.Threading;
29
 
using System.ComponentModel;
30
 
using System.Collections.Specialized;
31
 
 
32
 
 
33
 
 
34
 
#endregion
35
 
 
36
 
/////////////////////////////////////////////////////////////////////
37
 
// <summary>contains Service, the base interface that 
38
 
//   allows to query a service for different feeds
39
 
//  </summary>
40
 
////////////////////////////////////////////////////////////////////
41
 
namespace Google.GData.Client
42
 
{
43
 
 
44
 
    /// <summary>
45
 
    /// EventArgument class for service level events during parsing
46
 
    /// </summary>
47
 
    public class ServiceEventArgs : EventArgs
48
 
    {
49
 
        private AtomFeed feedObject;
50
 
        private IService service;
51
 
        private Uri uri;
52
 
 
53
 
        /// <summary>
54
 
        /// constructor. Takes the URI and the service this event applies to
55
 
        /// </summary>
56
 
        /// <param name="uri">URI currently executed</param>
57
 
        /// <param name="service">service object doing the execution</param>
58
 
        public ServiceEventArgs(Uri uri, IService service) 
59
 
        {
60
 
            this.service = service;
61
 
            this.uri = uri;
62
 
        }
63
 
    
64
 
        /// <summary>the feed to be created. If this is NULL, a service 
65
 
        /// will create a DEFAULT atomfeed</summary> 
66
 
        /// <returns> </returns>
67
 
        //////////////////////////////////////////////////////////////////////
68
 
        public AtomFeed Feed
69
 
        {
70
 
            get {return this.feedObject;}
71
 
            set {this.feedObject = value;}
72
 
        }
73
 
        ////////////////////////////////////////////////////////////////////////
74
 
        //////////////////////////////////////////////////////////////////////
75
 
        /// <summary>the service to be used for the feed to be created. </summary> 
76
 
        /// <returns> </returns>
77
 
        //////////////////////////////////////////////////////////////////////
78
 
        public IService Service
79
 
        {
80
 
            get {return this.service;}
81
 
        }
82
 
        ////////////////////////////////////////////////////////////////////////
83
 
        //////////////////////////////////////////////////////////////////////
84
 
        /// <summary>the Uri to be used</summary> 
85
 
        /// <returns> </returns>
86
 
        //////////////////////////////////////////////////////////////////////
87
 
        public Uri Uri
88
 
        {
89
 
            get {return this.uri;}
90
 
        }
91
 
        ////////////////////////////////////////////////////////////////////////
92
 
   }
93
 
 
94
 
 
95
 
 
96
 
    /// <summary>Delegate declaration for the feed creation in a service</summary> 
97
 
    public delegate void ServiceEventHandler(object sender, ServiceEventArgs e);
98
 
 
99
 
 
100
 
   
101
 
    //////////////////////////////////////////////////////////////////////
102
 
    /// <summary>base Service implementation
103
 
    /// </summary> 
104
 
    //////////////////////////////////////////////////////////////////////
105
 
    public partial class Service : IService, IVersionAware
106
 
    {
107
 
        /// <summary>holds the credential information</summary> 
108
 
        private GDataCredentials credentials; 
109
 
        /// <summary>the GDatarequest to use</summary> 
110
 
        private IGDataRequestFactory factory;
111
 
        /// <summary>holds the hooks for the eventing in the feedparser</summary> 
112
 
        public event FeedParserEventHandler NewAtomEntry;
113
 
        /// <summary>eventhandler, when the parser finds a new extension element-> mirrored from underlying parser</summary> 
114
 
        public event ExtensionElementEventHandler NewExtensionElement;
115
 
        /// <summary>eventhandler, when the service needs to create a new feed</summary> 
116
 
        public event ServiceEventHandler NewFeed;
117
 
 
118
 
        private string serviceID;
119
 
 
120
 
 
121
 
        //////////////////////////////////////////////////////////////////////
122
 
        /// <summary>default constructor, sets the default GDataRequest</summary> 
123
 
        //////////////////////////////////////////////////////////////////////
124
 
        public Service()
125
 
        {
126
 
            this.RequestFactory = new GDataRequestFactory(this.GetType().Name);
127
 
            InitDelegates();
128
 
            InitVersionInformation();
129
 
        }
130
 
        /////////////////////////////////////////////////////////////////////////////
131
 
 
132
 
 
133
 
        //////////////////////////////////////////////////////////////////////
134
 
        /// <summary>default constructor, sets the default GDataRequest</summary> 
135
 
        //////////////////////////////////////////////////////////////////////
136
 
        public Service(string applicationName)
137
 
        {
138
 
            this.RequestFactory = new GDataRequestFactory(applicationName == null ? 
139
 
                                                            this.GetType().Name : 
140
 
                                                            applicationName);
141
 
            InitDelegates();
142
 
            InitVersionInformation();
143
 
        }
144
 
        /////////////////////////////////////////////////////////////////////////////
145
 
 
146
 
 
147
 
        //////////////////////////////////////////////////////////////////////
148
 
        /// <summary>this will trigger the creation of an authenticating service</summary> 
149
 
        //////////////////////////////////////////////////////////////////////
150
 
        public Service(string service, string applicationName)
151
 
        {
152
 
            this.RequestFactory = new GDataGAuthRequestFactory(service, applicationName);
153
 
            this.serviceID = service; 
154
 
            InitDelegates();
155
 
            InitVersionInformation();
156
 
        }
157
 
        /////////////////////////////////////////////////////////////////////////////
158
 
 
159
 
 
160
 
        /// <summary>
161
 
        /// this returns the string that the services uses to identify the google service to use
162
 
        /// when authentication with Google is required. Examples are "cl" for calendar, e.g. 
163
 
        /// </summary>
164
 
        /// <returns></returns>
165
 
        public string ServiceIdentifier
166
 
        {
167
 
            get
168
 
            {
169
 
                return this.serviceID;
170
 
            }
171
 
        }
172
 
  
173
 
        private VersionInformation versionInfo = new VersionInformation();
174
 
        /// <summary>
175
 
        /// returns the major protocol version number this element 
176
 
        /// is working against. 
177
 
        /// </summary>
178
 
        /// <returns></returns>
179
 
        public int ProtocolMajor
180
 
        {
181
 
            get
182
 
            {
183
 
                return this.versionInfo.ProtocolMajor;
184
 
            }
185
 
            set
186
 
            {
187
 
                this.versionInfo.ProtocolMajor  = value;
188
 
                PropagateVersionInfo();
189
 
            }
190
 
        }
191
 
 
192
 
        /// <summary>
193
 
        /// returns the minor protocol version number this element 
194
 
        /// is working against. 
195
 
        /// </summary>
196
 
        /// <returns></returns>
197
 
        public int ProtocolMinor
198
 
        {
199
 
            get
200
 
            {
201
 
                return this.versionInfo.ProtocolMinor;
202
 
            }
203
 
            set
204
 
            {
205
 
                this.versionInfo.ProtocolMinor  = value;
206
 
                PropagateVersionInfo();
207
 
            }
208
 
        }
209
 
        
210
 
        /// <summary>
211
 
        /// by default all services now use version 2 for the protocol.
212
 
        /// this needs to be overridden by a service to specify otherwise. 
213
 
        /// </summary>
214
 
        /// <returns></returns>
215
 
        protected virtual void InitVersionInformation()
216
 
        {
217
 
        }
218
 
 
219
 
        //////////////////////////////////////////////////////////////////////
220
 
        /// <summary>accessor method public IGDataRequest Request</summary> 
221
 
        /// <returns> </returns>
222
 
        //////////////////////////////////////////////////////////////////////
223
 
        public IGDataRequestFactory RequestFactory
224
 
        {
225
 
            get { return this.factory; }
226
 
            set { this.factory = value; OnRequestFactoryChanged(); }
227
 
        }
228
 
 
229
 
        /// <summary>
230
 
        /// notifier if someone changes the requestfactory of the service. 
231
 
        /// This will cause the service to set the versionnumber on the 
232
 
        /// request factory to it's own
233
 
        /// </summary>
234
 
        public virtual void OnRequestFactoryChanged() 
235
 
        {
236
 
            PropagateVersionInfo();
237
 
        }
238
 
 
239
 
        private void PropagateVersionInfo()
240
 
        {
241
 
            IVersionAware v = this.factory as IVersionAware;
242
 
            if (v != null)
243
 
            {
244
 
                v.ProtocolMajor = this.ProtocolMajor;
245
 
                v.ProtocolMinor = this.ProtocolMinor;
246
 
            }
247
 
            return; 
248
 
        }
249
 
 
250
 
        //////////////////////////////////////////////////////////////////////
251
 
        /// <summary>accessor method public ICredentials Credentials</summary> 
252
 
        /// <returns> </returns>
253
 
        //////////////////////////////////////////////////////////////////////
254
 
        public GDataCredentials Credentials
255
 
        {
256
 
            get {return this.credentials;}
257
 
            set 
258
 
            {
259
 
                this.credentials = value; 
260
 
                // if we get new credentials, make sure we invalidate the old authtoken
261
 
                SetAuthenticationToken(value == null ? null : value.ClientToken);
262
 
            }
263
 
        }
264
 
        /////////////////////////////////////////////////////////////////////////////
265
 
 
266
 
 
267
 
        /// <summary>
268
 
        /// if the service is using a Google Request Factory it will use that 
269
 
        /// assuming credentials are set to retrieve the authentication token
270
 
        /// for those credentials
271
 
        /// </summary>
272
 
        /// <returns>string</returns>
273
 
        public string QueryAuthenticationToken() 
274
 
        {
275
 
            if (this.Credentials != null)
276
 
            {
277
 
                GDataGAuthRequestFactory factory = this.factory as GDataGAuthRequestFactory;
278
 
                if (factory != null)
279
 
                {
280
 
                    return factory.QueryAuthToken(this.Credentials);
281
 
                }
282
 
            }
283
 
            return null;
284
 
        }
285
 
 
286
 
        /// <summary>
287
 
        /// if the service is using a Google Request Factory it will set the passed 
288
 
        /// in token to the factory. NET CF does not support authsubtokens here
289
 
        /// </summary>
290
 
        /// <returns>string</returns>
291
 
        public void SetAuthenticationToken(string token) 
292
 
        {
293
 
            GDataGAuthRequestFactory factory = this.factory as GDataGAuthRequestFactory;
294
 
            if (factory != null)
295
 
            {
296
 
                factory.GAuthToken = token;
297
 
            }
298
 
#if WindowsCE || PocketPC
299
 
#else
300
 
            else 
301
 
            {
302
 
                GAuthSubRequestFactory f = this.factory as GAuthSubRequestFactory;
303
 
                if (f != null)
304
 
                {
305
 
                    f.Token = token;
306
 
                }
307
 
            }
308
 
#endif
309
 
        }
310
 
 
311
 
        /// <summary>
312
 
        /// Sets the credentials of the user to authenticate requests
313
 
        /// to the server.
314
 
        /// </summary>
315
 
        /// <param name="username"></param>
316
 
        /// <param name="password"></param>
317
 
        public void setUserCredentials(String username, String password)
318
 
        {
319
 
            this.Credentials = new GDataCredentials(username, password);
320
 
        }
321
 
 
322
 
 
323
 
 
324
 
   
325
 
        //////////////////////////////////////////////////////////////////////
326
 
        /// <summary>the basic interface. Take a URI and just get it</summary> 
327
 
        /// <param name="queryUri">the URI to execute</param>
328
 
        /// <returns> a webresponse object</returns>
329
 
        //////////////////////////////////////////////////////////////////////
330
 
        public Stream Query(Uri queryUri)
331
 
        {
332
 
          return Query(queryUri, DateTime.MinValue);
333
 
        }
334
 
 
335
 
        //////////////////////////////////////////////////////////////////////
336
 
        /// <summary>the basic interface. Take a URI and just get it</summary> 
337
 
        /// <param name="queryUri">the URI to execute</param>
338
 
        /// <param name="ifModifiedSince">used to set a precondition date that 
339
 
        /// indicates the feed should be returned only if it has been modified 
340
 
        /// after the specified date. A value of DateTime.MinValue indicates no 
341
 
        /// precondition.</param>
342
 
        /// <returns> a webresponse object</returns>
343
 
        //////////////////////////////////////////////////////////////////////
344
 
        public Stream Query(Uri queryUri, DateTime ifModifiedSince)
345
 
        {
346
 
            long l;
347
 
            return this.Query(queryUri, ifModifiedSince, null, out l);
348
 
        }
349
 
        /////////////////////////////////////////////////////////////////////////////
350
 
 
351
 
 
352
 
        //////////////////////////////////////////////////////////////////////
353
 
        /// <summary>the basic interface. Take a URI and just get it</summary> 
354
 
        /// <param name="queryUri">the URI to execute</param>
355
 
        /// <param name="etag">used to set a precondition etag that 
356
 
        /// indicates the feed should be returned only if it has been modified </param>
357
 
        /// <returns> a webresponse object</returns>
358
 
        //////////////////////////////////////////////////////////////////////
359
 
        public Stream Query(Uri queryUri, string etag)
360
 
        {
361
 
            long l;
362
 
            return this.Query(queryUri, DateTime.MinValue, etag, out l);
363
 
        }
364
 
        /////////////////////////////////////////////////////////////////////////////
365
 
 
366
 
        //////////////////////////////////////////////////////////////////////
367
 
        /// <summary>the basic interface. Take a URI and just get it</summary> 
368
 
        /// <param name="queryUri">the URI to execute</param>
369
 
        /// <param name="ifModifiedSince">used to set a precondition date that 
370
 
        /// indicates the feed should be returned only if it has been modified 
371
 
        /// after the specified date. A value of DateTime.MinValue indicates no 
372
 
        /// precondition.</param>
373
 
        /// <param name="etag">used to set a precondition etag that 
374
 
        /// indicates the feed should be returned only if it has been modified </param>
375
 
        /// <param name="contentLength">returns the content length of the response</param>
376
 
        /// <returns> a webresponse object</returns>
377
 
        //////////////////////////////////////////////////////////////////////
378
 
        private Stream Query(Uri queryUri, DateTime ifModifiedSince, string etag, out long contentLength)
379
 
        {
380
 
            Tracing.TraceCall("Enter");
381
 
            if (queryUri == null)
382
 
            {
383
 
              throw new System.ArgumentNullException("queryUri");
384
 
            }
385
 
 
386
 
            contentLength = -1; 
387
 
 
388
 
            IGDataRequest request = this.RequestFactory.CreateRequest(GDataRequestType.Query, queryUri);
389
 
            request.Credentials = this.Credentials;
390
 
            request.IfModifiedSince = ifModifiedSince;
391
 
 
392
 
            if (etag != null)
393
 
            {
394
 
                ISupportsEtag ise = request as ISupportsEtag;
395
 
                if (ise != null)
396
 
                {
397
 
                    ise.Etag = etag; 
398
 
                }
399
 
            }
400
 
 
401
 
            try
402
 
            {
403
 
              request.Execute();
404
 
            }
405
 
            catch (Exception)
406
 
            {
407
 
              // Prevent connection leaks
408
 
              if (request.GetResponseStream() != null)
409
 
                request.GetResponseStream().Close();
410
 
 
411
 
              throw;
412
 
            }
413
 
 
414
 
            // return the response
415
 
            GDataGAuthRequest gr = request as GDataGAuthRequest;
416
 
            if (gr != null)
417
 
            {
418
 
                 contentLength = gr.ContentLength;
419
 
            }
420
 
            
421
 
            Tracing.TraceCall("Exit");
422
 
            return new GDataReturnStream(request);
423
 
        }
424
 
        /////////////////////////////////////////////////////////////////////////////
425
 
 
426
 
 
427
 
        /// <summary>
428
 
        /// Returns a single Atom entry based upon its unique URI.
429
 
        /// </summary>
430
 
        /// <param name="entryUri">The URI of the Atom entry.</param>
431
 
        /// <returns>AtomEntry representing the entry.</returns>
432
 
        public AtomEntry Get(string entryUri)
433
 
        {
434
 
            FeedQuery query = new FeedQuery(entryUri);
435
 
            AtomFeed resultFeed = Query(query);
436
 
            return resultFeed.Entries[0];
437
 
        }
438
 
 
439
 
 
440
 
   
441
 
        //////////////////////////////////////////////////////////////////////
442
 
        /// <summary>executes the query and returns an AtomFeed object tree</summary> 
443
 
        /// <param name="feedQuery">the query parameters as a FeedQuery object </param>
444
 
        /// <returns>AtomFeed object tree</returns>
445
 
        //////////////////////////////////////////////////////////////////////
446
 
        public AtomFeed Query(FeedQuery feedQuery)
447
 
        {
448
 
            AtomFeed feed = null;
449
 
            Tracing.TraceCall("Enter");
450
 
 
451
 
            if (feedQuery == null)
452
 
            {
453
 
                throw new System.ArgumentNullException("feedQuery", "The query argument MUST not be null");
454
 
            }
455
 
            // Create a new request to the Uri in the query object...    
456
 
            Uri targetUri = null;
457
 
 
458
 
            try
459
 
            {
460
 
                targetUri = feedQuery.Uri;
461
 
 
462
 
            }
463
 
            catch (System.UriFormatException)
464
 
            {
465
 
                throw new System.ArgumentException("The query argument MUST contain a valid Uri", "feedQuery");
466
 
            }
467
 
 
468
 
            Tracing.TraceInfo("Service:Query - about to query");
469
 
 
470
 
            Stream responseStream = null;
471
 
 
472
 
            if (feedQuery.Etag != null)
473
 
            {
474
 
                responseStream = Query(targetUri, feedQuery.Etag);
475
 
            }
476
 
            else
477
 
            {
478
 
                responseStream = Query(targetUri, feedQuery.ModifiedSince);
479
 
            }
480
 
 
481
 
            Tracing.TraceInfo("Service:Query - query done");
482
 
            if (responseStream != null)
483
 
            {
484
 
                feed = CreateAndParseFeed(responseStream, feedQuery.Uri);
485
 
            }
486
 
            Tracing.TraceCall("Exit");
487
 
            return feed;
488
 
 
489
 
        }
490
 
        /////////////////////////////////////////////////////////////////////////////
491
 
 
492
 
 
493
 
        //////////////////////////////////////////////////////////////////////
494
 
        /// <summary>executes the query and returns an AtomFeed object tree</summary> 
495
 
        /// <param name="feedQuery">the query parameters as a FeedQuery object </param>
496
 
        /// <param name="ifModifiedSince">used to set a precondition date that 
497
 
        /// indicates the feed should be returned only if it has been modified 
498
 
        /// after the specified date. A value of null indicates no 
499
 
        /// precondition.</param>
500
 
        /// <returns>AtomFeed object tree</returns>
501
 
        //////////////////////////////////////////////////////////////////////
502
 
        [Obsolete("FeedQuery has a modifiedSince property, use that instead")] 
503
 
        public AtomFeed Query(FeedQuery feedQuery, DateTime ifModifiedSince)
504
 
        {
505
 
            feedQuery.ModifiedSince = ifModifiedSince;
506
 
            return Query(feedQuery);
507
 
        }
508
 
        /////////////////////////////////////////////////////////////////////////////
509
 
 
510
 
 
511
 
 
512
 
 
513
 
 
514
 
        //////////////////////////////////////////////////////////////////////
515
 
        /// <summary>object QueryOpenSearchRssDescription()</summary> 
516
 
        /// <param name="serviceUri">the service to ask for an OpenSearchRss Description</param> 
517
 
        /// <returns> a webresponse object</returns>
518
 
        //////////////////////////////////////////////////////////////////////
519
 
        public Stream QueryOpenSearchRssDescription(Uri serviceUri)
520
 
        {
521
 
            if (serviceUri == null)
522
 
            {
523
 
                throw new System.ArgumentNullException("serviceUri");
524
 
            }
525
 
            IGDataRequest request = this.RequestFactory.CreateRequest(GDataRequestType.Query, serviceUri);
526
 
            request.Credentials = this.Credentials;
527
 
            request.Execute();
528
 
            // return the response
529
 
            return request.GetResponseStream();
530
 
        }
531
 
        /////////////////////////////////////////////////////////////////////////////
532
 
 
533
 
 
534
 
 
535
 
        //////////////////////////////////////////////////////////////////////
536
 
        /// <summary>WebResponse Update(Uri updateUri, Stream entryStream, ICredentials credentials)</summary> 
537
 
        /// <param name="entry">the old entry to update</param> 
538
 
        /// <returns> the new Entry, as returned from the server</returns>
539
 
        //////////////////////////////////////////////////////////////////////
540
 
        public AtomEntry Update(AtomEntry entry)
541
 
        {
542
 
            return this.Update(entry, null); 
543
 
        }
544
 
        /////////////////////////////////////////////////////////////////////////////
545
 
 
546
 
 
547
 
 
548
 
 
549
 
        //////////////////////////////////////////////////////////////////////
550
 
        /// <summary>templated type safe verion of the interface</summary> 
551
 
        /// <param name="entry">the old entry to update</param> 
552
 
        /// <returns> the new Entry, as returned from the server</returns>
553
 
        //////////////////////////////////////////////////////////////////////
554
 
        public TEntry  Update<TEntry>(TEntry entry) where TEntry : AtomEntry
555
 
        {
556
 
            return this.Update(entry, null) as TEntry;
557
 
        }
558
 
        /////////////////////////////////////////////////////////////////////////////
559
 
 
560
 
 
561
 
        //////////////////////////////////////////////////////////////////////
562
 
        /// <summary>WebResponse Update(Uri updateUri, Stream entryStream, ICredentials credentials)</summary> 
563
 
        /// <param name="entry">the old entry to update</param> 
564
 
        /// <param name="data">the async data block used</param> 
565
 
        /// <returns> the new Entry, as returned from the server</returns>
566
 
        //////////////////////////////////////////////////////////////////////
567
 
        private AtomEntry Update(AtomEntry entry, AsyncSendData data)
568
 
        {
569
 
            Tracing.Assert(entry != null, "entry should not be null");
570
 
            if (entry == null)
571
 
            {
572
 
                throw new ArgumentNullException("entry"); 
573
 
            }
574
 
 
575
 
            if (entry.ReadOnly == true)
576
 
            {
577
 
                throw new GDataRequestException("Can not update a read-only entry"); 
578
 
            }
579
 
 
580
 
 
581
 
            Uri target = new Uri(entry.EditUri.ToString());
582
 
 
583
 
            Stream returnStream = EntrySend(target, entry, GDataRequestType.Update, data);
584
 
            return CreateAndParseEntry(returnStream, target);
585
 
        }
586
 
        /////////////////////////////////////////////////////////////////////////////
587
 
 
588
 
   
589
 
 
590
 
        //////////////////////////////////////////////////////////////////////
591
 
        /// <summary>public WebResponse Insert(Uri insertUri, Stream entryStream, ICredentials credentials)</summary> 
592
 
        /// <param name="feed">the feed this entry should be inserted into</param> 
593
 
        /// <param name="entry">the entry to be inserted</param> 
594
 
        /// <returns> the inserted entry</returns>
595
 
        //////////////////////////////////////////////////////////////////////
596
 
        AtomEntry IService.Insert(AtomFeed feed, AtomEntry entry)
597
 
        {
598
 
 
599
 
            Tracing.Assert(feed != null, "feed should not be null");
600
 
            if (feed == null)
601
 
            {
602
 
                throw new ArgumentNullException("feed"); 
603
 
            }
604
 
            Tracing.Assert(entry != null, "entry should not be null");
605
 
            if (entry == null)
606
 
            {
607
 
                throw new ArgumentNullException("entry"); 
608
 
            }
609
 
 
610
 
            if (feed.ReadOnly == true)
611
 
            {
612
 
                throw new GDataRequestException("Can not update a read-only feed"); 
613
 
            }
614
 
 
615
 
            Tracing.TraceMsg("Post URI is: " + feed.Post); 
616
 
            Uri target = new Uri(feed.Post); 
617
 
            return Insert(target, entry);
618
 
        }
619
 
        /////////////////////////////////////////////////////////////////////////////
620
 
        
621
 
 
622
 
 
623
 
     
624
 
        //////////////////////////////////////////////////////////////////////
625
 
        /// <summary>
626
 
        /// templated type safe version of Insert
627
 
        /// </summary>
628
 
        /// <typeparam name="TEntry"></typeparam>
629
 
        /// <param name="feed"></param>
630
 
        /// <param name="entry"></param>
631
 
        /// <returns> the new Entry, as returned from the server</returns>
632
 
        public TEntry Insert<TEntry>(AtomFeed feed, TEntry entry) where TEntry : AtomEntry
633
 
        {
634
 
            IService s = this as IService; 
635
 
            return s.Insert(feed, entry) as TEntry;
636
 
        }
637
 
        /////////////////////////////////////////////////////////////////////////////
638
 
 
639
 
        //////////////////////////////////////////////////////////////////////
640
 
        /// <summary>templated type safe verion of the interface</summary> 
641
 
        /// <typeparam name="TEntry"></typeparam>
642
 
        /// <param name="feedUri"></param>
643
 
        /// <param name="entry">the old entry to update</param> 
644
 
        /// <returns> the new Entry, as returned from the server</returns> 
645
 
        public TEntry Insert<TEntry>(Uri feedUri, TEntry entry) where TEntry : AtomEntry
646
 
        {
647
 
            return this.Insert(feedUri, entry, null) as TEntry;
648
 
        }
649
 
        /////////////////////////////////////////////////////////////////////////////
650
 
 
651
 
        /// <summary>
652
 
        /// internal Insert version to avoid recursion in the template versions
653
 
        /// </summary>
654
 
        /// <param name="feedUri"></param>
655
 
        /// <param name="newEntry"></param>
656
 
        /// <returns></returns>
657
 
        protected AtomEntry internalInsert(Uri feedUri, AtomEntry newEntry)
658
 
        {
659
 
            return this.Insert(feedUri, newEntry, null);
660
 
        }
661
 
 
662
 
 
663
 
 
664
 
        //////////////////////////////////////////////////////////////////////
665
 
        /// <summary>public WebResponse Insert(Uri insertUri, Stream entryStream, ICredentials credentials)</summary> 
666
 
        /// <param name="feedUri">the uri for the feed this entry should be inserted into</param> 
667
 
        /// <param name="newEntry">the entry to be inserted</param> 
668
 
        /// <param name="data">the data used for an async request</param>
669
 
        /// <returns> the inserted entry</returns>
670
 
        //////////////////////////////////////////////////////////////////////
671
 
        private AtomEntry Insert(Uri feedUri, AtomEntry newEntry, AsyncSendData data)
672
 
        {
673
 
            Tracing.Assert(feedUri != null, "feedUri should not be null");
674
 
            if (feedUri == null)
675
 
            {
676
 
                throw new ArgumentNullException("feedUri"); 
677
 
            }
678
 
            Tracing.Assert(newEntry != null, "newEntry should not be null");
679
 
            if (newEntry == null)
680
 
            {
681
 
                throw new ArgumentNullException("newEntry"); 
682
 
            }
683
 
            this.versionInfo.ImprintVersion(newEntry);
684
 
 
685
 
            Stream returnStream = EntrySend(feedUri, newEntry, GDataRequestType.Insert, data);
686
 
            return CreateAndParseEntry(returnStream, feedUri);
687
 
        }
688
 
        /////////////////////////////////////////////////////////////////////////////
689
 
 
690
 
 
691
 
 
692
 
        /// <summary>
693
 
        /// simple update for media resources
694
 
        /// </summary>
695
 
        /// <param name="uriTarget"></param>
696
 
        /// <param name="input">the stream to send</param>
697
 
        /// <param name="contentType"></param>
698
 
        /// <param name="slugHeader">the value for the slug header, indicating filenaming</param>
699
 
        /// <returns>AtomEntry</returns>
700
 
        public AtomEntry Update(Uri uriTarget, Stream input, string contentType, string slugHeader)
701
 
        {
702
 
            Stream returnStream = StreamSend(uriTarget, input, GDataRequestType.Update, contentType, slugHeader);
703
 
            return CreateAndParseEntry(returnStream, uriTarget);
704
 
        }   
705
 
 
706
 
        /// <summary>
707
 
        /// Simple insert for media resources
708
 
        /// </summary>
709
 
        /// <param name="uriTarget"></param>
710
 
        /// <param name="input"></param>
711
 
        /// <param name="contentType"></param>
712
 
        /// <param name="slugHeader">the value for the slug header, indicating filenaming</param>
713
 
        /// <returns>AtomEntry</returns>
714
 
        public AtomEntry Insert(Uri uriTarget, Stream input, string contentType, string slugHeader)
715
 
        {
716
 
            Stream returnStream = StreamSend(uriTarget, input, GDataRequestType.Insert, contentType, slugHeader);
717
 
            return CreateAndParseEntry(returnStream, uriTarget);
718
 
        }
719
 
 
720
 
 
721
 
        private AtomFeed CreateAndParseFeed(Stream inputStream, Uri uriToUse)
722
 
        {
723
 
            AtomFeed returnFeed = null;
724
 
 
725
 
            if (inputStream != null)
726
 
            {
727
 
                returnFeed = CreateFeed(uriToUse);
728
 
                this.versionInfo.ImprintVersion(returnFeed);
729
 
                try
730
 
                {
731
 
                    returnFeed.NewAtomEntry += new FeedParserEventHandler(this.OnParsedNewEntry); 
732
 
                    returnFeed.NewExtensionElement += new ExtensionElementEventHandler(this.OnNewExtensionElement);
733
 
                    returnFeed.Parse(inputStream, AlternativeFormat.Atom);
734
 
                }
735
 
                finally
736
 
                {
737
 
                    inputStream.Close(); 
738
 
                }
739
 
            }
740
 
 
741
 
            return returnFeed; 
742
 
        }
743
 
 
744
 
        private AtomEntry CreateAndParseEntry(Stream inputStream, Uri uriTarget)
745
 
        {
746
 
            AtomFeed returnFeed = CreateAndParseFeed(inputStream, uriTarget);
747
 
            AtomEntry entry=null; 
748
 
            // there should be ONE entry echoed back. 
749
 
            if (returnFeed != null && returnFeed.Entries.Count > 0)
750
 
            {
751
 
                entry = returnFeed.Entries[0];
752
 
                if (entry != null)
753
 
                {
754
 
                    entry.Service = this;
755
 
                    entry.setFeed(null);
756
 
                }
757
 
            }
758
 
            return entry; 
759
 
        }
760
 
   
761
 
 
762
 
 
763
 
        //////////////////////////////////////////////////////////////////////
764
 
        /// <summary>Inserts an AtomBase entry against a Uri</summary> 
765
 
        /// <param name="feedUri">the uri for the feed this object should be posted against</param> 
766
 
        /// <param name="baseEntry">the entry to be inserted</param> 
767
 
        /// <param name="type">the type of request to create</param> 
768
 
        /// <returns> the response as a stream</returns>
769
 
        //////////////////////////////////////////////////////////////////////
770
 
        public Stream EntrySend(Uri feedUri, AtomEntry baseEntry, GDataRequestType type)
771
 
        {
772
 
            return this.EntrySend(feedUri, baseEntry, type, null); 
773
 
        }
774
 
 
775
 
 
776
 
        //////////////////////////////////////////////////////////////////////
777
 
        /// <summary>Inserts an AtomBase entry against a Uri</summary> 
778
 
        /// <param name="feedUri">the uri for the feed this object should be posted against</param> 
779
 
        /// <param name="baseEntry">the entry to be inserted</param> 
780
 
        /// <param name="type">the type of request to create</param> 
781
 
        /// <param name="data">the async data payload</param>
782
 
        /// <returns> the response as a stream</returns>
783
 
        //////////////////////////////////////////////////////////////////////
784
 
        internal virtual Stream EntrySend(Uri feedUri, AtomBase baseEntry, GDataRequestType type, AsyncSendData data)
785
 
        {
786
 
            Tracing.Assert(feedUri != null, "feedUri should not be null");
787
 
            if (feedUri == null)
788
 
            {
789
 
                throw new ArgumentNullException("feedUri"); 
790
 
            }
791
 
            Tracing.Assert(baseEntry != null, "baseEntry should not be null");
792
 
            if (baseEntry == null)
793
 
            {
794
 
                throw new ArgumentNullException("baseEntry"); 
795
 
            }
796
 
            this.versionInfo.ImprintVersion(baseEntry);
797
 
 
798
 
            IGDataRequest request = this.RequestFactory.CreateRequest(type,feedUri);
799
 
            request.Credentials = this.Credentials;
800
 
 
801
 
            ISupportsEtag eTarget = request as ISupportsEtag;
802
 
            ISupportsEtag eSource = baseEntry as ISupportsEtag;
803
 
            if (eTarget != null && eSource != null)
804
 
            {
805
 
                eTarget.Etag = eSource.Etag;
806
 
            }
807
 
            if (data != null)
808
 
            {
809
 
                GDataGAuthRequest gr = request as GDataGAuthRequest;
810
 
                if (gr != null)
811
 
                {
812
 
                    gr.AsyncData = data;
813
 
                }
814
 
            }
815
 
 
816
 
            Stream outputStream = request.GetRequestStream();
817
 
 
818
 
            baseEntry.SaveToXml(outputStream);
819
 
            request.Execute();
820
 
 
821
 
            outputStream.Close();
822
 
            return request.GetResponseStream();
823
 
        }
824
 
 
825
 
 
826
 
 
827
 
        /// <summary>
828
 
        /// this is a helper function for external utilities. It is not worth
829
 
        /// running the other insert/saves through here, as this would involve
830
 
        /// double buffering/copying of the bytes
831
 
        /// </summary>
832
 
        /// <param name="targetUri"></param>
833
 
        /// <param name="payload"></param>
834
 
        /// <param name="type"></param>
835
 
        /// <returns>Stream</returns>
836
 
        
837
 
        public Stream StringSend(Uri targetUri, String payload, GDataRequestType type)
838
 
        {
839
 
            Tracing.Assert(targetUri != null, "targetUri should not be null");
840
 
            if (targetUri == null)
841
 
            {
842
 
                throw new ArgumentNullException("targetUri"); 
843
 
            }
844
 
            Tracing.Assert(payload != null, "payload should not be null");
845
 
            if (payload == null)
846
 
            {
847
 
                throw new ArgumentNullException("payload"); 
848
 
            }
849
 
 
850
 
            IGDataRequest request = this.RequestFactory.CreateRequest(type,targetUri);
851
 
            request.Credentials = this.Credentials;
852
 
 
853
 
            Stream outputStream = request.GetRequestStream();
854
 
 
855
 
            StreamWriter w = new StreamWriter(outputStream);
856
 
            w.Write(payload);
857
 
            w.Flush();
858
 
       
859
 
            request.Execute();
860
 
 
861
 
            w.Close();
862
 
            return request.GetResponseStream();
863
 
        }
864
 
 
865
 
 
866
 
 
867
 
        /// <summary>
868
 
        /// this is a helper function for to send binary data to a resource
869
 
        /// it is not worth running the other insert/saves through here, as this would involve
870
 
        /// double buffering/copying of the bytes
871
 
        /// </summary>
872
 
        /// <param name="targetUri"></param>
873
 
        /// <param name="inputStream"></param>
874
 
        /// <param name="type"></param>
875
 
        /// <param name="contentType">the contenttype to use in the request, if NULL is passed, factory default is used</param>
876
 
        /// <param name="slugHeader">the slugHeader to use in the request, if NULL is passed, factory default is used</param>
877
 
        /// <returns>Stream</returns>
878
 
        public Stream StreamSend(Uri targetUri, 
879
 
                                 Stream inputStream, 
880
 
                                 GDataRequestType type, 
881
 
                                 string contentType,
882
 
                                 string slugHeader)
883
 
        {
884
 
 
885
 
            return StreamSend(targetUri, inputStream, type, contentType, slugHeader, null, null);
886
 
        }
887
 
 
888
 
        /// <summary>
889
 
        /// this is a helper function for to send binary data to a resource
890
 
        /// it is not worth running the other insert/saves through here, as this would involve
891
 
        /// double buffering/copying of the bytes
892
 
        /// </summary>
893
 
        /// <param name="targetUri"></param>
894
 
        /// <param name="inputStream"></param>
895
 
        /// <param name="type"></param>
896
 
        /// <param name="contentType">the contenttype to use in the request, if NULL is passed, factory default is used</param>
897
 
        /// <param name="slugHeader">the slugHeader to use in the request, if NULL is passed, factory default is used</param>
898
 
        /// <param name="etag">The http etag to pass into the request</param>
899
 
        /// <returns>Stream</returns>
900
 
        public Stream StreamSend(Uri targetUri, 
901
 
                                 Stream inputStream, 
902
 
                                 GDataRequestType type, 
903
 
                                 string contentType,
904
 
                                 string slugHeader,
905
 
                                 string etag)
906
 
        {
907
 
 
908
 
            return StreamSend(targetUri, inputStream, type, contentType, slugHeader, etag, null);
909
 
        }
910
 
 
911
 
 
912
 
        /// <summary>
913
 
        /// this is a helper function for to send binary data to a resource
914
 
        /// it is not worth running the other insert/saves through here, as this would involve
915
 
        /// double buffering/copying of the bytes
916
 
        /// </summary>
917
 
        /// <param name="targetUri"></param>
918
 
        /// <param name="inputStream"></param>
919
 
        /// <param name="type"></param>
920
 
        /// <param name="contentType">the contenttype to use in the request, if NULL is passed, factory default is used</param>
921
 
        /// <param name="slugHeader">the slugHeader to use in the request, if NULL is passed, factory default is used</param>
922
 
        /// <param name="etag">The http etag to pass into the request</param>
923
 
        /// <param name="data">The async data needed for notifications</param>
924
 
        /// <returns>Stream from the server response. You should close this stream explicitly.</returns>
925
 
        private Stream StreamSend(Uri targetUri, 
926
 
                                 Stream inputStream, 
927
 
                                 GDataRequestType type, 
928
 
                                 string contentType,
929
 
                                 string slugHeader,
930
 
                                 string etag,
931
 
                                 AsyncSendData data)
932
 
        {
933
 
            Tracing.Assert(targetUri != null, "targetUri should not be null");
934
 
            if (targetUri == null)
935
 
            {
936
 
                throw new ArgumentNullException("targetUri"); 
937
 
            }
938
 
            if (inputStream == null)
939
 
            {
940
 
                Tracing.Assert(inputStream != null, "payload should not be null");
941
 
                throw new ArgumentNullException("inputStream"); 
942
 
            }
943
 
            if (type != GDataRequestType.Insert && type != GDataRequestType.Update)
944
 
            {
945
 
                Tracing.Assert(type != GDataRequestType.Insert && type != GDataRequestType.Update,"type needs to be insert or update");
946
 
                throw new ArgumentNullException("type"); 
947
 
            }
948
 
 
949
 
 
950
 
            IGDataRequest request = this.RequestFactory.CreateRequest(type,targetUri);
951
 
            request.Credentials = this.Credentials;
952
 
 
953
 
            if (data != null)
954
 
            {
955
 
                GDataGAuthRequest gr = request as GDataGAuthRequest;
956
 
                if (gr != null)
957
 
                {
958
 
                    gr.AsyncData = data;
959
 
                }
960
 
            }
961
 
 
962
 
            // set the contenttype of the request
963
 
            if (contentType != null)
964
 
            {
965
 
                GDataRequest r = request as GDataRequest;
966
 
                if (r != null)
967
 
                {
968
 
                    r.ContentType = contentType;
969
 
                }
970
 
            }
971
 
 
972
 
            if (slugHeader != null)
973
 
            {
974
 
                GDataRequest r = request as GDataRequest;
975
 
                if (r != null)
976
 
                {
977
 
                    r.Slug = slugHeader;
978
 
                }
979
 
            }
980
 
 
981
 
            if (etag != null)
982
 
            {
983
 
                ISupportsEtag ise = request as ISupportsEtag;
984
 
                if (ise != null)
985
 
                {
986
 
                    ise.Etag = etag;
987
 
                }
988
 
            }
989
 
 
990
 
            Stream outputStream = request.GetRequestStream();
991
 
 
992
 
            WriteInputStreamToRequest(inputStream, outputStream);
993
 
 
994
 
            request.Execute();
995
 
            outputStream.Close();
996
 
            return new GDataReturnStream(request);
997
 
        }
998
 
 
999
 
        /// <summary>
1000
 
        /// write the current stream to an output stream
1001
 
        /// this is primarily used to write data to the 
1002
 
        /// request stream
1003
 
        /// </summary>
1004
 
        /// <param name="input"></param>
1005
 
        /// <param name="output"></param>
1006
 
        protected void WriteInputStreamToRequest(Stream input, Stream output)
1007
 
        {
1008
 
            BinaryWriter w = new BinaryWriter(output);
1009
 
            const int size = 4096;
1010
 
            byte[] bytes = new byte[4096];
1011
 
            int numBytes;
1012
 
 
1013
 
            while((numBytes = input.Read(bytes, 0, size)) > 0)
1014
 
            {
1015
 
                w.Write(bytes, 0, numBytes);
1016
 
            }
1017
 
            w.Flush();
1018
 
        }
1019
 
 
1020
 
 
1021
 
        //////////////////////////////////////////////////////////////////////
1022
 
        /// <summary>creates a new feed instance to be returned by
1023
 
        /// Batch(), Query() and other operations
1024
 
        ///
1025
 
        /// Subclasses can supply their own feed implementation by
1026
 
        /// overriding this method.
1027
 
        /// </summary>
1028
 
        //////////////////////////////////////////////////////////////////////
1029
 
        protected virtual AtomFeed CreateFeed(Uri uriToUse)
1030
 
        {
1031
 
            ServiceEventArgs args = null;
1032
 
            AtomFeed feed = null;
1033
 
 
1034
 
            if (this.NewFeed != null)
1035
 
            {
1036
 
                args = new ServiceEventArgs(uriToUse, this);
1037
 
                this.NewFeed(this, args);
1038
 
            }
1039
 
 
1040
 
            if (args != null)
1041
 
            {
1042
 
                feed = args.Feed;
1043
 
            }
1044
 
 
1045
 
            if (feed == null)
1046
 
            {
1047
 
                feed = new AtomFeed(uriToUse, this);
1048
 
            }
1049
 
 
1050
 
            return feed;
1051
 
        }
1052
 
 
1053
 
 
1054
 
        /// <summary>
1055
 
        /// takes a given feed, and does a batch post of that feed
1056
 
        /// against the batchUri parameter. If that one is NULL 
1057
 
        /// it will try to use the batch link URI in the feed
1058
 
        /// </summary>
1059
 
        /// <param name="feed">the feed to post</param>
1060
 
        /// <param name="batchUri">the URI to user</param>
1061
 
        /// <returns>the returned AtomFeed</returns>
1062
 
        public AtomFeed Batch(AtomFeed feed, Uri batchUri) 
1063
 
        {
1064
 
            return Batch(feed, batchUri, null);
1065
 
        }
1066
 
        //////////////////////////////////////////////////////////////////////
1067
 
 
1068
 
 
1069
 
 
1070
 
        /// <summary>
1071
 
        /// takes a given feed, and does a batch post of that feed
1072
 
        /// against the batchUri parameter. If that one is NULL 
1073
 
        /// it will try to use the batch link URI in the feed
1074
 
        /// </summary>
1075
 
        /// <param name="feed">the feed to post</param>
1076
 
        /// <param name="batchUri">the URI to user</param>
1077
 
        /// <param name="data">The async data payload</param>
1078
 
        /// <returns>the returned AtomFeed</returns>
1079
 
        private AtomFeed Batch(AtomFeed feed, Uri batchUri, AsyncSendData data) 
1080
 
        {
1081
 
            Uri uriToUse = batchUri;
1082
 
            if (feed == null)
1083
 
            {
1084
 
                throw new ArgumentNullException("feed");
1085
 
            }
1086
 
 
1087
 
            if (uriToUse == null)
1088
 
            {
1089
 
                uriToUse = feed.Batch == null ? null : new Uri(feed.Batch); 
1090
 
            }
1091
 
 
1092
 
            if (uriToUse == null)
1093
 
            {
1094
 
                throw new ArgumentNullException("batchUri"); 
1095
 
            }
1096
 
 
1097
 
            Tracing.Assert(feed != null, "feed should not be null");
1098
 
            if (feed == null)
1099
 
            {
1100
 
                throw new ArgumentNullException("feed"); 
1101
 
            }
1102
 
 
1103
 
            if (feed.BatchData == null) 
1104
 
            {
1105
 
                // setting this will make the feed output the namespace, instead of each entry
1106
 
                feed.BatchData = new GDataBatchFeedData(); 
1107
 
            }  
1108
 
            Stream returnStream = EntrySend(uriToUse, feed, GDataRequestType.Batch, data);
1109
 
            return CreateAndParseFeed(returnStream, uriToUse);;  
1110
 
        }
1111
 
        //////////////////////////////////////////////////////////////////////
1112
 
 
1113
 
 
1114
 
 
1115
 
    
1116
 
        //////////////////////////////////////////////////////////////////////
1117
 
        /// <summary>deletes an Atom entry object</summary> 
1118
 
        /// <param name="entry"> </param>
1119
 
        //////////////////////////////////////////////////////////////////////
1120
 
        public void Delete(AtomEntry entry)
1121
 
        {
1122
 
            Tracing.Assert(entry != null, "entry should not be null");
1123
 
            string eTag = null;
1124
 
 
1125
 
            if (entry == null)
1126
 
            {
1127
 
                throw new ArgumentNullException("entry"); 
1128
 
            }
1129
 
 
1130
 
            if (entry.ReadOnly == true)
1131
 
            {
1132
 
                throw new GDataRequestException("Can not update a read-only entry"); 
1133
 
            }
1134
 
 
1135
 
            Tracing.Assert(entry.EditUri != null, "Entry should have a valid edit URI"); 
1136
 
 
1137
 
            ISupportsEtag eSource = entry as ISupportsEtag;
1138
 
 
1139
 
            if (eSource != null)
1140
 
            {
1141
 
                eTag = eSource.Etag;
1142
 
            }
1143
 
 
1144
 
            if (entry.EditUri != null)
1145
 
            {
1146
 
                Delete(new Uri(entry.EditUri.ToString()), eTag);
1147
 
            }
1148
 
            else
1149
 
            {
1150
 
                throw new GDataRequestException("Invalid Entry object (no edit uri) to call Delete on"); 
1151
 
            }
1152
 
        }
1153
 
        /////////////////////////////////////////////////////////////////////////////
1154
 
 
1155
 
        //////////////////////////////////////////////////////////////////////
1156
 
        ///<summary>Deletes an Atom entry when given a Uri</summary>
1157
 
        ///<param name="uriTarget">The target Uri to call http delete against</param>
1158
 
        /////////////////////////////////////////////////////////////////////
1159
 
        public void Delete(Uri uriTarget)
1160
 
        {
1161
 
            Delete(uriTarget, null);
1162
 
        }   
1163
 
        //////////////////////////////////////////////////////////////////////
1164
 
 
1165
 
 
1166
 
        //////////////////////////////////////////////////////////////////////
1167
 
        ///<summary>Deletes an Atom entry when given a Uri</summary>
1168
 
        ///<param name="uriTarget">The target Uri to call http delete against</param>
1169
 
        ///<param name="eTag">The eTag of the item to delete. This parameter is used for strong
1170
 
        /// concurrency support in protocol version 2 and up</param>
1171
 
        /////////////////////////////////////////////////////////////////////
1172
 
        public void Delete(Uri uriTarget, string eTag)
1173
 
        {
1174
 
            Tracing.Assert(uriTarget != null, "uri should not be null");
1175
 
            if (uriTarget == null)
1176
 
            {
1177
 
                throw new ArgumentNullException("uriTarget");
1178
 
            }
1179
 
 
1180
 
            Tracing.TraceMsg("Deleting entry: " + uriTarget.ToString());
1181
 
            IGDataRequest request = RequestFactory.CreateRequest(GDataRequestType.Delete, uriTarget);
1182
 
 
1183
 
            ISupportsEtag eTarget = request as ISupportsEtag;
1184
 
            if (eTarget != null && eTag != null)
1185
 
            {
1186
 
                eTarget.Etag = eTag;
1187
 
            }
1188
 
 
1189
 
            request.Credentials = Credentials;
1190
 
            request.Execute();
1191
 
            IDisposable disp = request as IDisposable;
1192
 
            disp.Dispose();
1193
 
        }   
1194
 
        //////////////////////////////////////////////////////////////////////
1195
 
 
1196
 
 
1197
 
        //////////////////////////////////////////////////////////////////////
1198
 
        /// <summary>eventchaining. We catch this by the baseFeedParsers, which 
1199
 
        /// would not do anything with the gathered data. We pass the event up
1200
 
        /// to the user</summary> 
1201
 
        /// <param name="sender"> the object which send the event</param>
1202
 
        /// <param name="e">FeedParserEventArguments, holds the feedentry</param> 
1203
 
        /// <returns> </returns>
1204
 
        //////////////////////////////////////////////////////////////////////
1205
 
        protected void OnParsedNewEntry(object sender, FeedParserEventArgs e)
1206
 
        {
1207
 
            if (e == null)
1208
 
            {
1209
 
                throw new ArgumentNullException("e"); 
1210
 
            }
1211
 
            if (this.NewAtomEntry != null)
1212
 
            {
1213
 
                // just forward it upstream, if hooked
1214
 
                Tracing.TraceMsg("\t calling event dispatcher"); 
1215
 
                this.NewAtomEntry(this, e);
1216
 
            }
1217
 
        }
1218
 
        /////////////////////////////////////////////////////////////////////////////
1219
 
 
1220
 
 
1221
 
        //////////////////////////////////////////////////////////////////////
1222
 
        /// <summary>eventchaining. We catch this by the baseFeedParsers, which 
1223
 
        /// would not do anything with the gathered data. We pass the event up
1224
 
        /// to the user, and if he did not dicscard it, we add the entry to our
1225
 
        /// collection</summary> 
1226
 
        /// <param name="sender"> the object which send the event</param>
1227
 
        /// <param name="e">FeedParserEventArguments, holds the feedentry</param> 
1228
 
        /// <returns> </returns>
1229
 
        //////////////////////////////////////////////////////////////////////
1230
 
        protected void OnNewExtensionElement(object sender, ExtensionElementEventArgs e)
1231
 
        {
1232
 
            // by default, if our event chain is not hooked, the underlying parser will add it
1233
 
            Tracing.TraceCall("received new extension element notification");
1234
 
            Tracing.Assert(e != null, "e should not be null");
1235
 
            if (e == null)
1236
 
            {
1237
 
                throw new ArgumentNullException("e"); 
1238
 
            }
1239
 
            if (this.NewExtensionElement != null)
1240
 
            {
1241
 
                Tracing.TraceMsg("\t calling event dispatcher"); 
1242
 
                this.NewExtensionElement(this, e);
1243
 
            }
1244
 
        }
1245
 
        /////////////////////////////////////////////////////////////////////////////
1246
 
 
1247
 
 
1248
 
    }
1249
 
    /////////////////////////////////////////////////////////////////////////////
1250
 
 
1251
 
    /// <summary>
1252
 
    /// used to cover a return stream and add some additional data to it. 
1253
 
    /// </summary>
1254
 
    public class GDataReturnStream : Stream, ISupportsEtag
1255
 
    {
1256
 
        private string etag;
1257
 
        private Stream innerStream;
1258
 
 
1259
 
        /// <summary>
1260
 
        /// default constructor based on a gdatarequest object
1261
 
        /// </summary>
1262
 
        /// <param name="r"></param>
1263
 
        public GDataReturnStream(IGDataRequest r)
1264
 
        {
1265
 
            this.innerStream = r.GetResponseStream();
1266
 
            ISupportsEtag ise = r as ISupportsEtag;
1267
 
            if (ise != null)
1268
 
            {
1269
 
                this.etag = ise.Etag;
1270
 
            }
1271
 
        }
1272
 
 
1273
 
        /// <summary>
1274
 
        /// default override, delegates to the real stream
1275
 
        /// </summary>
1276
 
        public override bool CanRead
1277
 
        {
1278
 
            get { return this.innerStream.CanRead; }
1279
 
        }
1280
 
 
1281
 
        /// <summary>
1282
 
        /// default override, delegates to the real stream
1283
 
        /// </summary>
1284
 
        public override bool CanSeek
1285
 
        {
1286
 
            get { return this.innerStream.CanSeek; }
1287
 
        }
1288
 
 
1289
 
        /// <summary>
1290
 
        /// default override, delegates to the real stream
1291
 
        /// </summary>
1292
 
        public override bool CanTimeout
1293
 
        {
1294
 
            get { return this.innerStream.CanTimeout;}
1295
 
        }
1296
 
 
1297
 
        /// <summary>
1298
 
        /// default override, delegates to the real stream
1299
 
        /// </summary>
1300
 
        public override void Close()
1301
 
        {
1302
 
            this.innerStream.Close();
1303
 
        }
1304
 
 
1305
 
        /// <summary>
1306
 
        /// default override, delegates to the real stream
1307
 
        /// </summary>
1308
 
        public override bool CanWrite
1309
 
        {
1310
 
            get { return this.innerStream.CanWrite; }
1311
 
        }
1312
 
 
1313
 
        /// <summary>
1314
 
        /// default override, delegates to the real stream
1315
 
        /// </summary>
1316
 
        public override long Length
1317
 
        {
1318
 
            get { return this.innerStream.Length; }
1319
 
        }
1320
 
 
1321
 
        /// <summary>
1322
 
        /// default override, delegates to the real stream
1323
 
        /// </summary>
1324
 
        public override long Position
1325
 
        {
1326
 
            get
1327
 
            {
1328
 
                return this.innerStream.Position;
1329
 
            }
1330
 
            set
1331
 
            {
1332
 
                this.innerStream.Position = value;
1333
 
            }
1334
 
        }
1335
 
 
1336
 
        /// <summary>
1337
 
        /// default override, delegates to the real stream
1338
 
        /// </summary>
1339
 
        public override void Flush()
1340
 
        {
1341
 
            this.innerStream.Flush();
1342
 
        }
1343
 
 
1344
 
        /// <summary>
1345
 
        /// default override, delegates to the real stream
1346
 
        /// </summary>
1347
 
        /// <param name="offset"></param>
1348
 
        /// <param name="origin"></param>
1349
 
        public override long Seek(long offset, SeekOrigin origin)
1350
 
        {
1351
 
            return this.innerStream.Seek(offset, origin);
1352
 
        }
1353
 
 
1354
 
        /// <summary>
1355
 
        /// default override, delegates to the real stream
1356
 
        /// </summary>
1357
 
        /// <param name="value"></param>
1358
 
        public override void SetLength(long value)
1359
 
        {
1360
 
            this.innerStream.SetLength(value);
1361
 
        }
1362
 
 
1363
 
        /// <summary>
1364
 
        /// default override, delegates to the real stream
1365
 
        /// </summary>
1366
 
        /// <param name="buffer"></param>
1367
 
        /// <param name="count"/>
1368
 
        /// <param name="offset"/>
1369
 
        public override int Read(byte[] buffer, int offset, int count)
1370
 
        {
1371
 
            return this.innerStream.Read(buffer, offset, count);           
1372
 
        }
1373
 
 
1374
 
        /// <summary>
1375
 
        /// default override, delegates to the real stream
1376
 
        /// </summary>
1377
 
        /// <param name="buffer"/>
1378
 
        /// <param name="count"/>
1379
 
        /// <param name="offset"/>
1380
 
        public override void Write(byte[] buffer, int offset, int count)
1381
 
        {
1382
 
            this.innerStream.Write(buffer, offset, count);
1383
 
        }
1384
 
 
1385
 
        /// <summary>
1386
 
        /// implements the etag interface
1387
 
        /// </summary>
1388
 
        public string Etag
1389
 
        {
1390
 
            get { return this.etag; }
1391
 
            set { this.etag = value; }
1392
 
        }
1393
 
    }
1394
 
1395
 
/////////////////////////////////////////////////////////////////////////////