[libgdata] documents: Switch to a stream-based upload API



commit c405bb66b00a72a3882452ff11b29aac6f2a0e4e
Author: Philip Withnall <philip tecnocode co uk>
Date:   Thu Dec 9 01:31:10 2010 +0000

    documents: Switch to a stream-based upload API
    
    For similar reasons as the switch to a stream-based download API, it makes
    sense to switch to a stream-based upload API. This gives us asynchronous
    support for free.
    
    The test suite has been updated appropriately.
    
    The following API has been broken:
     â?¢ gdata_documents_service_upload_document()
     â?¢ gdata_documents_service_update_document()
    
    The following API has been added:
     â?¢ gdata_documents_service_finish_upload()

 docs/reference/gdata-sections.txt                  |    1 +
 gdata/gdata.symbols                                |    1 +
 gdata/services/documents/gdata-documents-service.c |  253 +++++------
 gdata/services/documents/gdata-documents-service.h |   14 +-
 gdata/tests/documents.c                            |  439 +++++++++++++++++---
 5 files changed, 505 insertions(+), 203 deletions(-)
---
diff --git a/docs/reference/gdata-sections.txt b/docs/reference/gdata-sections.txt
index 382ee15..c80de81 100644
--- a/docs/reference/gdata-sections.txt
+++ b/docs/reference/gdata-sections.txt
@@ -1716,6 +1716,7 @@ gdata_documents_service_query_documents
 gdata_documents_service_query_documents_async
 gdata_documents_service_upload_document
 gdata_documents_service_update_document
+gdata_documents_service_finish_upload
 gdata_documents_service_move_document_to_folder
 gdata_documents_service_remove_document_from_folder
 gdata_documents_service_get_upload_uri
diff --git a/gdata/gdata.symbols b/gdata/gdata.symbols
index ae97d82..018352d 100644
--- a/gdata/gdata.symbols
+++ b/gdata/gdata.symbols
@@ -851,3 +851,4 @@ gdata_youtube_service_upload_video_async
 gdata_youtube_service_upload_video_finish
 gdata_picasaweb_service_insert_album_async
 gdata_picasaweb_service_query_files_async
+gdata_documents_service_finish_upload
diff --git a/gdata/services/documents/gdata-documents-service.c b/gdata/services/documents/gdata-documents-service.c
index 4040abc..06e39a3 100644
--- a/gdata/services/documents/gdata-documents-service.c
+++ b/gdata/services/documents/gdata-documents-service.c
@@ -62,8 +62,6 @@ static void gdata_documents_service_dispose (GObject *object);
 static void gdata_documents_service_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
 static void notify_authenticated_cb (GObject *service, GParamSpec *pspec, GObject *self);
 static void notify_proxy_uri_cb (GObject *service, GParamSpec *pspec, GObject *self);
-static GDataDocumentsEntry *upload_update_document (GDataDocumentsService *self, GDataDocumentsEntry *document, GFile *document_file,
-                                                    const gchar *method, const gchar *upload_uri, GCancellable *cancellable, GError **error);
 
 struct _GDataDocumentsServicePrivate {
 	GDataService *spreadsheet_service;
@@ -291,141 +289,59 @@ notify_proxy_uri_cb (GObject *service, GParamSpec *pspec, GObject *self)
 	gdata_service_set_proxy_uri (GDATA_DOCUMENTS_SERVICE (self)->priv->spreadsheet_service, proxy_uri);
 }
 
