/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ /* * oafd: OAF CORBA dameon. * * Copyright (C) 1999, 2000 Red Hat, Inc. * Copyright (C) 1999, 2000 Eazel, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Authors: Elliot Lee , * */ #include "config.h" #include #include #include "oafd.h" #include "oaf-i18n.h" #include "liboaf/liboaf.h" #include "ac-query-expr.h" #include "oafd-corba-extensions.h" #define OAF_LINK_TIME_TO_LIVE 256 typedef struct { OAF_ObjectDirectory obj; char *hostname, *username, *domain; OAF_ServerInfoList *list; OAF_CacheTime time_list_pulled; GHashTable *by_iid; GHashTable *active_servers; /* It is assumed that accesses to this * hash table are atomic - i.e. a CORBA * call cannot come in while * checking a value in this table */ OAF_ServerStateCache *active_server_list; OAF_CacheTime time_active_pulled; guchar locked; } ChildODInfo; /* forward declarations */ char *ac_aid_to_query_string (OAF_ActivationID aid); void ac_context_to_string_array (CORBA_Context context, char *sort_criteria[4], CORBA_Environment *ev); static ChildODInfo * child_od_info_new (OAF_ObjectDirectory obj, CORBA_Environment * ev) { ChildODInfo *retval; char *host, *domain, *user; host = OAF_ObjectDirectory__get_hostname (obj, ev); if (ev->_major != CORBA_NO_EXCEPTION) goto errhost; domain = OAF_ObjectDirectory__get_domain (obj, ev); if (ev->_major != CORBA_NO_EXCEPTION) goto errdomain; user = OAF_ObjectDirectory__get_username (obj, ev); if (ev->_major != CORBA_NO_EXCEPTION) goto erruser; retval = g_new0 (ChildODInfo, 1); retval->obj = CORBA_Object_duplicate (obj, ev); retval->hostname = host; retval->username = user; retval->domain = domain; return retval; erruser: CORBA_free (domain); errdomain: CORBA_free (host); errhost: return NULL; } static void child_od_exception (ChildODInfo * child, CORBA_Environment * ev) { CORBA_Object_release (child->obj, ev); child->obj = CORBA_OBJECT_NIL; } static void child_od_update_active (ChildODInfo * child, CORBA_Environment * ev) { int i; OAF_ServerStateCache *cache; cache = OAF_ObjectDirectory_get_active_servers (child->obj, child->time_active_pulled, ev); if (ev->_major != CORBA_NO_EXCEPTION) { child_od_exception (child, ev); return; } if (cache->_d) { if (child->active_servers) { g_hash_table_destroy (child->active_servers); CORBA_free (child->active_server_list); } child->active_server_list = cache; child->time_active_pulled = time (NULL); child->active_servers = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_freeze (child->active_servers); for (i = 0; i < cache->_u.active_servers._length; i++) g_hash_table_insert (child->active_servers, cache->_u. active_servers._buffer[i], GINT_TO_POINTER (1)); g_hash_table_thaw (child->active_servers); } else CORBA_free (cache); } static void child_od_update_list (ChildODInfo * child, CORBA_Environment * ev) { int i; OAF_ServerInfoListCache *cache; cache = OAF_ObjectDirectory_get_servers (child->obj, child->time_list_pulled, ev); if (ev->_major != CORBA_NO_EXCEPTION) { child->list = NULL; child_od_exception (child, ev); return; } if (cache->_d) { if (child->by_iid) g_hash_table_destroy (child->by_iid); if (child->list) { CORBA_sequence_set_release (child->list, CORBA_TRUE); CORBA_free (child->list); child->list = NULL; } child->list = OAF_ServerInfoList__alloc (); *(child->list) = cache->_u.server_list; CORBA_sequence_set_release (child->list, CORBA_FALSE); CORBA_sequence_set_release (&(cache->_u.server_list), CORBA_FALSE); child->time_list_pulled = time (NULL); child->by_iid = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_freeze (child->by_iid); for (i = 0; i < child->list->_length; i++) g_hash_table_insert (child->by_iid, child->list->_buffer[i].iid, &(child->list->_buffer[i])); g_hash_table_thaw (child->by_iid); } CORBA_free (cache); } static void child_od_info_free (ChildODInfo * child, CORBA_Environment * ev) { CORBA_Object_release (child->obj, ev); CORBA_free (child->hostname); CORBA_free (child->username); CORBA_free (child->domain); g_free (child); } static char * ac_CORBA_Context_get_value (CORBA_Context ctx, const char *propname, CORBA_Environment *ev) { return oafd_CORBA_Context_get_value (ctx, propname, ex_OAF_ActivationContext_IncompleteContext, ev); } /*** App-specific servant structures ***/ typedef struct { POA_OAF_ActivationContext servant; PortableServer_POA poa; GSList *dirs; int total_servers; gint refs; /* This is a use count, so we don't accidentally go * updating our server list and invalidating memory */ OAF_ActivationContext me; } impl_POA_OAF_ActivationContext; /*** Implementation stub prototypes ***/ static OAF_ObjectDirectoryList * impl_OAF_ActivationContext__get_directories (impl_POA_OAF_ActivationContext * servant, CORBA_Environment * ev); static void impl_OAF_ActivationContext_add_directory (impl_POA_OAF_ActivationContext * servant, OAF_ObjectDirectory dir, CORBA_Environment * ev); static void impl_OAF_ActivationContext_remove_directory (impl_POA_OAF_ActivationContext * servant, OAF_ObjectDirectory dir, CORBA_Environment * ev); static OAF_ActivationResult * impl_OAF_ActivationContext_activate (impl_POA_OAF_ActivationContext * servant, CORBA_char * requirements, GNOME_stringlist * selection_order, OAF_ActivationFlags flags, CORBA_Context ctx, CORBA_Environment * ev); static void impl_OAF_ActivationContext_activate_async(impl_POA_OAF_ActivationContext * servant, CORBA_char * requirements, GNOME_stringlist * selection_order, OAF_ActivationFlags flags, OAF_ActivationCallback callback_object, CORBA_Context ctx, CORBA_Environment * ev); static OAF_ServerInfoList * impl_OAF_ActivationContext__get_servers (impl_POA_OAF_ActivationContext * servant, CORBA_Environment * ev); static OAF_ServerInfoList * impl_OAF_ActivationContext_query (impl_POA_OAF_ActivationContext * servant, CORBA_char * requirements, GNOME_stringlist * selection_order, CORBA_Context ctx, CORBA_Environment * ev); static OAF_ActivationResult * impl_OAF_ActivationContext_activate_from_id (impl_POA_OAF_ActivationContext * servant, OAF_ActivationID aid, OAF_ActivationFlags flags, CORBA_Context ctx, CORBA_Environment * ev); static void impl_OAF_ActivationContext_activate_from_id_async (impl_POA_OAF_ActivationContext * servant, OAF_ActivationID aid, OAF_ActivationFlags flags, OAF_ActivationCallback callback_object, CORBA_Context ctx, CORBA_Environment * ev); static void ac_query_run (impl_POA_OAF_ActivationContext * servant, CORBA_char * requirements, GNOME_stringlist * selection_order, CORBA_Context ctx, OAF_ServerInfo ** items, CORBA_Environment * ev); static ChildODInfo *ac_find_child_for_server (impl_POA_OAF_ActivationContext * servant, OAF_ServerInfo * server, CORBA_Environment * ev); static void ac_update_lists (impl_POA_OAF_ActivationContext * servant, CORBA_Environment * ev); /*** epv structures ***/ static PortableServer_ServantBase__epv impl_OAF_ActivationContext_base_epv = { NULL, /* _private data */ NULL, /* finalize routine */ NULL /* default_POA routine */ }; static POA_OAF_ActivationContext__epv impl_OAF_ActivationContext_epv = { NULL, /* _private */ (gpointer) &impl_OAF_ActivationContext__get_directories, (gpointer) &impl_OAF_ActivationContext_add_directory, (gpointer) &impl_OAF_ActivationContext_remove_directory, (gpointer) &impl_OAF_ActivationContext_activate, (gpointer) &impl_OAF_ActivationContext_activate_async, (gpointer) &impl_OAF_ActivationContext__get_servers, (gpointer) &impl_OAF_ActivationContext_query, (gpointer) &impl_OAF_ActivationContext_activate_from_id, (gpointer) &impl_OAF_ActivationContext_activate_from_id_async }; /*** vepv structures ***/ static POA_OAF_ActivationContext__vepv impl_OAF_ActivationContext_vepv = { &impl_OAF_ActivationContext_base_epv, &impl_OAF_ActivationContext_epv }; /*** Stub implementations ***/ OAF_ActivationContext OAF_ActivationContext_create (PortableServer_POA poa, CORBA_Environment * ev) { OAF_ActivationContext retval; impl_POA_OAF_ActivationContext *newservant; PortableServer_ObjectId *objid; newservant = g_new0 (impl_POA_OAF_ActivationContext, 1); newservant->servant.vepv = &impl_OAF_ActivationContext_vepv; newservant->poa = poa; POA_OAF_ActivationContext__init ((PortableServer_Servant) newservant, ev); objid = PortableServer_POA_activate_object (poa, newservant, ev); CORBA_free (objid); retval = newservant->me = PortableServer_POA_servant_to_reference (poa, newservant, ev); return CORBA_Object_duplicate (retval, ev); } static void ac_update_list (impl_POA_OAF_ActivationContext * servant, ChildODInfo * child, CORBA_Environment * ev) { int prev, new; if (servant->refs > 0) return; if (child->list) prev = child->list->_length; else prev = 0; child_od_update_list (child, ev); if (child->list) new = child->list->_length; else new = 0; servant->total_servers += (new - prev); } static OAF_ObjectDirectoryList * impl_OAF_ActivationContext__get_directories (impl_POA_OAF_ActivationContext * servant, CORBA_Environment * ev) { OAF_ObjectDirectoryList *retval; int i; GSList *cur; retval = OAF_ObjectDirectoryList__alloc (); retval->_length = g_slist_length (servant->dirs); retval->_buffer = CORBA_sequence_OAF_ObjectDirectory_allocbuf (retval->_length); for (i = 0, cur = servant->dirs; cur; cur = cur->next, i++) { ChildODInfo *child; child = cur->data; retval->_buffer[i] = CORBA_Object_duplicate (child->obj, ev); } CORBA_sequence_set_release (retval, CORBA_TRUE); return retval; } static void impl_OAF_ActivationContext_add_directory (impl_POA_OAF_ActivationContext * servant, OAF_ObjectDirectory dir, CORBA_Environment * ev) { GSList *cur; ChildODInfo *new_child; for (cur = servant->dirs; cur; cur = cur->next) { ChildODInfo *child; child = cur->data; if (CORBA_Object_is_equivalent (dir, child->obj, ev)) { CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_OAF_ActivationContext_AlreadyListed, NULL); return; } } new_child = child_od_info_new (dir, ev); if (new_child) servant->dirs = g_slist_append (servant->dirs, new_child); } static void impl_OAF_ActivationContext_remove_directory (impl_POA_OAF_ActivationContext * servant, OAF_ObjectDirectory dir, CORBA_Environment * ev) { GSList *cur; for (cur = servant->dirs; cur; cur = cur->next) { ChildODInfo *child; child = cur->data; if (CORBA_Object_is_equivalent (dir, child->obj, ev)) { if (servant->refs) { CORBA_Object_release (child->obj, ev); child->obj = CORBA_OBJECT_NIL; } else { servant->dirs = g_slist_remove (servant->dirs, child); child_od_info_free (child, ev); } break; } } if (cur == NULL) { CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_OAF_ActivationContext_NotListed, NULL); } } static void ac_do_activation (impl_POA_OAF_ActivationContext *servant, OAF_ServerInfo *server, OAF_ActivationResult *out, OAF_ActivationFlags flags, const char *hostname, CORBA_Context ctx, CORBA_Environment *ev) { ChildODInfo *child; OAF_ServerInfo *activatable; int num_layers; /* When doing checks for shlib loadability, we * have to find the info on the factory object in case * a factory is inside a shlib */ child = ac_find_child_for_server (servant, server, ev); if (!child || !child->obj || ev->_major != CORBA_NO_EXCEPTION) { OAF_GeneralError *errval = OAF_GeneralError__alloc (); errval->description = CORBA_string_dup (_("Couldn't find which child the server was listed in")); CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_OAF_GeneralError, errval); return; } for (num_layers = 0, activatable = server; activatable && activatable->server_type && !strcmp (activatable->server_type, "factory") && num_layers < OAF_LINK_TIME_TO_LIVE; num_layers++) { activatable = g_hash_table_lookup (child->by_iid, activatable->location_info); } if (activatable == NULL) { OAF_GeneralError *errval = OAF_GeneralError__alloc (); errval->description = CORBA_string_dup ("Couldn't find the factory server"); CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_OAF_GeneralError, errval); return; } else if (num_layers == OAF_LINK_TIME_TO_LIVE) { OAF_GeneralError *errval = OAF_GeneralError__alloc (); errval->description = CORBA_string_dup ("Location loop"); CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_OAF_GeneralError, errval); return; } /* A shared library must be on the same host as the activator * in order for loading to work properly (no, we're not going * to bother with loading a remote shlib into a process - it * gets far too complicated far too quickly :-) */ if (activatable && !strcmp (activatable->server_type, "shlib") && !(flags & OAF_FLAG_NO_LOCAL) && (hostname && !strcmp (activatable->hostname, hostname))) { int j; char tbuf[512]; out->res._d = OAF_RESULT_SHLIB; /* Here is an explanation as to why we add 2 to num_layers. * At the end of the string list, after all the factory iids are added * to the string list, we then add the iid of the shaed library and the * location info. This data is later used in oaf_server_activate_shlib * to activate the component */ out->res._u.res_shlib._length = num_layers + 2; out->res._u.res_shlib._buffer = CORBA_sequence_CORBA_string_allocbuf (num_layers + 2); /* Copy over factory info */ for (j = 0, activatable = server; activatable && !strcmp (activatable->server_type, "factory"); j++) { out->res._u.res_shlib._buffer[j] = CORBA_string_dup (activatable->iid); activatable = g_hash_table_lookup (child->by_iid, activatable->location_info); } /* Copy shlib iid into buffer */ out->res._u.res_shlib._buffer[j] = CORBA_string_dup (activatable->iid); /* Copy location into last buffer slot for use in later activation */ out->res._u.res_shlib._buffer[j+1] = CORBA_string_dup (activatable->location_info); g_snprintf (tbuf, sizeof (tbuf), "OAFAID:[%s,%s,%s,%s]", activatable->iid, activatable->username, activatable->hostname, activatable->domain); out->aid = CORBA_string_dup (tbuf); } else { CORBA_Object retval; retval = OAF_ObjectDirectory_activate (child->obj, server->iid, servant->me, flags, ctx, ev); if (ev->_major == CORBA_NO_EXCEPTION) { char tbuf[512]; out->res._d = OAF_RESULT_OBJECT; out->res._u.res_object = retval; g_snprintf (tbuf, sizeof (tbuf), "OAFAID:[%s,%s,%s,%s]", activatable->iid, activatable->username, activatable->hostname, activatable->domain); out->aid = CORBA_string_dup (tbuf); } } } static OAF_ActivationResult * impl_OAF_ActivationContext_activate (impl_POA_OAF_ActivationContext * servant, CORBA_char * requirements, GNOME_stringlist * selection_order, OAF_ActivationFlags flags, CORBA_Context ctx, CORBA_Environment * ev) { OAF_ActivationResult *retval = NULL; OAF_ServerInfo **items, *curitem; int i; char *hostname; hostname = ac_CORBA_Context_get_value (ctx, "hostname", ev); ac_update_lists (servant, ev); servant->refs++; items = oaf_alloca (servant->total_servers * sizeof (OAF_ServerInfo *)); ac_query_run (servant, requirements, selection_order, ctx, items, ev); if (ev->_major != CORBA_NO_EXCEPTION) { goto out; } retval = OAF_ActivationResult__alloc (); retval->res._d = OAF_RESULT_NONE; if (items[0] == NULL) { OAF_GeneralError *errval = OAF_GeneralError__alloc (); errval->description = CORBA_string_dup (_("Nothing matched the requirements.")); CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_OAF_GeneralError, errval); goto out; } for (i = 0; (retval->res._d == OAF_RESULT_NONE) && items[i] != NULL && (i < servant->total_servers); i++) { curitem = items[i]; ac_do_activation (servant, curitem, retval, flags, hostname, ctx, ev); if (ev->_major != CORBA_NO_EXCEPTION) { goto out; } } if (retval->res._d == OAF_RESULT_NONE) retval->aid = CORBA_string_dup (""); out: g_free (hostname); servant->refs--; return retval; } static void impl_OAF_ActivationContext_activate_async(impl_POA_OAF_ActivationContext * servant, CORBA_char * requirements, GNOME_stringlist * selection_order, OAF_ActivationFlags flags, OAF_ActivationCallback callback_object, CORBA_Context ctx, CORBA_Environment * ev) { OAF_ActivationResult *retval = NULL; OAF_ServerInfo **items, *curitem; int i; char *hostname; hostname = ac_CORBA_Context_get_value (ctx, "hostname", ev); ac_update_lists (servant, ev); servant->refs++; items = oaf_alloca (servant->total_servers * sizeof (OAF_ServerInfo *)); ac_query_run (servant, requirements, selection_order, ctx, items, ev); if (ev->_major != CORBA_NO_EXCEPTION) { char *message; g_free (hostname); servant->refs--; message = g_strconcat(_("Query failed: "), CORBA_exception_id (ev), NULL); OAF_ActivationCallback_report_activation_failed (callback_object, message, ev); g_free (message); return; } retval = OAF_ActivationResult__alloc (); retval->res._d = OAF_RESULT_NONE; for (i = 0; (retval->res._d == OAF_RESULT_NONE) && items[i] && (i < servant->total_servers); i++) { curitem = items[i]; ac_do_activation (servant, curitem, retval, flags, hostname, ctx, ev); } if (retval->res._d == OAF_RESULT_NONE) retval->aid = CORBA_string_dup (""); if (ev->_major != CORBA_NO_EXCEPTION) { char *message; g_free (hostname); CORBA_free (retval); servant->refs--; message = g_strconcat(_("Activation failed: "), CORBA_exception_id (ev), NULL); OAF_ActivationCallback_report_activation_failed (callback_object, message, ev); g_free (message); return; } g_free (hostname); /* return the correct value back to the client */ OAF_ActivationCallback_report_activation_succeeded (callback_object, retval, ev); } static void ac_update_lists (impl_POA_OAF_ActivationContext * servant, CORBA_Environment * ev) { GSList *cur; if (servant->refs > 0) return; for (cur = servant->dirs; cur; cur = cur->next) ac_update_list (servant, cur->data, ev); } static OAF_ServerInfoList * impl_OAF_ActivationContext__get_servers (impl_POA_OAF_ActivationContext * servant, CORBA_Environment * ev) { OAF_ServerInfoList *retval; GSList *cur; int i; int total; ac_update_lists (servant, ev); total = servant->total_servers; retval = OAF_ServerInfoList__alloc (); retval->_length = total; retval->_buffer = CORBA_sequence_OAF_ServerInfo_allocbuf (total); CORBA_sequence_set_release (retval, CORBA_TRUE); for (i = 0; i < total;) { for (cur = servant->dirs; cur; cur = cur->next) { ChildODInfo *child; int j; child = cur->data; for (j = 0; j < child->list->_length; j++, i++) OAF_ServerInfo_copy (&retval->_buffer[i], &child-> list->_buffer[j]); } } return retval; } static ChildODInfo * ac_find_child_for_server (impl_POA_OAF_ActivationContext * servant, OAF_ServerInfo * server, CORBA_Environment * ev) { GSList *cur; for (cur = servant->dirs; cur; cur = cur->next) { ChildODInfo *child = cur->data; if (CORBA_Object_is_nil (child->obj, ev) || !child->list) continue; if ((server >= child->list->_buffer) && (server < (child->list->_buffer + child->list->_length))) return child; } return NULL; } static QueryExprConst ac_query_get_var (OAF_ServerInfo * si, const char *id, QueryContext * qctx) { ChildODInfo *child; QueryExprConst retval; retval.value_known = FALSE; retval.needs_free = FALSE; child = ac_find_child_for_server (qctx->user_data, si, NULL); if (!child) goto out; if (!strcasecmp (id, "_active")) { CORBA_Environment ev; CORBA_exception_init (&ev); child_od_update_active (child, &ev); CORBA_exception_free (&ev); retval.value_known = TRUE; retval.type = CONST_BOOLEAN; retval.u.v_boolean = g_hash_table_lookup (child->active_servers, si->iid) ? TRUE : FALSE; } out: return retval; } /* This function should only be called by * impl_OAF_ActivationContext_query and * impl_OAF_ActivationContext_activate - hairy implicit preconditions * exist. */ static void ac_query_run (impl_POA_OAF_ActivationContext * servant, CORBA_char * requirements, GNOME_stringlist * selection_order, CORBA_Context ctx, OAF_ServerInfo ** items, CORBA_Environment * ev) { int total, i; GSList *cur; QueryContext qctx; OAF_ServerInfo **orig_items; int item_count, orig_item_count; char *errstr; OAF_ActivationContext_ParseFailed *ex; QueryExpr *qexp_requirements; QueryExpr **qexp_sort_items; /* First, parse the query */ errstr = (char *) qexp_parse (requirements, &qexp_requirements); if (errstr) { puts (errstr); g_strstrip (errstr); ex = OAF_ActivationContext_ParseFailed__alloc (); ex->description = CORBA_string_dup (errstr); CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_OAF_ActivationContext_ParseFailed, ex); return; } qexp_sort_items = oaf_alloca (selection_order->_length * sizeof (QueryExpr *)); for (i = 0; i < selection_order->_length; i++) { errstr = (char *) qexp_parse (selection_order->_buffer[i], &qexp_sort_items[i]); if (errstr) { qexp_free (qexp_requirements); for (i--; i >= 0; i--) qexp_free (qexp_sort_items[i]); g_strstrip (errstr); ex = OAF_ActivationContext_ParseFailed__alloc (); ex->description = CORBA_string_dup (errstr); CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_OAF_ActivationContext_ParseFailed, ex); return; } } total = servant->total_servers; orig_items = oaf_alloca (total * sizeof (OAF_ServerInfo *)); for (item_count = 0, cur = servant->dirs; cur; cur = cur->next) { ChildODInfo *child; int i; child = cur->data; if (child->obj == CORBA_OBJECT_NIL) continue; for (i = 0; i < child->list->_length; i++, item_count++) items[item_count] = &child->list->_buffer[i]; } memcpy (orig_items, items, item_count * sizeof (OAF_ServerInfo *)); orig_item_count = item_count; qctx.sil = orig_items; qctx.nservers = orig_item_count; qctx.cctx = ctx; qctx.id_evaluator = ac_query_get_var; qctx.user_data = servant; for (i = 0; i < item_count; i++) { if (!qexp_matches (items[i], qexp_requirements, &qctx)) items[i] = NULL; } qexp_sort (items, item_count, qexp_sort_items, selection_order->_length, &qctx); qexp_free (qexp_requirements); for (i = 0; i < selection_order->_length; i++) qexp_free (qexp_sort_items[i]); } static OAF_ServerInfoList * impl_OAF_ActivationContext_query (impl_POA_OAF_ActivationContext * servant, CORBA_char * requirements, GNOME_stringlist * selection_order, CORBA_Context ctx, CORBA_Environment * ev) { OAF_ServerInfoList *retval; OAF_ServerInfo **items; int item_count; int i, j, total; retval = OAF_ServerInfoList__alloc (); retval->_length = 0; retval->_buffer = NULL; CORBA_sequence_set_release (retval, CORBA_TRUE); /* Pull in new lists from OD servers */ ac_update_lists (servant, ev); servant->refs++; items = oaf_alloca (servant->total_servers * sizeof (OAF_ServerInfo *)); item_count = servant->total_servers; ac_query_run (servant, requirements, selection_order, ctx, items, ev); if (ev->_major == CORBA_NO_EXCEPTION) { for (total = i = 0; i < item_count; i++) { if (items[i]) total++; } retval->_length = total; retval->_buffer = CORBA_sequence_OAF_ServerInfo_allocbuf (total); for (i = j = 0; i < item_count; i++) { if (!items[i]) continue; OAF_ServerInfo_copy (&retval->_buffer[j], items[i]); j++; } } servant->refs--; return retval; } char * ac_aid_to_query_string (OAF_ActivationID aid) { char *tmp_aid; char *requirements; char *iid_requirement; char *username_requirement; char *hostname_requirement; char *domain_requirement; OAFActivationInfo *ainfo; /* FIXME bugzilla.eazel.com 4659: this is completely broken. We activate by AID, not IID. */ if (strncmp ("OAFIID:", aid, 7) == 0) { tmp_aid = g_strconcat ("OAFAID:[", aid, "]", NULL); ainfo = oaf_actid_parse (tmp_aid); g_free (tmp_aid); } else { ainfo = oaf_actid_parse (aid); } if (ainfo == NULL) { return NULL; } iid_requirement = g_strconcat ("iid == \'", ainfo->iid, "\' ", NULL); if (ainfo->user) { username_requirement = g_strconcat ("AND username == \'", ainfo->user, "\'", NULL); } else { username_requirement = g_strdup (""); } if (ainfo->host) { hostname_requirement = g_strconcat ("AND hostname == \'", ainfo->host, "\'", NULL); } else { hostname_requirement = g_strdup (""); } if (ainfo->domain) { domain_requirement = g_strconcat ("AND domain == \'", ainfo->domain, "\'", NULL); } else { domain_requirement = g_strdup (""); } requirements = g_strconcat (iid_requirement, username_requirement, hostname_requirement, domain_requirement, NULL); g_free (iid_requirement); g_free (username_requirement); g_free (hostname_requirement); g_free (domain_requirement); oaf_actinfo_free (ainfo); return requirements; } void ac_context_to_string_array (CORBA_Context context, char **sort_criteria, CORBA_Environment *ev) { char *context_username; char *context_hostname; char *context_domain; context_username = ac_CORBA_Context_get_value (context, "username", ev); context_hostname = ac_CORBA_Context_get_value (context, "hostname", ev); context_domain = ac_CORBA_Context_get_value (context, "domain", ev); if (ev->_major != CORBA_NO_EXCEPTION) { return; } sort_criteria[0] = g_strconcat ("username == \'", context_username, "\'", NULL); sort_criteria[1] = g_strconcat ("hostname == \'", context_hostname, "\'", NULL); sort_criteria[2] = g_strconcat ("session == \'", context_domain, "\'", NULL); sort_criteria[3] = NULL; g_free (context_username); g_free (context_hostname); g_free (context_domain); } static OAF_ActivationResult * impl_OAF_ActivationContext_activate_from_id (impl_POA_OAF_ActivationContext *servant, OAF_ActivationID aid, OAF_ActivationFlags flags, CORBA_Context ctx, CORBA_Environment *ev) { OAF_ActivationResult *retval; char *requirements; char *sort_criteria[4]; GNOME_stringlist selection_order; OAF_ActivationContext_ParseFailed *ex; ac_update_lists (servant, ev); if (ev->_major != CORBA_NO_EXCEPTION) { return CORBA_OBJECT_NIL; } servant->refs++; requirements = ac_aid_to_query_string (aid); if (requirements == NULL) { servant->refs--; ex = OAF_ActivationContext_ParseFailed__alloc (); ex->description = CORBA_string_dup ("Invalid AID or IID"); CORBA_exception_set (ev, CORBA_USER_EXCEPTION, ex_OAF_ActivationContext_ParseFailed, ex); return CORBA_OBJECT_NIL; } ac_context_to_string_array (ctx, sort_criteria, ev); if (ev->_major != CORBA_NO_EXCEPTION) { servant->refs--; return CORBA_OBJECT_NIL; } selection_order._length = 3; selection_order._buffer = sort_criteria; CORBA_sequence_set_release (&selection_order, CORBA_FALSE); retval = impl_OAF_ActivationContext_activate (servant, requirements, &selection_order, flags, ctx, ev); g_free (sort_criteria[0]); g_free (sort_criteria[1]); g_free (sort_criteria[2]); g_free (requirements); servant->refs--; return retval; } static void impl_OAF_ActivationContext_activate_from_id_async (impl_POA_OAF_ActivationContext * servant, OAF_ActivationID aid, OAF_ActivationFlags flags, OAF_ActivationCallback callback_object, CORBA_Context ctx, CORBA_Environment * ev) { OAF_ActivationResult *retval; char *requirements; char *sort_criteria[4]; GNOME_stringlist selection_order; ac_update_lists (servant, ev); servant->refs++; requirements = ac_aid_to_query_string (aid); if (requirements == NULL) { servant->refs--; OAF_ActivationCallback_report_activation_failed (callback_object, _("Could not parse AID"), ev); return; } ac_context_to_string_array (ctx, sort_criteria, ev); if (ev->_major != CORBA_NO_EXCEPTION) { char *message; g_free (requirements); servant->refs--; message = g_strconcat (_("Could not parse context: "), CORBA_exception_id (ev), NULL); OAF_ActivationCallback_report_activation_failed (callback_object, message, ev); g_free (message); return; } selection_order._length = 3; selection_order._buffer = sort_criteria; CORBA_sequence_set_release (&selection_order, CORBA_FALSE); retval = impl_OAF_ActivationContext_activate (servant, requirements, &selection_order, flags, ctx, ev); g_free (sort_criteria[0]); g_free (sort_criteria[1]); g_free (sort_criteria[2]); g_free (requirements); if (ev->_major != CORBA_NO_EXCEPTION) { char *message; servant->refs--; message = g_strconcat (_("Could not activate server: "), CORBA_exception_id (ev), NULL); OAF_ActivationCallback_report_activation_failed (callback_object, message, ev); g_free (message); return; } servant->refs--; OAF_ActivationCallback_report_activation_succeeded (callback_object, retval, ev); }