1 /*
2  * e-source-resource.c
3  *
4  * This library is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation.
7  *
8  * This library is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11  * for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library. If not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17 
18 /**
19  * SECTION: e-source-resource
20  * @include: libedataserver/libedataserver.h
21  * @short_description: #ESource extension for a remote resource
22  *
23  * The #ESourceResource extension holds the server-assigned identity of a
24  * remote calendar, address book, or whatever else an #ESource can represent.
25  *
26  * This extension is typically used by an #ECollectionBackend to note a
27  * server-assigned resource identity in an #ESource.  Then in a later session,
28  * after querying the server for available resources, a resource identity can
29  * be paired with the same #ESource #ESource:uid from the previous session,
30  * allowing locally cached data from the previous session to be reused.
31  *
32  * Access the extension as follows:
33  *
34  * |[
35  *   #include <libedataserver/libedataserver.h>
36  *
37  *   ESourceResource *extension;
38  *
39  *   extension = e_source_get_extension (source, E_SOURCE_EXTENSION_RESOURCE);
40  * ]|
41  **/
42 
43 #include "e-source-resource.h"
44 
45 #include <libedataserver/e-data-server-util.h>
46 
47 struct _ESourceResourcePrivate {
48 	gchar *identity;
49 };
50 
51 enum {
52 	PROP_0,
53 	PROP_IDENTITY
54 };
55 
G_DEFINE_TYPE_WITH_PRIVATE(ESourceResource,e_source_resource,E_TYPE_SOURCE_EXTENSION)56 G_DEFINE_TYPE_WITH_PRIVATE (
57 	ESourceResource,
58 	e_source_resource,
59 	E_TYPE_SOURCE_EXTENSION)
60 
61 static void
62 source_resource_set_property (GObject *object,
63                               guint property_id,
64                               const GValue *value,
65                               GParamSpec *pspec)
66 {
67 	switch (property_id) {
68 		case PROP_IDENTITY:
69 			e_source_resource_set_identity (
70 				E_SOURCE_RESOURCE (object),
71 				g_value_get_string (value));
72 			return;
73 	}
74 
75 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
76 }
77 
78 static void
source_resource_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)79 source_resource_get_property (GObject *object,
80                               guint property_id,
81                               GValue *value,
82                               GParamSpec *pspec)
83 {
84 	switch (property_id) {
85 		case PROP_IDENTITY:
86 			g_value_take_string (
87 				value,
88 				e_source_resource_dup_identity (
89 				E_SOURCE_RESOURCE (object)));
90 			return;
91 	}
92 
93 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
94 }
95 
96 static void
source_resource_finalize(GObject * object)97 source_resource_finalize (GObject *object)
98 {
99 	ESourceResourcePrivate *priv;
100 
101 	priv = E_SOURCE_RESOURCE (object)->priv;
102 
103 	g_free (priv->identity);
104 
105 	/* Chain up to parent's finalize() method. */
106 	G_OBJECT_CLASS (e_source_resource_parent_class)->finalize (object);
107 }
108 
109 static void
e_source_resource_class_init(ESourceResourceClass * class)110 e_source_resource_class_init (ESourceResourceClass *class)
111 {
112 	GObjectClass *object_class;
113 	ESourceExtensionClass *extension_class;
114 
115 	object_class = G_OBJECT_CLASS (class);
116 	object_class->set_property = source_resource_set_property;
117 	object_class->get_property = source_resource_get_property;
118 	object_class->finalize = source_resource_finalize;
119 
120 	extension_class = E_SOURCE_EXTENSION_CLASS (class);
121 	extension_class->name = E_SOURCE_EXTENSION_RESOURCE;
122 
123 	g_object_class_install_property (
124 		object_class,
125 		PROP_IDENTITY,
126 		g_param_spec_string (
127 			"identity",
128 			"Identity",
129 			"Resource identity",
130 			NULL,
131 			G_PARAM_READWRITE |
132 			G_PARAM_CONSTRUCT |
133 			G_PARAM_EXPLICIT_NOTIFY |
134 			G_PARAM_STATIC_STRINGS |
135 			E_SOURCE_PARAM_SETTING));
136 }
137 
138 static void
e_source_resource_init(ESourceResource * extension)139 e_source_resource_init (ESourceResource *extension)
140 {
141 	extension->priv = e_source_resource_get_instance_private (extension);
142 }
143 
144 /**
145  * e_source_resource_get_identity:
146  * @extension: an #ESourceResource
147  *
148  * Returns the server-assigned identity of the remote resource associated
149  * with the #ESource to which @extension belongs.
150  *
151  * Returns: (nullable): the identity of a remote resource
152  *
153  * Since: 3.6
154  **/
155 const gchar *
e_source_resource_get_identity(ESourceResource * extension)156 e_source_resource_get_identity (ESourceResource *extension)
157 {
158 	g_return_val_if_fail (E_IS_SOURCE_RESOURCE (extension), NULL);
159 
160 	return extension->priv->identity;
161 }
162 
163 /**
164  * e_source_resource_dup_identity:
165  * @extension: an #ESourceResource
166  *
167  * Thread-safe variation of e_source_resource_get_identity().
168  * Use this function when accessing @extension from multiple threads.
169  *
170  * The returned string should be freed with g_free() when no longer needed.
171  *
172  * Returns: (nullable): a newly-allocated copy of #ESourceResource:identity
173  *
174  * Since: 3.6
175  **/
176 gchar *
e_source_resource_dup_identity(ESourceResource * extension)177 e_source_resource_dup_identity (ESourceResource *extension)
178 {
179 	const gchar *protected;
180 	gchar *duplicate;
181 
182 	g_return_val_if_fail (E_IS_SOURCE_RESOURCE (extension), NULL);
183 
184 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
185 
186 	protected = e_source_resource_get_identity (extension);
187 	duplicate = g_strdup (protected);
188 
189 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
190 
191 	return duplicate;
192 }
193 
194 /**
195  * e_source_resource_set_identity:
196  * @extension: an #ESourceResource
197  * @identity: (nullable): the identity of a remote resource
198  *
199  * Sets the server-assigned identity of the remote resource associated with
200  * the #ESource to which @extension belongs.
201  *
202  * The internal copy of @identity is automatically stripped of leading and
203  * trailing whitespace.  If the resulting string is empty, %NULL is set
204  * instead.
205  *
206  * Since: 3.6
207  **/
208 void
e_source_resource_set_identity(ESourceResource * extension,const gchar * identity)209 e_source_resource_set_identity (ESourceResource *extension,
210                                 const gchar *identity)
211 {
212 	g_return_if_fail (E_IS_SOURCE_RESOURCE (extension));
213 
214 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
215 
216 	if (e_util_strcmp0 (extension->priv->identity, identity) == 0) {
217 		e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
218 		return;
219 	}
220 
221 	g_free (extension->priv->identity);
222 	extension->priv->identity = e_util_strdup_strip (identity);
223 
224 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
225 
226 	g_object_notify (G_OBJECT (extension), "identity");
227 }
228 
229