-static GDataDocumentsEntry *
-upload_update_document (GDataDocumentsService *self, GDataDocumentsEntry *document, GFile *document_file, const gchar *method,
-                        const gchar *upload_uri, GCancellable *cancellable, GError **error)
+static GDataUploadStream *
+upload_update_document (GDataDocumentsService *self, GDataDocumentsEntry *document, const gchar *slug, const gchar *content_type, const gchar *method,
+                        const gchar *upload_uri)
 {
-	GDataDocumentsEntry *new_entry;
-	GOutputStream *output_stream;
-	GInputStream *input_stream;
-	const gchar *slug = NULL, *content_type = NULL, *response_body;
-	gssize response_length;
-	GFileInfo *file_info = NULL;
-	GType new_document_type = G_TYPE_INVALID;
-	GError *child_error = NULL;
-
-	/* Get some information about the file we're uploading */
-	if (document_file != NULL) {
-		/* Get the slug and content type */
-		file_info = g_file_query_info (document_file, "standard::display-name,standard::content-type", G_FILE_QUERY_INFO_NONE, NULL, error);
-		if (file_info == NULL)
-			return NULL;
-
-		slug = g_file_info_get_display_name (file_info);
-		content_type = g_file_info_get_content_type (file_info);
-
-		/* Corrects a bug on spreadsheet content types handling
-		 * The content type for ODF spreadsheets is "application/vnd.oasis.opendocument.spreadsheet" for my ODF spreadsheet;
-		 * but Google Documents' spreadsheet service is waiting for "application/x-vnd.oasis.opendocument.spreadsheet"
-		 * and nothing else.
-		 * Bug filed with Google: http://code.google.com/p/gdata-issues/issues/detail?id=1127 */
-		if (strcmp (content_type, "application/vnd.oasis.opendocument.spreadsheet") == 0)
-			content_type = "application/x-vnd.oasis.opendocument.spreadsheet";
-
-		if (document == NULL) {
-			/* Get the document type of the document which is being uploaded */
-			if (strcmp (content_type, "application/x-vnd.oasis.opendocument.spreadsheet") == 0 ||
-			    strcmp (content_type, "text/tab-separated-values") == 0 ||
-			    strcmp (content_type, "application/x-vnd.oasis.opendocument.spreadsheet") == 0 ||
-			    strcmp (content_type, "application/vnd.ms-excel") == 0) {
-				new_document_type = GDATA_TYPE_DOCUMENTS_SPREADSHEET;
-			} else if (strcmp (content_type, "application/msword") == 0 ||
-			           strcmp (content_type, "application/vnd.oasis.opendocument.text") == 0 ||
-			           strcmp (content_type, "application/rtf") == 0 ||
-			           strcmp (content_type, "text/html") == 0 ||
-			           strcmp (content_type, "application/vnd.sun.xml.writer") == 0 ||
-			           strcmp (content_type, "text/plain") == 0) {
-				new_document_type = GDATA_TYPE_DOCUMENTS_TEXT;
-			} else if (strcmp (content_type, "application/vnd.ms-powerpoint") == 0) {
-				new_document_type = GDATA_TYPE_DOCUMENTS_PRESENTATION;
-			} else {
-				g_set_error_literal (error, GDATA_DOCUMENTS_SERVICE_ERROR, GDATA_DOCUMENTS_SERVICE_ERROR_INVALID_CONTENT_TYPE,
-				                     _("The supplied document had an invalid content type."));
-				if (file_info != NULL)
-					g_object_unref (file_info);
-				return NULL;
-			}
-		}
-	}
-
-	/* Determine the type of the document we're uploading */
-	if (document != NULL)
-		new_document_type = G_OBJECT_TYPE (document);
+	/* Corrects a bug on spreadsheet content types handling
+	 * The content type for ODF spreadsheets is "application/vnd.oasis.opendocument.spreadsheet" for my ODF spreadsheet;
+	 * but Google Documents' spreadsheet service is waiting for "application/x-vnd.oasis.opendocument.spreadsheet"
+	 * and nothing else.
+	 * Bug filed with Google: http://code.google.com/p/gdata-issues/issues/detail?id=1127 */
+	if (strcmp (content_type, "application/vnd.oasis.opendocument.spreadsheet") == 0)
+		content_type = "application/x-vnd.oasis.opendocument.spreadsheet";
 
 	/* We need streaming file I/O: GDataUploadStream */
-	output_stream = gdata_upload_stream_new (GDATA_SERVICE (self), method, upload_uri, GDATA_ENTRY (document), slug, content_type);
-
-	if (file_info != NULL)
-		g_object_unref (file_info);
-	if (output_stream == NULL)
-		return NULL;
-
-	/* Open the document file for reading and pipe it to the upload stream */
-	input_stream = G_INPUT_STREAM (g_file_read (document_file, cancellable, error));
-	if (input_stream == NULL) {
-		g_object_unref (output_stream);
-		return NULL;
-	}
-
-	g_output_stream_splice (output_stream, input_stream, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
-	                        cancellable, &child_error);
-
-	g_object_unref (input_stream);
-	if (child_error != NULL) {
-		g_object_unref (output_stream);
-		g_propagate_error (error, child_error);
-		return NULL;
-	}
-
-	/* Get and parse the response from the server */
-	response_body = gdata_upload_stream_get_response (GDATA_UPLOAD_STREAM (output_stream), &response_length);
-	g_assert (response_body != NULL && response_length > 0);
-
-	new_entry = GDATA_DOCUMENTS_ENTRY (gdata_parsable_new_from_xml (new_document_type, response_body, (gint) response_length, error));
-	g_object_unref (output_stream);
-
-	return new_entry;
+	return GDATA_UPLOAD_STREAM (gdata_upload_stream_new (GDATA_SERVICE (self), method, upload_uri, GDATA_ENTRY (document), slug, content_type));
 }
 
 /**
  * gdata_documents_service_upload_document:
  * @self: an authenticated #GDataDocumentsService
  * @document: (allow-none): the #GDataDocumentsEntry to insert, or %NULL
- * @document_file: (allow-none): the document to upload, or %NULL
+ * @slug: the filename to give to the uploaded document
+ * @content_type: the content type of the uploaded data
  * @folder: (allow-none): the folder to which the document should be uploaded, or %NULL
- * @cancellable: optional #GCancellable object, or %NULL
  * @error: a #GError, or %NULL
  *
- * Uploads a document to Google Documents, using the properties from @document and the document file pointed to by @document_file.
- *
- * If @document is %NULL, only the document file will be uploaded. The new document entry will be named after the document file's name,
- * and will have default metadata.
+ * Uploads a document to Google Documents, using the properties from @document and the document data written to the resulting #GDataUploadStream. If
+ * the document data does not need to be provided at the moment, just the metadata, use gdata_service_insert_entry() instead (e.g. in the case of
+ * creating a new, empty file to be edited at a later date).
  *
- * If @document_file is %NULL, only the document metadata will be uploaded. A blank document file will be created with the name
- * <literal>new document</literal> and the specified metadata. @document and @document_file cannot both be %NULL, but can both have values.
+ * If @document is %NULL, only the document data will be uploaded. The new document entry will be named using @slug, and will have default metadata.
  *
- * The updated @document_entry will be returned on success, containing updated metadata.
+ * The stream returned by this function should be written to using the standard #GOutputStream methods, asychronously or synchronously. Once the stream
+ * is closed (using g_output_stream_close()), gdata_documents_service_finish_upload() should be called on it to parse and return the updated
+ * #GDataDocumentEntry for the document. This must be done, as @document isn't updated in-place.
  *
- * If there is a problem reading @document_file, an error from g_file_load_contents() or g_file_query_info() will be returned. Other errors from
- * #GDataServiceError can be returned for other exceptional conditions, as determined by the server.
+ * Any upload errors will be thrown by the stream methods, and may come from the #GDataServiceError domain.
  *
- * Return value: (transfer full): an updated #GDataDocumentsEntry, or %NULL; unref with g_object_unref()
+ * Return value: (transfer full): a #GDataUploadStream to write the document data to, or %NULL; unref with g_object_unref()
  *
- * Since: 0.4.0
+ * Since: 0.8.0
  **/
