1 /*
2 * handle-repo.c - mechanism to store and retrieve handles on a connection
3 * (abstract interface)
4 *
5 * Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
6 * Copyright (C) 2007 Nokia Corporation
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /**
24 * SECTION:handle-repo
25 * @title: TpHandleRepoIface
26 * @short_description: abstract interface for handle allocation
27 * @see_also: TpDynamicHandleRepo, TpStaticHandleRepo
28 *
29 * Abstract interface of a repository for handles, supporting operations
30 * which include checking for validity, lookup by
31 * string value and lookup by numeric value. See #TpDynamicHandleRepo
32 * and #TpStaticHandleRepo for concrete implementations.
33 */
34
35 #include "config.h"
36
37 #include <telepathy-glib/handle-repo.h>
38
39 #include <telepathy-glib/handle-repo-internal.h>
40 #include <telepathy-glib/util-internal.h>
41
42 G_DEFINE_INTERFACE (TpHandleRepoIface, tp_handle_repo_iface, G_TYPE_OBJECT);
43
44 /**
45 * tp_handle_is_valid: (skip)
46 * @self: A handle repository implementation
47 * @handle: A handle of the type stored in the repository @self
48 * @error: Set to InvalidHandle if %FALSE is returned
49 *
50 * <!--Returns: says it all-->
51 *
52 * Returns: %TRUE if the handle is nonzero and is present in the repository,
53 * else %FALSE
54 */
55
56 gboolean
tp_handle_is_valid(TpHandleRepoIface * self,TpHandle handle,GError ** error)57 tp_handle_is_valid (TpHandleRepoIface *self,
58 TpHandle handle,
59 GError **error)
60 {
61 return TP_HANDLE_REPO_IFACE_GET_CLASS (self)->handle_is_valid (self,
62 handle, error);
63 }
64
65
66 /**
67 * tp_handles_are_valid: (skip)
68 * @self: A handle repository implementation
69 * @handles: Array of TpHandle representing handles of the type stored in
70 * the repository @self
71 * @allow_zero: If %TRUE, zero is treated like a valid handle
72 * @error: Set to InvalidHandle if %FALSE is returned
73 *
74 * <!--Returns: says it all-->
75 *
76 * Returns: %TRUE if the handle is present in the repository, else %FALSE
77 */
78
79 gboolean
tp_handles_are_valid(TpHandleRepoIface * self,const GArray * handles,gboolean allow_zero,GError ** error)80 tp_handles_are_valid (TpHandleRepoIface *self,
81 const GArray *handles,
82 gboolean allow_zero,
83 GError **error)
84 {
85 return TP_HANDLE_REPO_IFACE_GET_CLASS (self)->handles_are_valid (self,
86 handles, allow_zero, error);
87 }
88
89
90 /**
91 * tp_handle_ref: (skip)
92 * @self: not used
93 * @handle: not used
94 *
95 * Do nothing. Since version 0.13.8, handles always last as long as
96 * the connection; previously, this function provided refcounting for handles.
97 *
98 * Changed in 0.13.6: @handle is now returned; previously,
99 * this function didn't return anything.
100 *
101 * Returns: the same @handle
102 * Deprecated: This is no-op so can be safely removed.
103 */
104
105 TpHandle
tp_handle_ref(TpHandleRepoIface * self G_GNUC_UNUSED,TpHandle handle)106 tp_handle_ref (TpHandleRepoIface *self G_GNUC_UNUSED,
107 TpHandle handle)
108 {
109 return handle;
110 }
111
112
113 /**
114 * tp_handles_ref: (skip)
115 * @self: not used
116 * @handles: not used
117 *
118 * Do nothing. Since version 0.13.8, handles always last as long as
119 * the connection; previously, this function provided refcounting for handles.
120 *
121 * Deprecated: This is no-op so can be safely removed.
122 */
123 void
tp_handles_ref(TpHandleRepoIface * self G_GNUC_UNUSED,const GArray * handles G_GNUC_UNUSED)124 tp_handles_ref (TpHandleRepoIface *self G_GNUC_UNUSED,
125 const GArray *handles G_GNUC_UNUSED)
126 {
127 }
128
129
130 /**
131 * tp_handle_unref: (skip)
132 * @self: A handle repository implementation
133 * @handle: A handle of the type stored in the repository
134 *
135 * Do nothing. Since version 0.13.8, handles always last as long as
136 * the connection; previously, this function provided refcounting for handles.
137 *
138 * Deprecated: This is no-op so can be safely removed.
139 */
140
141 void
tp_handle_unref(TpHandleRepoIface * self G_GNUC_UNUSED,TpHandle handle G_GNUC_UNUSED)142 tp_handle_unref (TpHandleRepoIface *self G_GNUC_UNUSED,
143 TpHandle handle G_GNUC_UNUSED)
144 {
145 }
146
147
148 /**
149 * tp_handles_unref: (skip)
150 * @self: not used
151 * @handles: not used
152 *
153 * Do nothing. Since version 0.13.8, handles always last as long as
154 * the connection; previously, this function provided refcounting for handles.
155 *
156 * Deprecated: This is no-op so can be safely removed.
157 */
158 void
tp_handles_unref(TpHandleRepoIface * self G_GNUC_UNUSED,const GArray * handles G_GNUC_UNUSED)159 tp_handles_unref (TpHandleRepoIface *self G_GNUC_UNUSED,
160 const GArray *handles G_GNUC_UNUSED)
161 {
162 }
163
164
165 /**
166 * tp_handle_client_hold: (skip)
167 * @self: not used
168 * @client: not used
169 * @handle: not used
170 * @error: not set
171 *
172 * Do nothing. Since version 0.13.8, handles always last as long as
173 * the connection; previously, this function provided refcounting for handles.
174 *
175 * Returns: %TRUE
176 * Deprecated: This is no-op so can be safely removed.
177 */
178
179 gboolean
tp_handle_client_hold(TpHandleRepoIface * self G_GNUC_UNUSED,const gchar * client G_GNUC_UNUSED,TpHandle handle G_GNUC_UNUSED,GError ** error G_GNUC_UNUSED)180 tp_handle_client_hold (TpHandleRepoIface *self G_GNUC_UNUSED,
181 const gchar *client G_GNUC_UNUSED,
182 TpHandle handle G_GNUC_UNUSED,
183 GError **error G_GNUC_UNUSED)
184 {
185 return TRUE;
186 }
187
188
189 typedef gboolean (*HoldReleaseFunc) (TpHandleRepoIface *, const gchar *,
190 TpHandle, GError **);
191
192 /**
193 * tp_handles_client_hold: (skip)
194 * @self: ignored
195 * @client: ignored
196 * @handles: ignored
197 * @error: ignored
198 *
199 * Do nothing. Since version 0.13.8, handles always last as long as
200 * the connection; previously, this function provided refcounting for handles.
201 *
202 * Returns: %TRUE
203 * Deprecated: This is no-op so can be safely removed.
204 */
205 gboolean
tp_handles_client_hold(TpHandleRepoIface * self G_GNUC_UNUSED,const gchar * client G_GNUC_UNUSED,const GArray * handles G_GNUC_UNUSED,GError ** error G_GNUC_UNUSED)206 tp_handles_client_hold (TpHandleRepoIface *self G_GNUC_UNUSED,
207 const gchar *client G_GNUC_UNUSED,
208 const GArray *handles G_GNUC_UNUSED,
209 GError **error G_GNUC_UNUSED)
210 {
211 return TRUE;
212 }
213
214
215 /**
216 * tp_handle_client_release: (skip)
217 * @self: ignored
218 * @client: ignored
219 * @handle: ignored
220 * @error: ignored
221 *
222 * Do nothing. Since version 0.13.8, handles always last as long as
223 * the connection; previously, this function provided refcounting for handles.
224 *
225 * Returns: %TRUE
226 * Deprecated: This is no-op so can be safely removed.
227 */
228 gboolean
tp_handle_client_release(TpHandleRepoIface * self G_GNUC_UNUSED,const gchar * client G_GNUC_UNUSED,TpHandle handle G_GNUC_UNUSED,GError ** error G_GNUC_UNUSED)229 tp_handle_client_release (TpHandleRepoIface *self G_GNUC_UNUSED,
230 const gchar *client G_GNUC_UNUSED,
231 TpHandle handle G_GNUC_UNUSED,
232 GError **error G_GNUC_UNUSED)
233 {
234 return TRUE;
235 }
236
237 /**
238 * tp_handles_client_release: (skip)
239 * @self: ignored
240 * @client: ignored
241 * @handles: ignored
242 * @error: ignored
243 *
244 * Do nothing. Since version 0.13.8, handles always last as long as
245 * the connection; previously, this function provided refcounting for handles.
246 *
247 * Returns: %TRUE
248 * Deprecated: This is no-op so can be safely removed.
249 */
250 gboolean
tp_handles_client_release(TpHandleRepoIface * self G_GNUC_UNUSED,const gchar * client G_GNUC_UNUSED,const GArray * handles G_GNUC_UNUSED,GError ** error G_GNUC_UNUSED)251 tp_handles_client_release (TpHandleRepoIface *self G_GNUC_UNUSED,
252 const gchar *client G_GNUC_UNUSED,
253 const GArray *handles G_GNUC_UNUSED,
254 GError **error G_GNUC_UNUSED)
255 {
256 return TRUE;
257 }
258
259
260 /**
261 * tp_handle_inspect: (skip)
262 * @self: A handle repository implementation
263 * @handle: A handle of the type stored in the repository
264 *
265 * <!--Returns: says it all-->
266 *
267 * Returns: the string represented by the given handle, or NULL if the
268 * handle is absent from the repository. The string is owned by the
269 * handle repository and will remain valid as long as a reference to
270 * the handle exists.
271 */
272
273 const char *
tp_handle_inspect(TpHandleRepoIface * self,TpHandle handle)274 tp_handle_inspect (TpHandleRepoIface *self,
275 TpHandle handle)
276 {
277 return TP_HANDLE_REPO_IFACE_GET_CLASS (self)->inspect_handle (self,
278 handle);
279 }
280
281
282 /**
283 * tp_handle_ensure:
284 * @self: A handle repository implementation
285 * @id: A string whose handle is required
286 * @context: User data to be passed to the normalization callback
287 * @error: Used to return an error if 0 is returned
288 *
289 * Return a handle for the given string, creating one if necessary. The string
290 * is normalized, if possible.
291 *
292 * Returns: the handle corresponding to the given string, or 0 if it
293 * is invalid.
294 */
295
296 TpHandle
tp_handle_ensure(TpHandleRepoIface * self,const gchar * id,gpointer context,GError ** error)297 tp_handle_ensure (TpHandleRepoIface *self,
298 const gchar *id,
299 gpointer context,
300 GError **error)
301 {
302 return TP_HANDLE_REPO_IFACE_GET_CLASS (self)->ensure_handle (self,
303 id, context, error);
304 }
305
306 /**
307 * tp_handle_ensure_async: (skip)
308 * @self: A handle repository implementation
309 * @connection: the #TpBaseConnection using this handle repo
310 * @id: A string whose handle is required
311 * @context: User data to be passed to the normalization callback
312 * @callback: a callback to call when the operation finishes
313 * @user_data: data to pass to @callback
314 *
315 * Asyncronously normalize an identifier and create an handle for it. This could
316 * involve a server round-trip. This should be used instead of
317 * tp_handle_ensure() for user provided contact identifiers, but it is not
318 * necessary for identifiers from the server.
319 *
320 * Since: 0.19.2
321 */
322 void
tp_handle_ensure_async(TpHandleRepoIface * self,TpBaseConnection * connection,const gchar * id,gpointer context,GAsyncReadyCallback callback,gpointer user_data)323 tp_handle_ensure_async (TpHandleRepoIface *self,
324 TpBaseConnection *connection,
325 const gchar *id,
326 gpointer context,
327 GAsyncReadyCallback callback,
328 gpointer user_data)
329 {
330 return TP_HANDLE_REPO_IFACE_GET_CLASS (self)->ensure_handle_async (self,
331 connection, id, context, callback, user_data);
332 }
333
334 /**
335 * tp_handle_ensure_finish: (skip)
336 * @self: A handle repository implementation
337 * @result: a #GAsyncResult
338 * @error: a #GError to fill
339 *
340 * Finishes tp_handle_ensure_async()
341 *
342 * Returns: non-0 #TpHandle if the operation was successful, otherwise 0.
343 *
344 * Since: 0.19.2
345 */
346 TpHandle
tp_handle_ensure_finish(TpHandleRepoIface * self,GAsyncResult * result,GError ** error)347 tp_handle_ensure_finish (TpHandleRepoIface *self,
348 GAsyncResult *result,
349 GError **error)
350 {
351 return TP_HANDLE_REPO_IFACE_GET_CLASS (self)->ensure_handle_finish (self,
352 result, error);
353 }
354
355 /**
356 * tp_handle_lookup: (skip)
357 * @self: A handle repository implementation
358 * @id: A string whose handle is required
359 * @context: User data to be passed to the normalization callback
360 * @error: Used to raise an error if the handle does not exist or is
361 * invalid
362 *
363 * Return the handle for the given string. The string is normalized if
364 * possible. If no handle already exists for the string, none is created.
365 *
366 * Returns: the handle corresponding to the given string, or 0 if it
367 * does not exist or is invalid
368 */
369
370 TpHandle
tp_handle_lookup(TpHandleRepoIface * self,const gchar * id,gpointer context,GError ** error)371 tp_handle_lookup (TpHandleRepoIface *self,
372 const gchar *id,
373 gpointer context,
374 GError **error)
375 {
376 return TP_HANDLE_REPO_IFACE_GET_CLASS (self)->lookup_handle (self,
377 id, context, error);
378 }
379
380
381 /**
382 * tp_handle_set_qdata: (skip)
383 * @repo: A handle repository implementation
384 * @handle: A handle to set data on
385 * @key_id: Key id to associate data with
386 * @data: data to associate with handle
387 * @destroy: A #GDestroyNotify to call to destroy the data,
388 * or NULL if not needed.
389 *
390 * Associates a blob of data with a given handle and a given key
391 *
392 * If @destroy is set, then the data is freed when the handle is freed.
393 *
394 * Since version 0.13.8, handles always last as long as the
395 * connection, so @destroy will not be called until the connection
396 * disconnects.
397 *
398 * Deprecated: Since 0.19.9. It is not recommended to use this function
399 * because the associated data won't be freed until the connection disconnects.
400 */
401
402 void
tp_handle_set_qdata(TpHandleRepoIface * repo,TpHandle handle,GQuark key_id,gpointer data,GDestroyNotify destroy)403 tp_handle_set_qdata (TpHandleRepoIface *repo,
404 TpHandle handle,
405 GQuark key_id,
406 gpointer data,
407 GDestroyNotify destroy)
408 {
409 TP_HANDLE_REPO_IFACE_GET_CLASS (repo)->set_qdata (repo,
410 handle, key_id, data, destroy);
411 }
412
413 /**
414 * tp_handle_get_qdata: (skip)
415 * @repo: A handle repository implementation
416 * @handle: A handle to get data from
417 * @key_id: Key id of data to fetch
418 *
419 * <!--Returns: says it all-->
420 *
421 * Returns: the data associated with a given key on a given handle; %NULL
422 * if there is no associated data.
423 * Deprecated: Since 0.19.9. It is not recommended to use this function
424 * because the associated data won't be freed until the connection disconnects.
425 */
426 gpointer
tp_handle_get_qdata(TpHandleRepoIface * repo,TpHandle handle,GQuark key_id)427 tp_handle_get_qdata (TpHandleRepoIface *repo, TpHandle handle,
428 GQuark key_id)
429 {
430 return TP_HANDLE_REPO_IFACE_GET_CLASS (repo)->get_qdata (repo,
431 handle, key_id);
432 }
433
434 static void
default_ensure_handle_async(TpHandleRepoIface * self,TpBaseConnection * connection,const gchar * id,gpointer context,GAsyncReadyCallback callback,gpointer user_data)435 default_ensure_handle_async (TpHandleRepoIface *self,
436 TpBaseConnection *connection,
437 const gchar *id,
438 gpointer context,
439 GAsyncReadyCallback callback,
440 gpointer user_data)
441 {
442 GSimpleAsyncResult *result;
443 TpHandle handle;
444 GError *error = NULL;
445
446 result = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
447 default_ensure_handle_async);
448
449 handle = tp_handle_ensure (self, id, context, &error);
450 if (handle == 0)
451 {
452 g_simple_async_result_take_error (result, error);
453 }
454 else
455 {
456 g_simple_async_result_set_op_res_gpointer (result,
457 GUINT_TO_POINTER (handle), NULL);
458 }
459
460 g_simple_async_result_complete_in_idle (result);
461
462 g_object_unref (result);
463 }
464
465 static TpHandle
default_ensure_handle_finish(TpHandleRepoIface * self,GAsyncResult * result,GError ** error)466 default_ensure_handle_finish (TpHandleRepoIface *self,
467 GAsyncResult *result,
468 GError **error)
469 {
470 GSimpleAsyncResult *simple = (GSimpleAsyncResult *) result;
471
472 g_return_val_if_fail (g_simple_async_result_is_valid (result,
473 G_OBJECT (self), NULL), 0);
474
475 if (g_simple_async_result_propagate_error (simple, error))
476 return 0;
477
478 return GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (simple));
479 }
480
481 static void
tp_handle_repo_iface_default_init(TpHandleRepoIfaceInterface * iface)482 tp_handle_repo_iface_default_init (TpHandleRepoIfaceInterface *iface)
483 {
484 GParamSpec *param_spec;
485
486 iface->ensure_handle_async = default_ensure_handle_async;
487 iface->ensure_handle_finish = default_ensure_handle_finish;
488
489 param_spec = g_param_spec_uint ("handle-type", "Handle type",
490 "The TpHandleType held in this handle repository.",
491 0, G_MAXUINT32, 0,
492 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
493 g_object_interface_install_property (iface, param_spec);
494 }
495