2001-10-18 Bradford Hovinen <hovinen@ximian.com> * bonobo-config-archiver.c (get_listener_oafiid): Update listener name
942 lines
21 KiB
C
942 lines
21 KiB
C
/**
|
|
* bonobo-config-archiver.c: XML configuration database with an interface to
|
|
* the XML archiver
|
|
*
|
|
* Author:
|
|
* Dietmar Maurer (dietmar@ximian.com)
|
|
* Bradford Hovinen <hovinen@ximian.com>
|
|
*
|
|
* Copyright 2000, 2001 Ximian, Inc.
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <ctype.h>
|
|
#include <bonobo.h>
|
|
#include <bonobo-conf/bonobo-config-utils.h>
|
|
#include <gnome-xml/xmlmemory.h>
|
|
#include <gtk/gtkmain.h>
|
|
|
|
#include "util.h"
|
|
#include "bonobo-config-archiver.h"
|
|
|
|
static GtkObjectClass *parent_class = NULL;
|
|
|
|
#define CLASS(o) BONOBO_CONFIG_ARCHIVER_CLASS (GTK_OBJECT(o)->klass)
|
|
|
|
#define PARENT_TYPE BONOBO_CONFIG_DATABASE_TYPE
|
|
#define FLUSH_INTERVAL 30 /* 30 seconds */
|
|
|
|
/* Small Bonobo bug here... */
|
|
|
|
#undef BONOBO_RET_EX
|
|
#define BONOBO_RET_EX(ev) \
|
|
G_STMT_START{ \
|
|
if (BONOBO_EX (ev)) \
|
|
return; \
|
|
}G_STMT_END
|
|
|
|
extern int daytime;
|
|
|
|
static DirEntry *
|
|
dir_lookup_entry (DirData *dir,
|
|
char *name,
|
|
gboolean create)
|
|
{
|
|
GSList *l;
|
|
DirEntry *de;
|
|
|
|
l = dir->entries;
|
|
|
|
while (l) {
|
|
de = (DirEntry *)l->data;
|
|
|
|
if (!strcmp (de->name, name))
|
|
return de;
|
|
|
|
l = l->next;
|
|
}
|
|
|
|
if (create) {
|
|
|
|
de = g_new0 (DirEntry, 1);
|
|
|
|
de->dir = dir;
|
|
|
|
de->name = g_strdup (name);
|
|
|
|
dir->entries = g_slist_prepend (dir->entries, de);
|
|
|
|
return de;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static DirData *
|
|
dir_lookup_subdir (DirData *dir,
|
|
char *name,
|
|
gboolean create)
|
|
{
|
|
GSList *l;
|
|
DirData *dd;
|
|
|
|
l = dir->subdirs;
|
|
|
|
while (l) {
|
|
dd = (DirData *)l->data;
|
|
|
|
if (!strcmp (dd->name, name))
|
|
return dd;
|
|
|
|
l = l->next;
|
|
}
|
|
|
|
if (create) {
|
|
|
|
dd = g_new0 (DirData, 1);
|
|
|
|
dd->dir = dir;
|
|
|
|
dd->name = g_strdup (name);
|
|
|
|
dir->subdirs = g_slist_prepend (dir->subdirs, dd);
|
|
|
|
return dd;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static DirData *
|
|
lookup_dir (DirData *dir,
|
|
const char *path,
|
|
gboolean create)
|
|
{
|
|
const char *s, *e;
|
|
char *name;
|
|
DirData *dd = dir;
|
|
|
|
s = path;
|
|
while (*s == '/') s++;
|
|
|
|
if (*s == '\0')
|
|
return dir;
|
|
|
|
if ((e = strchr (s, '/')))
|
|
name = g_strndup (s, e - s);
|
|
else
|
|
name = g_strdup (s);
|
|
|
|
if ((dd = dir_lookup_subdir (dd, name, create))) {
|
|
if (e)
|
|
dd = lookup_dir (dd, e, create);
|
|
|
|
g_free (name);
|
|
return dd;
|
|
|
|
} else {
|
|
g_free (name);
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
static DirEntry *
|
|
lookup_dir_entry (BonoboConfigArchiver *archiver_db,
|
|
const char *key,
|
|
gboolean create)
|
|
{
|
|
char *dir_name;
|
|
char *leaf_name;
|
|
DirEntry *de;
|
|
DirData *dd;
|
|
|
|
if ((dir_name = bonobo_config_dir_name (key))) {
|
|
dd = lookup_dir (archiver_db->dir, dir_name, create);
|
|
|
|
if (dd && !dd->node) {
|
|
dd->node = xmlNewChild (archiver_db->doc->root, NULL,
|
|
"section", NULL);
|
|
|
|
xmlSetProp (dd->node, "path", dir_name);
|
|
}
|
|
|
|
g_free (dir_name);
|
|
|
|
} else {
|
|
dd = archiver_db->dir;
|
|
|
|
if (!dd->node)
|
|
dd->node = xmlNewChild (archiver_db->doc->root, NULL,
|
|
"section", NULL);
|
|
}
|
|
|
|
if (!dd)
|
|
return NULL;
|
|
|
|
if (!(leaf_name = bonobo_config_leaf_name (key)))
|
|
return NULL;
|
|
|
|
de = dir_lookup_entry (dd, leaf_name, create);
|
|
|
|
g_free (leaf_name);
|
|
|
|
return de;
|
|
}
|
|
|
|
static CORBA_any *
|
|
real_get_value (BonoboConfigDatabase *db,
|
|
const CORBA_char *key,
|
|
const CORBA_char *locale,
|
|
CORBA_Environment *ev)
|
|
{
|
|
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
|
DirEntry *de;
|
|
CORBA_any *value = NULL;
|
|
|
|
de = lookup_dir_entry (archiver_db, key, FALSE);
|
|
if (!de) {
|
|
bonobo_exception_set (ev, ex_Bonobo_ConfigDatabase_NotFound);
|
|
return NULL;
|
|
}
|
|
|
|
if (de->value)
|
|
return bonobo_arg_copy (de->value);
|
|
|
|
/* localized value */
|
|
if (de->node && de->node->childs && de->node->childs->next)
|
|
value = bonobo_config_xml_decode_any ((BonoboUINode *)de->node,
|
|
locale, ev);
|
|
|
|
if (!value)
|
|
bonobo_exception_set (ev, ex_Bonobo_ConfigDatabase_NotFound);
|
|
|
|
return value;
|
|
}
|
|
|
|
/* Produce a new, dynamically allocated string with the OAF IID of the listener
|
|
* associated with the given backend id
|
|
*/
|
|
|
|
static gchar *
|
|
get_listener_oafiid (const gchar *backend_id)
|
|
{
|
|
gchar *oafiid, *tmp, *tmp1;
|
|
|
|
tmp = g_strdup (backend_id);
|
|
if ((tmp1 = strstr (tmp, "-properties")) != NULL) *tmp1 = '\0';
|
|
oafiid = g_strconcat ("OAFIID:Bonobo_Listener_Config_", tmp, NULL);
|
|
g_free (tmp);
|
|
|
|
return oafiid;
|
|
}
|
|
|
|
static void
|
|
real_sync (BonoboConfigDatabase *db,
|
|
CORBA_Environment *ev)
|
|
{
|
|
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
|
BonoboArg *arg;
|
|
|
|
gchar *listener_oafiid;
|
|
Bonobo_Listener listener;
|
|
|
|
if (!db->writeable)
|
|
return;
|
|
|
|
/* FIXME: This will not work correctly in the pathlogical case that two
|
|
* ConfigArchiver objects sync at almost exactly the same time.
|
|
*/
|
|
|
|
archiver_db->is_up_to_date = TRUE;
|
|
location_client_store_xml (archiver_db->location, archiver_db->backend_id,
|
|
archiver_db->doc, ConfigArchiver_STORE_MASK_PREVIOUS, ev);
|
|
|
|
BONOBO_RET_EX (ev);
|
|
|
|
/* Try to find a listener to apply the settings. If we can't, don't
|
|
* worry about it
|
|
*/
|
|
|
|
listener_oafiid = get_listener_oafiid (archiver_db->backend_id);
|
|
listener = bonobo_get_object (listener_oafiid, "IDL:Bonobo/Listener:1.0", ev);
|
|
g_free (listener_oafiid);
|
|
|
|
if (BONOBO_EX (ev)) {
|
|
listener = CORBA_OBJECT_NIL;
|
|
CORBA_exception_init (ev);
|
|
}
|
|
|
|
arg = bonobo_arg_new (BONOBO_ARG_NULL);
|
|
bonobo_event_source_notify_listeners (archiver_db->es, "Bonobo/ConfigDatabase:sync", arg, ev);
|
|
bonobo_arg_release (arg);
|
|
|
|
if (listener != CORBA_OBJECT_NIL)
|
|
bonobo_object_release_unref (listener, NULL);
|
|
}
|
|
|
|
static void
|
|
notify_listeners (BonoboConfigArchiver *archiver_db,
|
|
const char *key,
|
|
const CORBA_any *value)
|
|
{
|
|
CORBA_Environment ev;
|
|
char *dir_name;
|
|
char *leaf_name;
|
|
char *ename;
|
|
|
|
if (GTK_OBJECT_DESTROYED (archiver_db))
|
|
return;
|
|
|
|
if (!key)
|
|
return;
|
|
|
|
CORBA_exception_init (&ev);
|
|
|
|
ename = g_strconcat ("Bonobo/Property:change:", key, NULL);
|
|
|
|
bonobo_event_source_notify_listeners (archiver_db->es, ename, value, &ev);
|
|
|
|
g_free (ename);
|
|
|
|
if (!(dir_name = bonobo_config_dir_name (key)))
|
|
dir_name = g_strdup ("");
|
|
|
|
if (!(leaf_name = bonobo_config_leaf_name (key)))
|
|
leaf_name = g_strdup ("");
|
|
|
|
ename = g_strconcat ("Bonobo/ConfigDatabase:change", dir_name, ":",
|
|
leaf_name, NULL);
|
|
|
|
bonobo_event_source_notify_listeners (archiver_db->es, ename, value, &ev);
|
|
|
|
CORBA_exception_free (&ev);
|
|
|
|
g_free (ename);
|
|
g_free (dir_name);
|
|
g_free (leaf_name);
|
|
}
|
|
|
|
static void
|
|
real_set_value (BonoboConfigDatabase *db,
|
|
const CORBA_char *key,
|
|
const CORBA_any *value,
|
|
CORBA_Environment *ev)
|
|
{
|
|
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
|
DirEntry *de;
|
|
char *name;
|
|
|
|
de = lookup_dir_entry (archiver_db, key, TRUE);
|
|
|
|
if (de->value)
|
|
CORBA_free (de->value);
|
|
|
|
de->value = bonobo_arg_copy (value);
|
|
|
|
if (de->node) {
|
|
xmlUnlinkNode (de->node);
|
|
xmlFreeNode (de->node);
|
|
}
|
|
|
|
name = bonobo_config_leaf_name (key);
|
|
|
|
de->node = (xmlNodePtr) bonobo_config_xml_encode_any (value, name, ev);
|
|
|
|
g_free (name);
|
|
|
|
bonobo_ui_node_add_child ((BonoboUINode *)de->dir->node,
|
|
(BonoboUINode *)de->node);
|
|
|
|
notify_listeners (archiver_db, key, value);
|
|
}
|
|
|
|
static Bonobo_KeyList *
|
|
real_list_dirs (BonoboConfigDatabase *db,
|
|
const CORBA_char *dir,
|
|
CORBA_Environment *ev)
|
|
{
|
|
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
|
Bonobo_KeyList *key_list;
|
|
DirData *dd, *sub;
|
|
GSList *l;
|
|
int len;
|
|
|
|
key_list = Bonobo_KeyList__alloc ();
|
|
key_list->_length = 0;
|
|
|
|
if (!(dd = lookup_dir (archiver_db->dir, dir, FALSE)))
|
|
return key_list;
|
|
|
|
if (!(len = g_slist_length (dd->subdirs)))
|
|
return key_list;
|
|
|
|
key_list->_buffer = CORBA_sequence_CORBA_string_allocbuf (len);
|
|
CORBA_sequence_set_release (key_list, TRUE);
|
|
|
|
for (l = dd->subdirs; l != NULL; l = l->next) {
|
|
sub = (DirData *)l->data;
|
|
|
|
key_list->_buffer [key_list->_length] =
|
|
CORBA_string_dup (sub->name);
|
|
key_list->_length++;
|
|
}
|
|
|
|
return key_list;
|
|
}
|
|
|
|
static Bonobo_KeyList *
|
|
real_list_keys (BonoboConfigDatabase *db,
|
|
const CORBA_char *dir,
|
|
CORBA_Environment *ev)
|
|
{
|
|
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
|
Bonobo_KeyList *key_list;
|
|
DirData *dd;
|
|
DirEntry *de;
|
|
GSList *l;
|
|
int len;
|
|
|
|
key_list = Bonobo_KeyList__alloc ();
|
|
key_list->_length = 0;
|
|
|
|
if (!(dd = lookup_dir (archiver_db->dir, dir, FALSE)))
|
|
return key_list;
|
|
|
|
if (!(len = g_slist_length (dd->entries)))
|
|
return key_list;
|
|
|
|
key_list->_buffer = CORBA_sequence_CORBA_string_allocbuf (len);
|
|
CORBA_sequence_set_release (key_list, TRUE);
|
|
|
|
for (l = dd->entries; l != NULL; l = l->next) {
|
|
de = (DirEntry *)l->data;
|
|
|
|
key_list->_buffer [key_list->_length] =
|
|
CORBA_string_dup (de->name);
|
|
key_list->_length++;
|
|
}
|
|
|
|
return key_list;
|
|
}
|
|
|
|
static CORBA_boolean
|
|
real_dir_exists (BonoboConfigDatabase *db,
|
|
const CORBA_char *dir,
|
|
CORBA_Environment *ev)
|
|
{
|
|
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
|
|
|
if (lookup_dir (archiver_db->dir, dir, FALSE))
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
delete_dir_entry (DirEntry *de)
|
|
{
|
|
CORBA_free (de->value);
|
|
|
|
if (de->node) {
|
|
xmlUnlinkNode (de->node);
|
|
xmlFreeNode (de->node);
|
|
}
|
|
|
|
g_free (de->name);
|
|
g_free (de);
|
|
}
|
|
|
|
static void
|
|
real_remove_value (BonoboConfigDatabase *db,
|
|
const CORBA_char *key,
|
|
CORBA_Environment *ev)
|
|
{
|
|
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
|
DirEntry *de;
|
|
|
|
if (!(de = lookup_dir_entry (archiver_db, key, FALSE)))
|
|
return;
|
|
|
|
de->dir->entries = g_slist_remove (de->dir->entries, de);
|
|
|
|
delete_dir_entry (de);
|
|
}
|
|
|
|
static void
|
|
delete_dir_data (DirData *dd, gboolean is_root)
|
|
{
|
|
GSList *l;
|
|
|
|
for (l = dd->subdirs; l; l = l->next)
|
|
delete_dir_data ((DirData *)l->data, FALSE);
|
|
|
|
g_slist_free (dd->subdirs);
|
|
|
|
dd->subdirs = NULL;
|
|
|
|
for (l = dd->entries; l; l = l->next)
|
|
delete_dir_entry ((DirEntry *)l->data);
|
|
|
|
g_slist_free (dd->entries);
|
|
|
|
dd->entries = NULL;
|
|
|
|
if (!is_root) {
|
|
g_free (dd->name);
|
|
|
|
if (dd->node) {
|
|
xmlUnlinkNode (dd->node);
|
|
xmlFreeNode (dd->node);
|
|
}
|
|
|
|
g_free (dd);
|
|
}
|
|
}
|
|
|
|
static void
|
|
real_remove_dir (BonoboConfigDatabase *db,
|
|
const CORBA_char *dir,
|
|
CORBA_Environment *ev)
|
|
{
|
|
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
|
DirData *dd;
|
|
|
|
if (!(dd = lookup_dir (archiver_db->dir, dir, FALSE)))
|
|
return;
|
|
|
|
if (dd != archiver_db->dir && dd->dir)
|
|
dd->dir->subdirs = g_slist_remove (dd->dir->subdirs, dd);
|
|
|
|
delete_dir_data (dd, dd == archiver_db->dir);
|
|
}
|
|
|
|
static void
|
|
pb_get_fn (BonoboPropertyBag *bag, BonoboArg *arg,
|
|
guint arg_id, CORBA_Environment *ev,
|
|
gpointer user_data)
|
|
{
|
|
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (user_data);
|
|
time_t val;
|
|
|
|
val = ConfigArchiver_Location_getModificationTime
|
|
(archiver_db->location, archiver_db->backend_id, ev);
|
|
|
|
BONOBO_ARG_SET_GENERAL (arg, val, TC_ulonglong, CORBA_unsigned_long_long, NULL);
|
|
}
|
|
|
|
static void
|
|
pb_set_fn (BonoboPropertyBag *bag, const BonoboArg *arg,
|
|
guint arg_id, CORBA_Environment *ev,
|
|
gpointer user_data)
|
|
{
|
|
g_assert_not_reached ();
|
|
}
|
|
|
|
static void
|
|
bonobo_config_archiver_destroy (GtkObject *object)
|
|
{
|
|
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (object);
|
|
CORBA_Environment ev;
|
|
|
|
DEBUG_MSG ("Enter");
|
|
|
|
CORBA_exception_init (&ev);
|
|
|
|
if (archiver_db->moniker != NULL) {
|
|
bonobo_url_unregister ("BONOBO_CONF:ARCHIVER", archiver_db->moniker, &ev);
|
|
g_free (archiver_db->moniker);
|
|
|
|
if (BONOBO_EX (&ev)) {
|
|
g_critical ("Could not unregister the archiver URL");
|
|
CORBA_exception_init (&ev);
|
|
}
|
|
}
|
|
|
|
if (archiver_db->listener_id != 0) {
|
|
bonobo_event_source_client_remove_listener
|
|
(archiver_db->location, archiver_db->listener_id, &ev);
|
|
|
|
if (BONOBO_EX (&ev))
|
|
g_critical ("Could not remove the rollback data listener");
|
|
}
|
|
|
|
CORBA_exception_free (&ev);
|
|
|
|
if (archiver_db->doc != NULL) {
|
|
delete_dir_data (archiver_db->dir, TRUE);
|
|
archiver_db->dir = NULL;
|
|
xmlFreeDoc (archiver_db->doc);
|
|
}
|
|
|
|
if (archiver_db->filename != NULL)
|
|
g_free (archiver_db->filename);
|
|
|
|
if (archiver_db->fp != NULL)
|
|
fclose (archiver_db->fp);
|
|
|
|
if (archiver_db->location != CORBA_OBJECT_NIL)
|
|
bonobo_object_release_unref (archiver_db->location, NULL);
|
|
|
|
if (archiver_db->archive != CORBA_OBJECT_NIL)
|
|
bonobo_object_release_unref (archiver_db->archive, NULL);
|
|
|
|
parent_class->destroy (object);
|
|
|
|
DEBUG_MSG ("Exit");
|
|
}
|
|
|
|
|
|
static void
|
|
bonobo_config_archiver_class_init (BonoboConfigDatabaseClass *class)
|
|
{
|
|
GtkObjectClass *object_class = (GtkObjectClass *) class;
|
|
BonoboConfigDatabaseClass *cd_class;
|
|
|
|
parent_class = gtk_type_class (PARENT_TYPE);
|
|
|
|
object_class->destroy = bonobo_config_archiver_destroy;
|
|
|
|
cd_class = BONOBO_CONFIG_DATABASE_CLASS (class);
|
|
|
|
cd_class->get_value = real_get_value;
|
|
cd_class->set_value = real_set_value;
|
|
cd_class->list_dirs = real_list_dirs;
|
|
cd_class->list_keys = real_list_keys;
|
|
cd_class->dir_exists = real_dir_exists;
|
|
cd_class->remove_value = real_remove_value;
|
|
cd_class->remove_dir = real_remove_dir;
|
|
cd_class->sync = real_sync;
|
|
}
|
|
|
|
static void
|
|
bonobo_config_archiver_init (BonoboConfigArchiver *archiver_db)
|
|
{
|
|
archiver_db->dir = g_new0 (DirData, 1);
|
|
|
|
/* This will always be writeable */
|
|
BONOBO_CONFIG_DATABASE (archiver_db)->writeable = TRUE;
|
|
}
|
|
|
|
BONOBO_X_TYPE_FUNC (BonoboConfigArchiver, PARENT_TYPE, bonobo_config_archiver);
|
|
|
|
static void
|
|
read_section (DirData *dd)
|
|
{
|
|
CORBA_Environment ev;
|
|
DirEntry *de;
|
|
xmlNodePtr s;
|
|
gchar *name;
|
|
|
|
CORBA_exception_init (&ev);
|
|
|
|
s = dd->node->childs;
|
|
|
|
while (s) {
|
|
if (s->type == XML_ELEMENT_NODE &&
|
|
!strcmp (s->name, "entry") &&
|
|
(name = xmlGetProp(s, "name"))) {
|
|
|
|
de = dir_lookup_entry (dd, name, TRUE);
|
|
|
|
de->node = s;
|
|
|
|
/* we only decode it if it is a single value,
|
|
* multiple (localized) values are decoded in the
|
|
* get_value function */
|
|
if (!(s->childs && s->childs->next))
|
|
de->value = bonobo_config_xml_decode_any
|
|
((BonoboUINode *)s, NULL, &ev);
|
|
|
|
xmlFree (name);
|
|
}
|
|
s = s->next;
|
|
}
|
|
|
|
CORBA_exception_free (&ev);
|
|
}
|
|
|
|
static void
|
|
fill_cache (BonoboConfigArchiver *archiver_db)
|
|
{
|
|
xmlNodePtr n;
|
|
gchar *path;
|
|
DirData *dd;
|
|
|
|
n = archiver_db->doc->root->childs;
|
|
|
|
while (n) {
|
|
if (n->type == XML_ELEMENT_NODE &&
|
|
!strcmp (n->name, "section")) {
|
|
|
|
path = xmlGetProp(n, "path");
|
|
|
|
if (!path || !strcmp (path, "")) {
|
|
dd = archiver_db->dir;
|
|
} else
|
|
dd = lookup_dir (archiver_db->dir, path, TRUE);
|
|
|
|
if (!dd->node)
|
|
dd->node = n;
|
|
|
|
read_section (dd);
|
|
|
|
xmlFree (path);
|
|
}
|
|
n = n->next;
|
|
}
|
|
}
|
|
|
|
/* parse_name
|
|
*
|
|
* Given a moniker with a backend id and (possibly) a location id encoded
|
|
* therein, parse out the backend id and the location id and set the pointers
|
|
* given to them.
|
|
*
|
|
* FIXME: Is this encoding really the way we want to do this? Ask Dietmar and
|
|
* Michael.
|
|
*/
|
|
|
|
static gboolean
|
|
parse_name (const gchar *name, gchar **backend_id, gchar **location, struct tm **date)
|
|
{
|
|
gchar *e, *e1, *time_str = NULL;
|
|
|
|
*date = NULL;
|
|
|
|
if (name[0] == '[') {
|
|
e = strchr (name + 1, '|');
|
|
|
|
if (e != NULL) {
|
|
*location = g_strndup (name + 1, e - (name + 1));
|
|
e1 = strchr (e + 1, ']');
|
|
|
|
if (e1 != NULL) {
|
|
time_str = g_strndup (e + 1, e1 - (e + 1));
|
|
*date = parse_date (time_str);
|
|
g_free (time_str);
|
|
}
|
|
|
|
*backend_id = g_strdup (e1 + 1);
|
|
} else {
|
|
e = strchr (name + 1, ']');
|
|
|
|
if (e != NULL)
|
|
*location = g_strndup (name + 1, e - (name + 1));
|
|
else
|
|
return FALSE;
|
|
|
|
*backend_id = g_strdup (e + 1);
|
|
}
|
|
} else {
|
|
*backend_id = g_strdup (name);
|
|
*location = NULL;
|
|
}
|
|
|
|
if (*location != NULL && **location == '\0') {
|
|
g_free (*location);
|
|
*location = NULL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
new_rollback_cb (BonoboListener *listener,
|
|
gchar *event_name,
|
|
CORBA_any *any,
|
|
CORBA_Environment *ev,
|
|
BonoboConfigArchiver *archiver_db)
|
|
{
|
|
BonoboArg *arg;
|
|
|
|
if (archiver_db->is_up_to_date) {
|
|
archiver_db->is_up_to_date = FALSE;
|
|
return;
|
|
}
|
|
|
|
if (archiver_db->dir != NULL) {
|
|
delete_dir_data (archiver_db->dir, TRUE);
|
|
g_free (archiver_db->dir->name);
|
|
g_free (archiver_db->dir);
|
|
archiver_db->dir = g_new0 (DirData, 1);
|
|
}
|
|
|
|
if (archiver_db->doc != NULL)
|
|
xmlFreeDoc (archiver_db->doc);
|
|
|
|
archiver_db->doc = location_client_load_rollback_data
|
|
(archiver_db->location, NULL, 0, archiver_db->backend_id, TRUE, ev);
|
|
|
|
if (archiver_db->doc == NULL)
|
|
g_critical ("Could not load new rollback data");
|
|
else
|
|
fill_cache (archiver_db);
|
|
|
|
arg = bonobo_arg_new (BONOBO_ARG_NULL);
|
|
bonobo_event_source_notify_listeners (archiver_db->es, "Bonobo/ConfigDatabase:sync", arg, ev);
|
|
bonobo_arg_release (arg);
|
|
}
|
|
|
|
Bonobo_ConfigDatabase
|
|
bonobo_config_archiver_new (Bonobo_Moniker parent,
|
|
const Bonobo_ResolveOptions *options,
|
|
const char *moniker,
|
|
CORBA_Environment *ev)
|
|
{
|
|
BonoboConfigArchiver *archiver_db;
|
|
Bonobo_ConfigDatabase db;
|
|
ConfigArchiver_Archive archive;
|
|
ConfigArchiver_Location location;
|
|
gchar *moniker_tmp;
|
|
gchar *backend_id;
|
|
gchar *location_id;
|
|
struct tm *date;
|
|
|
|
g_return_val_if_fail (backend_id != NULL, NULL);
|
|
|
|
/* Check the Bonobo URL database to see if this archiver database has
|
|
* already been created, and return it if it has */
|
|
|
|
moniker_tmp = g_strdup (moniker);
|
|
db = bonobo_url_lookup ("BONOBO_CONF:ARCHIVER", moniker_tmp, ev);
|
|
g_free (moniker_tmp);
|
|
|
|
if (BONOBO_EX (ev)) {
|
|
db = CORBA_OBJECT_NIL;
|
|
CORBA_exception_init (ev);
|
|
}
|
|
|
|
if (db != CORBA_OBJECT_NIL)
|
|
return bonobo_object_dup_ref (db, NULL);
|
|
|
|
/* Parse out the backend id, location id, and rollback date from the
|
|
* moniker given */
|
|
|
|
if (parse_name (moniker, &backend_id, &location_id, &date) < 0) {
|
|
EX_SET_NOT_FOUND (ev);
|
|
return CORBA_OBJECT_NIL;
|
|
}
|
|
|
|
/* Resolve the parent archive and the location */
|
|
|
|
archive = Bonobo_Moniker_resolve (parent, options, "IDL:ConfigArchiver/Archive:1.0", ev);
|
|
|
|
if (BONOBO_EX (ev) || archive == CORBA_OBJECT_NIL) {
|
|
g_free (location_id);
|
|
g_free (date);
|
|
return CORBA_OBJECT_NIL;
|
|
}
|
|
|
|
if (location_id == NULL || *location_id == '\0')
|
|
location = ConfigArchiver_Archive__get_currentLocation (archive, ev);
|
|
else
|
|
location = ConfigArchiver_Archive_getLocation (archive, location_id, ev);
|
|
|
|
g_free (location_id);
|
|
|
|
if (location == CORBA_OBJECT_NIL) {
|
|
g_free (date);
|
|
bonobo_object_release_unref (archive, NULL);
|
|
return CORBA_OBJECT_NIL;
|
|
}
|
|
|
|
/* Construct the database object proper and fill in its values */
|
|
|
|
if ((archiver_db = gtk_type_new (BONOBO_CONFIG_ARCHIVER_TYPE)) == NULL) {
|
|
g_free (date);
|
|
return CORBA_OBJECT_NIL;
|
|
}
|
|
|
|
archiver_db->backend_id = backend_id;
|
|
archiver_db->moniker = g_strdup (moniker);
|
|
archiver_db->archive = archive;
|
|
archiver_db->location = location;
|
|
|
|
/* Load the XML data, or use the defaults file if none are present */
|
|
|
|
archiver_db->doc = location_client_load_rollback_data
|
|
(archiver_db->location, date, 0, archiver_db->backend_id, TRUE, ev);
|
|
g_free (date);
|
|
|
|
if (BONOBO_EX (ev) || archiver_db->doc == NULL) {
|
|
gchar *filename;
|
|
|
|
filename = g_strconcat (GNOMECC_DEFAULTS_DIR "/", archiver_db->backend_id, ".xml", NULL);
|
|
archiver_db->doc = xmlParseFile (filename);
|
|
g_free (filename);
|
|
|
|
if (archiver_db->doc == NULL) {
|
|
bonobo_object_release_unref (archiver_db->location, NULL);
|
|
bonobo_object_release_unref (archiver_db->archive, NULL);
|
|
bonobo_object_unref (BONOBO_OBJECT (archiver_db));
|
|
return CORBA_OBJECT_NIL;
|
|
}
|
|
|
|
CORBA_exception_init (ev);
|
|
}
|
|
|
|
/* Load data from the XML file */
|
|
|
|
if (archiver_db->doc->root == NULL)
|
|
archiver_db->doc->root =
|
|
xmlNewDocNode (archiver_db->doc, NULL, "bonobo-config", NULL);
|
|
|
|
if (strcmp (archiver_db->doc->root->name, "bonobo-config")) {
|
|
xmlFreeDoc (archiver_db->doc);
|
|
archiver_db->doc = xmlNewDoc("1.0");
|
|
archiver_db->doc->root =
|
|
xmlNewDocNode (archiver_db->doc, NULL, "bonobo-config", NULL);
|
|
}
|
|
|
|
fill_cache (archiver_db);
|
|
|
|
/* Construct the associated property bag and event source */
|
|
|
|
#if 0
|
|
archiver_db->es = bonobo_event_source_new ();
|
|
|
|
bonobo_object_add_interface (BONOBO_OBJECT (archiver_db),
|
|
BONOBO_OBJECT (archiver_db->es));
|
|
#endif
|
|
|
|
archiver_db->pb = bonobo_property_bag_new (pb_get_fn,
|
|
pb_set_fn,
|
|
archiver_db);
|
|
|
|
bonobo_object_add_interface (BONOBO_OBJECT (archiver_db),
|
|
BONOBO_OBJECT (archiver_db->pb));
|
|
|
|
archiver_db->es = archiver_db->pb->es;
|
|
|
|
bonobo_property_bag_add (archiver_db->pb,
|
|
"last_modified", 1, TC_ulonglong, NULL,
|
|
"Date (time_t) of modification",
|
|
BONOBO_PROPERTY_READABLE);
|
|
|
|
/* Listen for events pertaining to new rollback data */
|
|
|
|
if (date == NULL && location_id == NULL)
|
|
archiver_db->listener_id =
|
|
bonobo_event_source_client_add_listener
|
|
(location, (BonoboListenerCallbackFn) new_rollback_cb,
|
|
"ConfigArchiver/Location:newRollbackData", ev, archiver_db);
|
|
else
|
|
archiver_db->listener_id = 0;
|
|
|
|
/* Prepare to return the database object */
|
|
|
|
db = CORBA_Object_duplicate (BONOBO_OBJREF (archiver_db), NULL);
|
|
|
|
moniker_tmp = g_strdup (moniker);
|
|
bonobo_url_register ("BONOBO_CONF:ARCHIVER", moniker_tmp, NULL, db, ev);
|
|
g_free (moniker_tmp);
|
|
|
|
return db;
|
|
}
|