-GDataDocumentsEntry *
-gdata_documents_service_upload_document (GDataDocumentsService *self, GDataDocumentsEntry *document, GFile *document_file,
-                                         GDataDocumentsFolder *folder, GCancellable *cancellable, GError **error)
+GDataUploadStream *
+gdata_documents_service_upload_document (GDataDocumentsService *self, GDataDocumentsEntry *document, const gchar *slug, const gchar *content_type,
+                                         GDataDocumentsFolder *folder, GError **error)
 {
-	GDataDocumentsEntry *new_document;
+	GDataUploadStream *upload_stream;
 	gchar *upload_uri;
 
 	g_return_val_if_fail (GDATA_IS_DOCUMENTS_SERVICE (self), NULL);
 	g_return_val_if_fail (document == NULL || GDATA_IS_DOCUMENTS_ENTRY (document), NULL);
-	g_return_val_if_fail (document_file == NULL || G_IS_FILE (document_file), NULL);
-	g_return_val_if_fail (document != NULL || document_file != NULL, NULL);
+	g_return_val_if_fail (slug != NULL && *slug != '\0', NULL);
+	g_return_val_if_fail (content_type != NULL && *content_type != '\0', NULL);
 	g_return_val_if_fail (folder == NULL || GDATA_IS_DOCUMENTS_FOLDER (folder), NULL);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
 	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	if (gdata_service_is_authenticated (GDATA_SERVICE (self)) == FALSE) {
@@ -441,48 +357,45 @@ gdata_documents_service_upload_document (GDataDocumentsService *self, GDataDocum
 	}
 
 	upload_uri = gdata_documents_service_get_upload_uri (folder);
-
-	if (document_file == NULL) {
-		new_document = GDATA_DOCUMENTS_ENTRY (gdata_service_insert_entry (GDATA_SERVICE (self), upload_uri, GDATA_ENTRY (document),
-		                                                                  cancellable, error));
-	} else {
-		new_document = upload_update_document (self, document, document_file, SOUP_METHOD_POST, upload_uri, cancellable, error);
-	}
+	upload_stream = upload_update_document (self, document, slug, content_type, SOUP_METHOD_POST, upload_uri);
 	g_free (upload_uri);
 
-	return new_document;
+	return upload_stream;
 }
 
 /**
  * gdata_documents_service_update_document:
  * @self: a #GDataDocumentsService
  * @document: the #GDataDocumentsEntry to update
- * @document_file: (allow-none): the local document file containing the new data, or %NULL
- * @cancellable: optional #GCancellable object, or %NULL
+ * @slug: the filename to give to the uploaded document
+ * @content_type: the content type of the uploaded data
  * @error: a #GError, or %NULL
  *
- * Update the document using the properties from @document and the document file pointed to by @document_file. If the document file does not
- * need to be changed, @document_file can be %NULL.
+ * Update the document using the properties from @document and the document data written to the resulting #GDataUploadStream. If the document data does
+ * not need to be changed, just the metadata, use gdata_service_update_entry() instead.
  *
- * If there is a problem reading @document_file, an error from g_file_load_contents() or g_file_query_info() will be returned. Other errors from
- * #GDataServiceError can be returned for other exceptional conditions, as determined by the server.
+ * The stream returned by this function should be written to using the standard #GOutputStream methods, asychronously or synchronously. Once the stream
+ * is closed (using g_output_stream_close()), gdata_documents_service_finish_upload() should be called on it to parse and return the updated
+ * #GDataDocumentEntry for the document. This must be done, as @document isn't updated in-place.
  *
- * For more details, see gdata_service_insert_entry().
+ * Any upload errors will be thrown by the stream methods, and may come from the #GDataServiceError domain.
  *
- * Return value: (transfer full): an updated #GDataDocumentsEntry, or %NULL; unref with g_object_unref()
+ * For more information, see gdata_service_update_entry().
  *
- * Since: 0.4.0
+ * Return value: (transfer full): a #GDataUploadStream to write the document data to; unref with g_object_unref()
+ *
+ * Since: 0.8.0
  **/
-GDataDocumentsEntry *
-gdata_documents_service_update_document (GDataDocumentsService *self, GDataDocumentsEntry *document, GFile *document_file,
-                                         GCancellable *cancellable, GError **error)
+GDataUploadStream *
+gdata_documents_service_update_document (GDataDocumentsService *self, GDataDocumentsEntry *document, const gchar *slug, const gchar *content_type,
+                                         GError **error)
 {
 	GDataLink *update_link;
 
 	g_return_val_if_fail (GDATA_IS_DOCUMENTS_SERVICE (self), NULL);
 	g_return_val_if_fail (GDATA_IS_DOCUMENTS_ENTRY (document), NULL);
-	g_return_val_if_fail (document_file == NULL || G_IS_FILE (document_file), NULL);
-	g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+	g_return_val_if_fail (slug != NULL && *slug != '\0', NULL);
+	g_return_val_if_fail (content_type != NULL && *content_type != '\0', NULL);
 	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
 	if (gdata_service_is_authenticated (GDATA_SERVICE (self)) == FALSE) {
@@ -491,13 +404,75 @@ gdata_documents_service_update_document (GDataDocumentsService *self, GDataDocum
 		return NULL;
 	}
 
-	if (document_file == NULL)
-		return GDATA_DOCUMENTS_ENTRY (gdata_service_update_entry (GDATA_SERVICE (self), GDATA_ENTRY (document), cancellable, error));
-
 	update_link = gdata_entry_look_up_link (GDATA_ENTRY (document), GDATA_LINK_EDIT_MEDIA);
 	g_assert (update_link != NULL);
 
-	return upload_update_document (self, document, document_file, SOUP_METHOD_PUT, gdata_link_get_uri (update_link), cancellable, error);
+	return upload_update_document (self, document, slug, content_type, SOUP_METHOD_PUT, gdata_link_get_uri (update_link));
+}
+
+/**
+ * gdata_documents_service_finish_upload:
+ * @self: a #GDataDocumentsService
+ * @upload_stream: the #GDataUploadStream from the operation
+ * @error: a #GError, or %NULL
+ *
+ * Finish off a document upload or update operation started by gdata_documents_service_upload_document() or gdata_documents_service_update_document(),
+ * parsing the result and returning the new or updated #GDataDocumentsEntry.
+ *
+ * If an error occurred during the upload or update operation, it will have been returned during the operation (e.g. by g_output_stream_splice() or one
+ * of the other stream methods). In such a case, %NULL will be returned but @error will remain unset. @error is only set in the case that the server
+ * indicates that the operation was successful, but an error is encountered in parsing the result sent by the server.
+ *
+ * In the case that no #GDataDocumentsEntry was passed (to gdata_documents_service_upload_document() or gdata_documents_service_update_document()) when
+ * starting the operation, %GDATA_DOCUMENTS_SERVICE_ERROR_INVALID_CONTENT_TYPE will be thrown in @error if the content type of the uploaded data
+ * could not be mapped to a document type with which to interpret the response from the server.
+ *
+ * Return value: (transfer full): the new or updated #GDataDocumentsEntry, or %NULL; unref with g_object_unref()
+ *
+ * Since: 0.8.0
+ */
+GDataDocumentsEntry *
+gdata_documents_service_finish_upload (GDataDocumentsService *self, GDataUploadStream *upload_stream, GError **error)
+{
+	const gchar *response_body, *content_type;
+	gssize response_length;
+	GDataEntry *entry;
+	GType new_document_type = G_TYPE_INVALID;
+
+	/* Determine the type of the document we've uploaded */
+	entry = gdata_upload_stream_get_entry (upload_stream);
+	content_type = gdata_upload_stream_get_content_type (upload_stream);
+
+	if (entry != NULL) {
+		new_document_type = G_OBJECT_TYPE (entry);
+	} else if (strcmp (content_type, "application/x-vnd.oasis.opendocument.spreadsheet") == 0 ||
+	           strcmp (content_type, "text/tab-separated-values") == 0 ||
+	           strcmp (content_type, "application/x-vnd.oasis.opendocument.spreadsheet") == 0 ||
+	           strcmp (content_type, "application/vnd.ms-excel") == 0) {
+		new_document_type = GDATA_TYPE_DOCUMENTS_SPREADSHEET;
+	} else if (strcmp (content_type, "application/msword") == 0 ||
+	           strcmp (content_type, "application/vnd.oasis.opendocument.text") == 0 ||
+	           strcmp (content_type, "application/rtf") == 0 ||
+	           strcmp (content_type, "text/html") == 0 ||
+	           strcmp (content_type, "application/vnd.sun.xml.writer") == 0 ||
+	           strcmp (content_type, "text/plain") == 0) {
+		new_document_type = GDATA_TYPE_DOCUMENTS_TEXT;
+	} else if (strcmp (content_type, "application/vnd.ms-powerpoint") == 0) {
+		new_document_type = GDATA_TYPE_DOCUMENTS_PRESENTATION;
+	}
+
+	if (g_type_is_a (new_document_type, GDATA_TYPE_ENTRY) == FALSE) {
+		g_set_error (error, GDATA_DOCUMENTS_SERVICE_ERROR, GDATA_DOCUMENTS_SERVICE_ERROR_INVALID_CONTENT_TYPE,
+		             _("The content type of the supplied document ('%s') could not be recognized."), content_type);
+		return NULL;
+	}
+
+	/* Get and parse the response from the server */
+	response_body = gdata_upload_stream_get_response (upload_stream, &response_length);
+	if (response_body == NULL || response_length == 0)
+		return NULL;
+
+	return GDATA_DOCUMENTS_ENTRY (gdata_parsable_new_from_xml (new_document_type, response_body, (gint) response_length, error));
 }
 
 /**
diff --git a/gdata/services/documents/gdata-documents-service.h b/gdata/services/documents/gdata-documents-service.h
index 0b5a023..78bfc46 100644
--- a/gdata/services/documents/gdata-documents-service.h
+++ b/gdata/services/documents/gdata-documents-service.h
@@ -24,6 +24,7 @@
 #include <glib-object.h>
 #include <gio/gio.h>
 #include <gdata/gdata-service.h>
+#include <gdata/gdata-upload-stream.h>
 #include <gdata/services/documents/gdata-documents-query.h>
 #include <gdata/services/documents/gdata-documents-feed.h>
 
@@ -89,11 +90,14 @@ void gdata_documents_service_query_documents_async (GDataDocumentsService *self,
 
 #include <gdata/services/documents/gdata-documents-folder.h>
 
-GDataDocumentsEntry *gdata_documents_service_upload_document (GDataDocumentsService *self, GDataDocumentsEntry *document, GFile *document_file,
-                                                              GDataDocumentsFolder *folder, GCancellable *cancellable,
-                                                              GError **error) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
-GDataDocumentsEntry *gdata_documents_service_update_document (GDataDocumentsService *self, GDataDocumentsEntry *document, GFile *document_file,
-                                                              GCancellable *cancellable, GError **error) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+GDataUploadStream *gdata_documents_service_upload_document (GDataDocumentsService *self, GDataDocumentsEntry *document, const gchar *slug,
+                                                            const gchar *content_type, GDataDocumentsFolder *folder,
+                                                            GError **error) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+GDataUploadStream *gdata_documents_service_update_document (GDataDocumentsService *self, GDataDocumentsEntry *document, const gchar *slug,
+                                                            const gchar *content_type, GError **error) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+GDataDocumentsEntry *gdata_documents_service_finish_upload (GDataDocumentsService *self, GDataUploadStream *upload_stream,
+                                                            GError **error) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
+
 GDataDocumentsEntry *gdata_documents_service_move_document_to_folder (GDataDocumentsService *self, GDataDocumentsEntry *document,
                                                                       GDataDocumentsFolder *folder, GCancellable *cancellable,
                                                                       GError **error) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC;
diff --git a/gdata/tests/documents.c b/gdata/tests/documents.c
index 892fea8..d9ead5a 100644
--- a/gdata/tests/documents.c
+++ b/gdata/tests/documents.c
@@ -20,10 +20,30 @@
 
 #include <glib.h>
 #include <unistd.h>
+#include <string.h>
 
 #include "gdata.h"
 #include "common.h"
 
+static gboolean
+check_document_is_in_folder (GDataDocumentsEntry *document, GDataDocumentsFolder *folder)
+{
+	GList *categories;
+	gboolean found_folder_category = FALSE;
+
+	for (categories = gdata_entry_get_categories (GDATA_ENTRY (document)); categories != NULL; categories = categories->next) {
+		GDataCategory *category = GDATA_CATEGORY (categories->data);
+
+		if (strcmp (gdata_category_get_scheme (category), "http://schemas.google.com/docs/2007/folders/"; DOCUMENTS_USERNAME) == 0 &&
+		    strcmp (gdata_category_get_term (category), gdata_entry_get_title (GDATA_ENTRY (folder))) == 0) {
+			g_assert (found_folder_category == FALSE);
+			found_folder_category = TRUE;
+		}
+	}
+
+	return found_folder_category;
+}
+
 static void
 test_authentication (void)
 {
@@ -166,6 +186,7 @@ test_upload_metadata (gconstpointer service)
 {
 	GDataDocumentsEntry *document, *new_document;
 	GError *error = NULL;
+	gchar *upload_uri;
 
 	g_assert (service != NULL);
 
@@ -173,7 +194,9 @@ test_upload_metadata (gconstpointer service)
 	gdata_entry_set_title (GDATA_ENTRY (document), "myNewSpreadsheet");
 
 	/* Insert the document */
-	new_document = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), GDATA_DOCUMENTS_ENTRY (document), NULL, NULL, NULL, &error);
+	upload_uri = gdata_documents_service_get_upload_uri (NULL);
+	new_document = GDATA_DOCUMENTS_ENTRY (gdata_service_insert_entry (GDATA_SERVICE (service), upload_uri, GDATA_ENTRY (document), NULL, &error));
+	g_free (upload_uri);
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_SPREADSHEET (new_document));
 
@@ -187,21 +210,49 @@ test_upload_metadata_file (gconstpointer service)
 {
 	GDataDocumentsEntry *document, *new_document;
 	GFile *document_file;
+	GFileInfo *file_info;
+	GDataUploadStream *upload_stream;
+	GFileInputStream *file_stream;
 	GError *error = NULL;
 
 	g_assert (service != NULL);
 
 	document_file = g_file_new_for_path (TEST_FILE_DIR "test.odt");
+	file_info = g_file_query_info (document_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+	                               G_FILE_QUERY_INFO_NONE, NULL, &error);
+	g_assert_no_error (error);
 
 	document = GDATA_DOCUMENTS_ENTRY (gdata_documents_text_new (NULL));
 	gdata_entry_set_title (GDATA_ENTRY (document), "upload_metadata_file");
 
-	/* Insert the document */
-	new_document = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), document, document_file, NULL, NULL, &error);
+	/* Prepare the upload stream */
+	upload_stream = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), document, g_file_info_get_display_name (file_info),
+	                                                         g_file_info_get_content_type (file_info), NULL, &error);
+	g_assert_no_error (error);
+	g_assert (GDATA_IS_UPLOAD_STREAM (upload_stream));
+
+	g_object_unref (file_info);
+
+	/* Open the file */
+	file_stream = g_file_read (document_file, NULL, &error);
+	g_assert_no_error (error);
+
+	/* Upload the document */
+	g_output_stream_splice (G_OUTPUT_STREAM (upload_stream), G_INPUT_STREAM (file_stream),
+	                        G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, NULL, &error);
+	g_assert_no_error (error);
+
+	/* Finish the upload */
+	new_document = gdata_documents_service_finish_upload (GDATA_DOCUMENTS_SERVICE (service), upload_stream, &error);
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_TEXT (new_document));
 
+	/* Verify the uploaded document is the same as the original */
+	g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (document)), ==, gdata_entry_get_title (GDATA_ENTRY (new_document)));
+
 	g_clear_error (&error);
+	g_object_unref (upload_stream);
+	g_object_unref (file_stream);
 	g_object_unref (document_file);
 	g_object_unref (document);
 	g_object_unref (new_document);
@@ -212,28 +263,58 @@ test_upload_file_get_entry (gconstpointer service)
 {
 	GDataDocumentsEntry *new_document;
 	GDataEntry *new_presentation;
+	GDataUploadStream *upload_stream;
+	GFileInputStream *file_stream;
 	GFile *document_file;
+	GFileInfo *file_info;
 	GError *error = NULL;
 
 	g_assert (service != NULL);
 
 	document_file = g_file_new_for_path (TEST_FILE_DIR "test.ppt");
+	file_info = g_file_query_info (document_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+	                               G_FILE_QUERY_INFO_NONE, NULL, &error);
+	g_assert_no_error (error);
 
-	/* Insert the document */
-	new_document = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), NULL, document_file, NULL, NULL, &error);
+	/* Prepare the upload stream */
+	upload_stream = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), NULL, g_file_info_get_display_name (file_info),
+	                                                         g_file_info_get_content_type (file_info), NULL, &error);
+	g_assert_no_error (error);
+	g_assert (GDATA_IS_UPLOAD_STREAM (upload_stream));
+
+	g_object_unref (file_info);
+
+	/* Open the file */
+	file_stream = g_file_read (document_file, NULL, &error);
+	g_assert_no_error (error);
+
+	g_object_unref (document_file);
+
+	/* Upload the document */
+	g_output_stream_splice (G_OUTPUT_STREAM (upload_stream), G_INPUT_STREAM (file_stream),
+	                        G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, NULL, &error);
+	g_assert_no_error (error);
+
+	/* Finish the upload */
+	new_document = gdata_documents_service_finish_upload (GDATA_DOCUMENTS_SERVICE (service), upload_stream, &error);
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_PRESENTATION (new_document));
 
+	g_object_unref (file_stream);
+	g_object_unref (upload_stream);
+
 	/* Get the entry on the server */
 	new_presentation = gdata_service_query_single_entry (GDATA_SERVICE (service), gdata_entry_get_id (GDATA_ENTRY (new_document)), NULL,
 	                                                     GDATA_TYPE_DOCUMENTS_PRESENTATION, NULL, &error);
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_PRESENTATION (new_presentation));
 
+	/* Verify that the entry is correct (mangled version of the file's display name) */
+	g_assert_cmpstr (gdata_entry_get_title (new_presentation), ==, "test");
+
 	g_clear_error (&error);
 	g_object_unref (new_document);
 	g_object_unref (new_presentation);
-	g_object_unref (document_file);
 }
 
 static void
@@ -241,7 +322,11 @@ test_add_remove_file_from_folder (gconstpointer service)
 {
 	GDataDocumentsEntry *document, *new_document, *new_document2;
 	GDataDocumentsFolder *folder, *new_folder;
+	GDataUploadStream *upload_stream;
 	GFile *document_file;
+	GFileInfo *file_info;
+	GFileInputStream *file_stream;
+	gchar *upload_uri;
 	GError *error = NULL;
 
 	g_assert (service != NULL);
@@ -249,32 +334,73 @@ test_add_remove_file_from_folder (gconstpointer service)
 	folder = gdata_documents_folder_new (NULL);
 	gdata_entry_set_title (GDATA_ENTRY (folder), "add_remove_from_folder_folder");
 
+	/* Insert the folder */
+	upload_uri = gdata_documents_service_get_upload_uri (NULL);
+	new_folder = GDATA_DOCUMENTS_FOLDER (gdata_service_insert_entry (GDATA_SERVICE (service), upload_uri, GDATA_ENTRY (folder), NULL, &error));
+	g_free (upload_uri);
+
+	g_assert_no_error (error);
+	g_assert (GDATA_IS_DOCUMENTS_FOLDER (new_folder));
+
+	/* Check for success */
+	g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (new_folder)), ==, gdata_entry_get_title (GDATA_ENTRY (folder)));
+
+	g_object_unref (folder);
+
+	/* Prepare the file */
 	document_file = g_file_new_for_path (TEST_FILE_DIR "test.ppt");
 	document = GDATA_DOCUMENTS_ENTRY (gdata_documents_presentation_new (NULL));
 	gdata_entry_set_title (GDATA_ENTRY (document), "add_remove_from_folder_presentation");
 
-	/* Insert the folder */
-	new_folder = GDATA_DOCUMENTS_FOLDER (gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), GDATA_DOCUMENTS_ENTRY (folder), NULL, NULL, NULL, &error));
+	file_info = g_file_query_info (document_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+	                               G_FILE_QUERY_INFO_NONE, NULL, &error);
 	g_assert_no_error (error);
-	g_assert (GDATA_IS_DOCUMENTS_FOLDER (new_folder));
 
-	/* Insert the document in the new folder */
-	new_document = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), document, document_file, new_folder, NULL, &error);
+	/* Prepare the upload stream */
+	upload_stream = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), document, g_file_info_get_display_name (file_info),
+	                                                         g_file_info_get_content_type (file_info), new_folder, &error);
+	g_assert_no_error (error);
+	g_assert (GDATA_IS_UPLOAD_STREAM (upload_stream));
+
+	g_object_unref (file_info);
+
+	/* Open the file */
+	file_stream = g_file_read (document_file, NULL, &error);
+	g_assert_no_error (error);
+
+	g_object_unref (document_file);
+
+	/* Upload the document into the new folder */
+	g_output_stream_splice (G_OUTPUT_STREAM (upload_stream), G_INPUT_STREAM (file_stream),
+	                        G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, NULL, &error);
+	g_assert_no_error (error);
+
+	/* Finish the upload */
+	new_document = gdata_documents_service_finish_upload (GDATA_DOCUMENTS_SERVICE (service), upload_stream, &error);
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_PRESENTATION (new_document));
 
-	/*remove document from the folder*/
+	g_object_unref (upload_stream);
+	g_object_unref (file_stream);
+
+	/* Check the uploaded document is correct */
+	g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (new_document)), ==, gdata_entry_get_title (GDATA_ENTRY (document)));
+	g_assert (check_document_is_in_folder (new_document, new_folder) == TRUE);
+
+	/* Remove the document from the folder */
 	new_document2 = gdata_documents_service_remove_document_from_folder (GDATA_DOCUMENTS_SERVICE (service), new_document, new_folder, NULL, &error);
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_PRESENTATION (new_document2));
 
+	/* Check it's still the same document */
+	g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (new_document2)), ==, gdata_entry_get_title (GDATA_ENTRY (document)));
+	g_assert (check_document_is_in_folder (new_document2, new_folder) == FALSE);
+
 	g_clear_error (&error);
 	g_object_unref (document);
 	g_object_unref (new_document);
 	g_object_unref (new_document2);
-	g_object_unref (folder);
 	g_object_unref (new_folder);
-	g_object_unref (document_file);
 }
 
 static void
@@ -282,40 +408,85 @@ test_add_file_folder_and_move (gconstpointer service)
 {
 	GDataDocumentsEntry *document, *new_document, *new_document2;
 	GDataDocumentsFolder *folder, *new_folder;
+	GDataUploadStream *upload_stream;
+	GFileInputStream *file_stream;
 	GFile *document_file;
+	GFileInfo *file_info;
+	gchar *upload_uri;
 	GError *error = NULL;
 
 	g_assert (service != NULL);
 
-	document_file = g_file_new_for_path (TEST_FILE_DIR "test.odt");
-
 	folder = gdata_documents_folder_new (NULL);
 	gdata_entry_set_title (GDATA_ENTRY (folder), "add_file_folder_move_folder");
 
+	/* Insert the folder */
+	upload_uri = gdata_documents_service_get_upload_uri (NULL);
+	new_folder = GDATA_DOCUMENTS_FOLDER (gdata_service_insert_entry (GDATA_SERVICE (service), upload_uri, GDATA_ENTRY (folder), NULL, &error));
+	g_free (upload_uri);
+
+	g_assert_no_error (error);
+	g_assert (GDATA_IS_DOCUMENTS_FOLDER (new_folder));
+
+	/* Check for success */
+	g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (new_folder)), ==, gdata_entry_get_title (GDATA_ENTRY (folder)));
+
+	g_object_unref (folder);
+
+	/* Prepare the file */
+	document_file = g_file_new_for_path (TEST_FILE_DIR "test.odt");
 	document = GDATA_DOCUMENTS_ENTRY (gdata_documents_text_new (NULL));
 	gdata_entry_set_title (GDATA_ENTRY (document), "add_file_folder_move_text");
 
-	/* Insert the folder */
-	new_folder = GDATA_DOCUMENTS_FOLDER (gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), GDATA_DOCUMENTS_ENTRY (folder), NULL, NULL, NULL, &error));
+	file_info = g_file_query_info (document_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+	                               G_FILE_QUERY_INFO_NONE, NULL, &error);
+	g_assert_no_error (error);
+
+	/* Prepare the upload stream */
+	upload_stream = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), document, g_file_info_get_display_name (file_info),
+	                                                         g_file_info_get_content_type (file_info), NULL, &error);
+	g_assert_no_error (error);
+	g_assert (GDATA_IS_UPLOAD_STREAM (upload_stream));
+
+	g_object_unref (file_info);
+
+	/* Open the file */
+	file_stream = g_file_read (document_file, NULL, &error);
+	g_assert_no_error (error);
+
+	g_object_unref (document_file);
+
+	/* Upload the document (but not into the new folder; we'll move it there next) */
+	g_output_stream_splice (G_OUTPUT_STREAM (upload_stream), G_INPUT_STREAM (file_stream),
+	                        G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, NULL, &error);
 	g_assert_no_error (error);
-	g_assert (GDATA_IS_DOCUMENTS_FOLDER (new_folder));
 
-	/* Insert the document in the new folder */
-	new_document = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), document, document_file, NULL, NULL, &error);
+	/* Finish the upload */
+	new_document = gdata_documents_service_finish_upload (GDATA_DOCUMENTS_SERVICE (service), upload_stream, &error);
+	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_TEXT (new_document));
 
-	/* Remove the document from the folder */
+	g_object_unref (upload_stream);
+	g_object_unref (file_stream);
+
+	/* Check it's still the same document */
+	g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (new_document)), ==, gdata_entry_get_title (GDATA_ENTRY (document)));
+	g_assert (check_document_is_in_folder (new_document, new_folder) == FALSE);
+
+	/* Move the document from the folder */
 	new_document2 = gdata_documents_service_move_document_to_folder (GDATA_DOCUMENTS_SERVICE (service), new_document, new_folder, NULL, &error);
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_TEXT (new_document2));
 
+	/* Check it's still the same document */
+	g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (new_document2)), ==, gdata_entry_get_title (GDATA_ENTRY (document)));
+	g_assert (check_document_is_in_folder (new_document2, new_folder) == TRUE);
+
 	g_clear_error (&error);
 	g_object_unref (document);
 	g_object_unref (new_document);
 	g_object_unref (new_document2);
-	g_object_unref (folder);
 	g_object_unref (new_folder);
-	g_object_unref (document_file);
 }
 
 static void
@@ -323,42 +494,79 @@ test_upload_file_metadata_in_new_folder (gconstpointer service)
 {
 	GDataDocumentsEntry *document, *new_document;
 	GDataDocumentsFolder *folder, *new_folder;
+	GDataUploadStream *upload_stream;
+	GFileInputStream *file_stream;
 	GFile *document_file;
+	GFileInfo *file_info;
+	gchar *upload_uri;
 	GError *error = NULL;
 
 	g_assert (service != NULL);
 
-	document_file = g_file_new_for_path (TEST_FILE_DIR "test.odt");
-
 	folder = gdata_documents_folder_new (NULL);
 	gdata_entry_set_title (GDATA_ENTRY (folder), "upload_file_metadata_in_new_folder_folder");
 
+	/* Insert the folder */
+	upload_uri = gdata_documents_service_get_upload_uri (NULL);
+	new_folder = GDATA_DOCUMENTS_FOLDER (gdata_service_insert_entry (GDATA_SERVICE (service), upload_uri, GDATA_ENTRY (folder), NULL, &error));
+	g_free (upload_uri);
+
+	g_assert_no_error (error);
+	g_assert (GDATA_IS_DOCUMENTS_FOLDER (new_folder));
+
+	g_object_unref (folder);
+
+	/* Prepare the file */
+	document_file = g_file_new_for_path (TEST_FILE_DIR "test.odt");
 	document = GDATA_DOCUMENTS_ENTRY (gdata_documents_text_new (NULL));
 	gdata_entry_set_title (GDATA_ENTRY (document), "upload_file_metadata_in_new_folder_text");
 
-	/* Insert the folder */
-	new_folder = GDATA_DOCUMENTS_FOLDER (gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), GDATA_DOCUMENTS_ENTRY (folder), NULL, NULL, NULL, &error));
+	file_info = g_file_query_info (document_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+	                               G_FILE_QUERY_INFO_NONE, NULL, &error);
 	g_assert_no_error (error);
-	g_assert (GDATA_IS_DOCUMENTS_FOLDER (new_folder));
-	g_clear_error (&error);
 
-	/* Insert the document in the new folder */
-	new_document = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), document, document_file, new_folder, NULL, &error);
+	/* Prepare the upload stream */
+	upload_stream = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), document, g_file_info_get_display_name (file_info),
+	                                                         g_file_info_get_content_type (file_info), new_folder, &error);
+	g_assert_no_error (error);
+	g_assert (GDATA_IS_UPLOAD_STREAM (upload_stream));
+
+	g_object_unref (file_info);
+
+	/* Open the file */
+	file_stream = g_file_read (document_file, NULL, &error);
+	g_assert_no_error (error);
+
+	g_object_unref (document_file);
+
+	/* Upload the document into the new folder */
+	g_output_stream_splice (G_OUTPUT_STREAM (upload_stream), G_INPUT_STREAM (file_stream),
+	                        G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, NULL, &error);
+	g_assert_no_error (error);
+
+	/* Finish the upload */
+	new_document = gdata_documents_service_finish_upload (GDATA_DOCUMENTS_SERVICE (service), upload_stream, &error);
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_TEXT (new_document));
 
+	g_object_unref (upload_stream);
+	g_object_unref (file_stream);
+
+	/* Check for success */
+	g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (new_document)), ==, gdata_entry_get_title (GDATA_ENTRY (document)));
+	g_assert (check_document_is_in_folder (new_document, new_folder) == TRUE);
+
 	g_clear_error (&error);
 	g_object_unref (document);
 	g_object_unref (new_document);
-	g_object_unref (folder);
 	g_object_unref (new_folder);
-	g_object_unref (document_file);
 }
 
 static void
 test_update_metadata (gconstpointer service)
 {
 	GDataDocumentsEntry *document, *new_document, *updated_document;
+	gchar *upload_uri;
 	GError *error = NULL;
 
 	g_assert (service != NULL);
@@ -367,18 +575,25 @@ test_update_metadata (gconstpointer service)
 	gdata_entry_set_title (GDATA_ENTRY (document), "update_metadata_first_title");
 
 	/* Insert the document */
-	new_document = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), document, NULL, NULL, NULL, &error);
+	upload_uri = gdata_documents_service_get_upload_uri (NULL);
+	new_document = GDATA_DOCUMENTS_ENTRY (gdata_service_insert_entry (GDATA_SERVICE (service), upload_uri, GDATA_ENTRY (document), NULL, &error));
+	g_free (upload_uri);
+
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_TEXT (new_document));
 
 	/* Change the title */
-	gdata_entry_set_title (GDATA_ENTRY (document), "update_metadata_updated_title");
+	gdata_entry_set_title (GDATA_ENTRY (new_document), "update_metadata_updated_title");
 
 	/* Update the document */
-	updated_document = gdata_documents_service_update_document (GDATA_DOCUMENTS_SERVICE (service), new_document, NULL, NULL, &error);
+	updated_document = GDATA_DOCUMENTS_ENTRY (gdata_service_update_entry (GDATA_SERVICE (service), GDATA_ENTRY (new_document), NULL, &error));
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_TEXT (updated_document));
 
+	/* Check for success */
+	g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (updated_document)), ==, gdata_entry_get_title (GDATA_ENTRY (new_document)));
+	g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (new_document)), !=, gdata_entry_get_title (GDATA_ENTRY (document)));
+
 	g_clear_error (&error);
 	g_object_unref (document);
 	g_object_unref (new_document);
@@ -389,62 +604,161 @@ static void
 test_update_metadata_file (gconstpointer service)
 {
 	GDataDocumentsEntry *document, *new_document, *updated_document;
-	GFile *document_file, *updated_document_file;
+	GDataUploadStream *upload_stream;
+	GFileInputStream *file_stream;
+	GFile *updated_document_file;
+	GFileInfo *file_info;
+	gchar *upload_uri;
 	GError *error = NULL;
 
 	g_assert (service != NULL);
 
-	document_file = g_file_new_for_path (TEST_FILE_DIR "test.odt");
-	updated_document_file = g_file_new_for_path (TEST_FILE_DIR "test_updated.odt");
-
 	document = GDATA_DOCUMENTS_ENTRY (gdata_documents_text_new (NULL));
 	gdata_entry_set_title (GDATA_ENTRY (document), "update_metadata_file_first_title");
 
-	/* Insert the documents metadata*/
-	new_document = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), document, NULL, NULL, NULL, &error);
+	/* Insert the document's metadata */
+	upload_uri = gdata_documents_service_get_upload_uri (NULL);
+	new_document = GDATA_DOCUMENTS_ENTRY (gdata_service_insert_entry (GDATA_SERVICE (service), upload_uri, GDATA_ENTRY (document), NULL, &error));
+	g_free (upload_uri);
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_TEXT (new_document));
 
+	g_object_unref (document);
+
 	/* Change the title of the document */
 	gdata_entry_set_title (GDATA_ENTRY (new_document), "update_metadata_file_updated_title");
 
-	/* Update the document */
-	updated_document = gdata_documents_service_update_document (GDATA_DOCUMENTS_SERVICE (service), new_document, updated_document_file, NULL, &error);
+	/* Prepare the file */
+	updated_document_file = g_file_new_for_path (TEST_FILE_DIR "test_updated.odt");
+
+	file_info = g_file_query_info (updated_document_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+	                               G_FILE_QUERY_INFO_NONE, NULL, &error);
+	g_assert_no_error (error);
+
+	/* Prepare the upload stream */
+	upload_stream = gdata_documents_service_update_document (GDATA_DOCUMENTS_SERVICE (service), new_document,
+	                                                         g_file_info_get_display_name (file_info), g_file_info_get_content_type (file_info),
+	                                                         &error);
+	g_assert_no_error (error);
+	g_assert (GDATA_IS_UPLOAD_STREAM (upload_stream));
+
+	g_object_unref (file_info);
+
+	/* Open the file */
+	file_stream = g_file_read (updated_document_file, NULL, &error);
+	g_assert_no_error (error);
+
+	g_object_unref (updated_document_file);
+
+	/* Upload the updated document */
+	g_output_stream_splice (G_OUTPUT_STREAM (upload_stream), G_INPUT_STREAM (file_stream),
+	                        G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, NULL, &error);
+	g_assert_no_error (error);
+
+	/* Finish the upload */
+	updated_document = gdata_documents_service_finish_upload (GDATA_DOCUMENTS_SERVICE (service), upload_stream, &error);
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_TEXT (updated_document));
 
+	g_object_unref (upload_stream);
+	g_object_unref (file_stream);
+
+	/* Check for success */
+	g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (new_document)), ==, gdata_entry_get_title (GDATA_ENTRY (updated_document)));
+
 	g_clear_error (&error);
-	g_object_unref (document);
-	g_object_unref (new_document);
 	g_object_unref (updated_document);
-	g_object_unref (document_file);
+	g_object_unref (new_document);
 }
 
 static void
 test_update_file (gconstpointer service)
 {
 	GDataDocumentsEntry *new_document, *updated_document;
-	GFile *document_file, *updated_document_file;
+	GDataUploadStream *upload_stream;
+	GFileInputStream *file_stream;
+	GFile *document_file;
+	GFileInfo *file_info;
 	GError *error = NULL;
 
 	g_assert (service != NULL);
 
+	/* Upload the original file */
+
+	/* Get the file info */
 	document_file = g_file_new_for_path (TEST_FILE_DIR "test.ppt");
-	updated_document_file = g_file_new_for_path (TEST_FILE_DIR "test_updated_file.ppt");
+	file_info = g_file_query_info (document_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+	                               G_FILE_QUERY_INFO_NONE, NULL, &error);
+	g_assert_no_error (error);
 
-	/* Insert the document */
-	new_document = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), NULL, document_file, NULL, NULL, &error);
+	/* Prepare the upload stream */
+	upload_stream = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), NULL, g_file_info_get_display_name (file_info),
+	                                                         g_file_info_get_content_type (file_info), NULL, &error);
+	g_assert_no_error (error);
+	g_assert (GDATA_IS_UPLOAD_STREAM (upload_stream));
+
+	g_object_unref (file_info);
+
+	/* Open the file */
+	file_stream = g_file_read (document_file, NULL, &error);
+	g_assert_no_error (error);
+
+	g_object_unref (document_file);
+
+	/* Upload the document */
+	g_output_stream_splice (G_OUTPUT_STREAM (upload_stream), G_INPUT_STREAM (file_stream),
+	                        G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, NULL, &error);
+	g_assert_no_error (error);
+
+	g_object_unref (file_stream);
+
+	/* Finish the upload */
+	new_document = gdata_documents_service_finish_upload (GDATA_DOCUMENTS_SERVICE (service), upload_stream, &error);
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_PRESENTATION (new_document));
 
+	g_object_unref (upload_stream);
+
 	/* Update the document */
-	updated_document = gdata_documents_service_update_document (GDATA_DOCUMENTS_SERVICE (service), new_document, document_file, NULL, &error);
+
+	/* Get the file info for the updated document */
+	document_file = g_file_new_for_path (TEST_FILE_DIR "test_updated_file.ppt");
+	file_info = g_file_query_info (document_file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+	                               G_FILE_QUERY_INFO_NONE, NULL, &error);
+	g_assert_no_error (error);
+
+	/* Prepare the upload stream */
+	upload_stream = gdata_documents_service_update_document (GDATA_DOCUMENTS_SERVICE (service), new_document,
+	                                                         g_file_info_get_display_name (file_info), g_file_info_get_content_type (file_info),
+	                                                         &error);
+	g_assert_no_error (error);
+	g_assert (GDATA_IS_UPLOAD_STREAM (upload_stream));
+
+	g_object_unref (file_info);
+
+	/* Open the file */
+	file_stream = g_file_read (document_file, NULL, &error);
 	g_assert_no_error (error);
-	g_assert (GDATA_IS_DOCUMENTS_PRESENTATION (updated_document));
-	g_clear_error (&error);
 
 	g_object_unref (document_file);
-	g_object_unref (updated_document_file);
+
+	/* Upload the document */
+	g_output_stream_splice (G_OUTPUT_STREAM (upload_stream), G_INPUT_STREAM (file_stream),
+	                        G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, NULL, &error);
+	g_assert_no_error (error);
+
+	g_object_unref (file_stream);
+
+	/* Finish the upload */
+	updated_document = gdata_documents_service_finish_upload (GDATA_DOCUMENTS_SERVICE (service), upload_stream, &error);
+	g_assert_no_error (error);
+	g_assert (GDATA_IS_DOCUMENTS_PRESENTATION (updated_document));
+
+	g_object_unref (upload_stream);
+
+	/* Check for success */
+	g_assert_cmpstr (gdata_entry_get_title (GDATA_ENTRY (new_document)), ==, gdata_entry_get_title (GDATA_ENTRY (updated_document)));
+
 	g_object_unref (new_document);
 	g_object_unref (updated_document);
 }
@@ -531,6 +845,7 @@ test_new_document_with_collaborator (gconstpointer service)
 	GDataDocumentsEntry *document, *new_document;
 	GDataAccessRule *access_rule, *new_access_rule;
 	GDataLink *_link;
+	gchar *upload_uri;
 	GError *error = NULL;
 
 	g_assert (service != NULL);
@@ -539,7 +854,10 @@ test_new_document_with_collaborator (gconstpointer service)
 	gdata_entry_set_title (GDATA_ENTRY (document), "new_with_collaborator");
 
 	/* Insert the document */
-	new_document = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), GDATA_DOCUMENTS_ENTRY (document), NULL, NULL, NULL, &error);
+	upload_uri = gdata_documents_service_get_upload_uri (NULL);
+	new_document = GDATA_DOCUMENTS_ENTRY (gdata_service_insert_entry (GDATA_SERVICE (service), upload_uri, GDATA_ENTRY (document), NULL, &error));
+	g_free (upload_uri);
+
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_SPREADSHEET (new_document));
 
@@ -731,14 +1049,17 @@ static void
 setup_batch_async (BatchAsyncData *data, gconstpointer service)
 {
 	GDataDocumentsText *doc;
+	gchar *upload_uri;
 	GError *error = NULL;
 
 	/* Insert a new document which we can query asyncly */
 	doc = gdata_documents_text_new (NULL);
 	gdata_entry_set_title (GDATA_ENTRY (doc), "A View from the Bridge");
 
-	data->new_doc = gdata_documents_service_upload_document (GDATA_DOCUMENTS_SERVICE (service), GDATA_DOCUMENTS_ENTRY (doc), NULL, NULL, NULL,
-	                                                         &error);
+	upload_uri = gdata_documents_service_get_upload_uri (NULL);
+	data->new_doc = GDATA_DOCUMENTS_ENTRY (gdata_service_insert_entry (GDATA_SERVICE (service), upload_uri, GDATA_ENTRY (doc), NULL, &error));
+	g_free (upload_uri);
+
 	g_assert_no_error (error);
 	g_assert (GDATA_IS_DOCUMENTS_TEXT (data->new_doc));
 	g_clear_error (&error);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]