/* -*- mode: C; c-file-style: "bsd" -*- */ #include "errors.h" #include "interfaces.h" #include "globals.h" #include "types.h" /* Forward declarations */ XS(_porbit_callStub); static CORBA_Repository iface_repository = NULL; PORBitIfaceInfo * porbit_find_interface_description (const char *repoid) { HV *hv = perl_get_hv("CORBA::ORBit::_interfaces", TRUE); SV **result = hv_fetch (hv, (char *)repoid, strlen(repoid), 0); if (!result) return NULL; else return (PORBitIfaceInfo *)SvIV(*result); } static void free_interface_info (PORBitIfaceInfo *info) { g_free (info->pkg); CORBA_free (info->desc); g_free (info); } static PORBitIfaceInfo * store_interface_description (CORBA_InterfaceDef_FullInterfaceDescription *desc, const char *package_name) { SV *pkg_sv; char *varname; HV *hv = perl_get_hv("CORBA::ORBit::_interfaces", TRUE); PORBitIfaceInfo *info = g_new (PORBitIfaceInfo, 1); info->pkg = g_strdup (package_name); info->desc = desc; info->class_id = 0; hv_store (hv, (char *)desc->id, strlen (desc->id), newSViv((IV)info), 0); varname = g_strconcat (info->pkg, "::", PORBIT_REPOID_KEY, NULL); pkg_sv = perl_get_sv (varname, TRUE ); g_free (varname); sv_setpv (pkg_sv, desc->id); return info; } static gboolean ensure_iface_repository (CORBA_Environment *ev) { if (iface_repository == NULL) iface_repository = CORBA_ORB_resolve_initial_references(porbit_orb, "InterfaceRepository", ev); if (ev->_major != CORBA_NO_EXCEPTION || iface_repository == NULL) { CORBA_exception_set_system (ev, ex_CORBA_INTF_REPOS, CORBA_COMPLETED_NO); warn("Cannot locate interface repository"); return FALSE; } return TRUE; } static void define_exception (const char *repoid, CORBA_Environment *ev) { CORBA_char *pack = NULL; char *pkg; CORBA_Contained contained = NULL; if (porbit_find_exception(repoid)) return; if (!ensure_iface_repository (ev)) goto error; contained = CORBA_Repository_lookup_id (iface_repository, ((char *)repoid), ev); if (ev->_major != CORBA_NO_EXCEPTION) goto error; pack = CORBA_Contained__get_absolute_name (contained, ev); if (ev->_major != CORBA_NO_EXCEPTION) goto error; pkg = pack; if (!strncmp(pkg, "::", 2)) pkg += 2; porbit_setup_exception (repoid, pkg, "CORBA::UserException"); error: if (pack) CORBA_free (pack); if (contained) CORBA_Object_release (contained, ev); } static void define_method (const char *pkg, const char *prefix, const char *name, I32 index) { gchar *fullname = g_strconcat (pkg, prefix, name, NULL); CV *method_cv = newXS ((char *)fullname, _porbit_callStub, __FILE__); CvXSUBANY(method_cv).any_i32 = index; CvSTASH (method_cv) = gv_stashpv ((char *)pkg, 0); g_free (fullname); } XS(_repoid) { dXSARGS; if (items != 1) croak("Usage: _repoid(self)"); ST(0) = (SV *)CvXSUBANY(cv).any_ptr; XSRETURN(1); } static PORBitIfaceInfo * load_ancestor (const char *id, CORBA_Environment *ev) { PORBitIfaceInfo *info; CORBA_Contained base; CORBA_DefinitionKind defkind; info = porbit_find_interface_description (id); if (info) return info; if (!ensure_iface_repository (ev)) return NULL; base = CORBA_Repository_lookup_id (iface_repository, (char *)id, ev); if (ev->_major != CORBA_NO_EXCEPTION || !base) return NULL; /* Paranoia */ defkind = CORBA_IRObject__get_def_kind (base, ev); if (ev->_major != CORBA_NO_EXCEPTION || defkind != CORBA_dk_Interface) { CORBA_Object_release (base, ev); return NULL; } info = porbit_load_contained (base, NULL, ev); CORBA_Object_release (base, ev); return info; } PORBitIfaceInfo * porbit_init_interface (CORBA_InterfaceDef_FullInterfaceDescription *desc, const char *package_name, CORBA_Environment *ev) { PORBitIfaceInfo *info; CORBA_unsigned_long i, j; char *tmp_str; AV *isa_av; CV *method_cv; info = porbit_find_interface_description (desc->id); if (info) { CORBA_free (desc); return info; } info = store_interface_description (desc, package_name); /* Set up the interface's operations and attributes */ for (i = 0 ; i < desc->operations._length ; i++) { CORBA_OperationDescription *opr = &desc->operations._buffer[i]; if (!strcmp(opr->name, "_is_a")) continue; define_method (info->pkg, "::", opr->name, PORBIT_OPERATION_BASE + i); for (j = 0 ; j < opr->exceptions._length ; j++) { define_exception (opr->exceptions._buffer[j].id, ev); if (ev->_major != CORBA_NO_EXCEPTION) return NULL; } } for (i = 0; i < desc->attributes._length; i++) { if (desc->attributes._buffer[i].mode == CORBA_ATTR_NORMAL) { define_method (info->pkg, "::_set_", desc->attributes._buffer[i].name, PORBIT_SETTER_BASE + i); } define_method (info->pkg, "::_get_", desc->attributes._buffer[i].name, PORBIT_GETTER_BASE + i); } /* Register the base interfaces */ tmp_str = g_strconcat (info->pkg, "::ISA", NULL); isa_av = perl_get_av (tmp_str, TRUE ); g_free (tmp_str); for (i = 0; i < desc->base_interfaces._length ; i++) { PORBitIfaceInfo *info = load_ancestor (desc->base_interfaces._buffer[i], ev); if (ev->_major != CORBA_NO_EXCEPTION) { warn ("Can't find interface description for ancestor '%s'", desc->base_interfaces._buffer[i]); return NULL; } if (info) av_push (isa_av, newSVpv(info->pkg, 0)); } /* Set up the server side package */ tmp_str = g_strconcat ("POA_", info->pkg, "::ISA", NULL); isa_av = perl_get_av (tmp_str, TRUE); g_free (tmp_str); av_push (isa_av, newSVpv("PortableServer::ServantBase", 0)); /* Create a package method that will allow us to determine the * repository id even before we have the ORBit object set up */ tmp_str = g_strconcat ("POA_", info->pkg, "::_repoid", NULL); method_cv = newXS (tmp_str, _repoid, __FILE__); g_free (tmp_str); CvXSUBANY(method_cv).any_ptr = (void *)newSVpv((char *)desc->id, 0); return info; } /* Assumes ownership of SV's refcount */ void porbit_init_constant (const char *pkgname, const char *name, SV *sv) { HV *stash = gv_stashpv ((char *)pkgname, TRUE); newCONSTSUB (stash, (char *)name, sv); } static void load_container (CORBA_Container container, PORBitIfaceInfo *info, CORBA_Environment *ev) { CORBA_unsigned_long i; CORBA_ContainedSeq *contents = NULL; CORBA_char *pkg = NULL; contents = CORBA_Container_contents (container, CORBA_dk_Constant, CORBA_TRUE, ev); if (ev->_major != CORBA_NO_EXCEPTION) return; if (contents->_length > 0) { char *pkgname; if (info) pkgname = g_strdup (info->pkg); else { CORBA_char *pkg = CORBA_Contained__get_absolute_name(container, ev); if (!strncmp(pkg, "_", 2)) pkgname = &pkg[2]; else pkgname = pkg; } for (i = 0; i_length; i++) ; /* porbit_init_constant (pkgname, contents->_buffer[i]); */ } CORBA_free (contents); contents = CORBA_Container_contents (container, CORBA_dk_Interface, CORBA_TRUE, ev); if (ev->_major != CORBA_NO_EXCEPTION) { contents = NULL; goto error; } for (i = 0; i_length; i++) { CORBA_char *id; id = CORBA_Contained__get_id (contents->_buffer[i], ev); if (ev->_major != CORBA_NO_EXCEPTION) goto error; if (!porbit_find_interface_description (id)) porbit_load_contained (contents->_buffer[i], NULL, ev); CORBA_free (id); if (ev->_major != CORBA_NO_EXCEPTION) goto error; } error: if (pkg) CORBA_free (pkg); if (contents) CORBA_free (contents); } static PORBitIfaceInfo * load_interface (CORBA_InterfaceDef iface, CORBA_Environment *ev) { CORBA_InterfaceDef_FullInterfaceDescription *desc; CORBA_char *absolute_name; const char *package_name; PORBitIfaceInfo *retval; desc = CORBA_InterfaceDef_describe_interface (iface, ev); if (ev->_major != CORBA_NO_EXCEPTION) return NULL; absolute_name = CORBA_InterfaceDef__get_absolute_name (iface, ev); if (ev->_major != CORBA_NO_EXCEPTION) { CORBA_free (desc); return NULL; } package_name = absolute_name; if (!strncmp(package_name, "::", 2)) package_name += 2; retval = porbit_init_interface (desc, package_name, ev); CORBA_free (absolute_name); CORBA_free (desc); return retval; } PORBitIfaceInfo * porbit_load_contained (CORBA_Contained _contained, const char *_id, CORBA_Environment *ev) { PORBitIfaceInfo *retval = NULL; CORBA_DefinitionKind defkind; CORBA_char *id; CORBA_Contained contained; assert (_contained != NULL || _id != NULL); id = (CORBA_char *)_id; if (_contained) { contained = CORBA_Object_duplicate (_contained, ev); if (ev->_major != CORBA_NO_EXCEPTION) return NULL; if (!id) { id = CORBA_Contained__get_id (contained, ev); if (ev->_major != CORBA_NO_EXCEPTION) { id = NULL; goto error; } } } else { if (!ensure_iface_repository (ev)) return NULL; contained = CORBA_Repository_lookup_id (iface_repository, id, ev); if (ev->_major != CORBA_NO_EXCEPTION) return NULL; if (!contained) { warn ("Cannot find '%s' in interface repository", id); CORBA_exception_set_system (ev, ex_CORBA_BAD_PARAM, CORBA_COMPLETED_NO); return NULL; } } defkind = CORBA_IRObject__get_def_kind (contained, ev); if (ev->_major != CORBA_NO_EXCEPTION) goto error; /* If the container is an interface, suck all the information * out of it for later use. */ if (defkind == CORBA_dk_Interface) { retval = porbit_find_interface_description (id); if (!retval) { retval = load_interface (contained, ev); if (ev->_major != CORBA_NO_EXCEPTION) goto error; } } /* Initialize all constants in the container, and all * enclosed interfaces. */ switch (defkind) { case CORBA_dk_Exception: case CORBA_dk_Interface: case CORBA_dk_Module: case CORBA_dk_Struct: case CORBA_dk_Union: case CORBA_dk_Repository: load_container (contained, retval, ev); break; default: break; } error: if (id && id != _id) CORBA_free (id); if (contained) CORBA_Object_release (contained, ev); return retval; } /* TypeCode lookup */ static GHashTable *typecode_hash = NULL; #define duplicate_typecode(a) (CORBA_TypeCode)CORBA_Object_duplicate ((CORBA_Object)a, NULL) CORBA_TypeCode porbit_find_typecode (const char *repoid) { if (typecode_hash) { CORBA_TypeCode result = g_hash_table_lookup (typecode_hash, repoid); return duplicate_typecode (result); } else { return NULL; } } void porbit_store_typecode (const char *repoid, CORBA_TypeCode tc) { if (!typecode_hash) typecode_hash = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (typecode_hash, g_strdup (repoid), duplicate_typecode (tc)); } void porbit_remove_typecode (const char *repoid) { if (typecode_hash) g_hash_table_remove (typecode_hash, repoid); } static CORBA_ParameterDescription is_a_parameter = { "logical_type_id", /* name */ TC_CORBA_string, /* type */ CORBA_OBJECT_NIL, /* type_def */ CORBA_PARAM_IN /* mode */ }; static CORBA_OperationDescription is_a_desc = { "_is_a", /* name */ NULL, /* id */ NULL, /* defined_in */ NULL, /* version */ TC_CORBA_boolean, /* result */ CORBA_OP_NORMAL, /* mode */ { /* contexts */ 0, /* _maximum */ 0, /* _length */ NULL, /* _buffer */ FALSE /* _release */ }, { /* parameters */ 1, /* _maximum */ 1, /* _length */ &is_a_parameter, /* _buffer */ FALSE /* _release */ }, { /* exceptions */ 0, /* _maximum */ 0, /* _length */ NULL, /* _buffer */ FALSE /* _release */ } }; void porbit_init_interfaces (void) { CORBA_Environment ev; CORBA_InterfaceDef_FullInterfaceDescription *desc; desc = g_new (CORBA_InterfaceDef_FullInterfaceDescription, 1); desc->name = "Object"; desc->id = "IDL:CORBA/Object:1.0"; desc->operations._maximum = 1; desc->operations._length = 1; desc->operations._buffer = &is_a_desc; desc->operations._release = FALSE; desc->attributes._maximum = 0; desc->attributes._length = 0; desc->attributes._buffer = NULL; desc->attributes._release = FALSE; desc->base_interfaces._maximum = 0; desc->base_interfaces._length = 0; desc->base_interfaces._buffer = NULL; desc->base_interfaces._release = FALSE; desc->version = NULL; desc->defined_in = NULL; desc->type = NULL; CORBA_exception_init (&ev); porbit_init_interface (desc, "CORBA::Object", &ev); if (ev._major != CORBA_NO_EXCEPTION) { warn ("Registering interface 'CORBA::Object' failed!\n"); CORBA_exception_free (&ev); } } void porbit_init_typecodes (void) { porbit_store_typecode ("IDL:omg.org/CORBA/Null:1.0", duplicate_typecode(TC_null)); porbit_store_typecode ("IDL:omg.org/CORBA/Void:1.0", duplicate_typecode(TC_void)); porbit_store_typecode ("IDL:omg.org/CORBA/Short:1.0", duplicate_typecode(TC_CORBA_short)); porbit_store_typecode ("IDL:omg.org/CORBA/Long:1.0", duplicate_typecode(TC_CORBA_long)); porbit_store_typecode ("IDL:omg.org/CORBA/LongLong:1.0", duplicate_typecode(TC_CORBA_longlong)); porbit_store_typecode ("IDL:omg.org/CORBA/UShort:1.0", duplicate_typecode(TC_CORBA_ushort)); porbit_store_typecode ("IDL:omg.org/CORBA/ULong:1.0", duplicate_typecode(TC_CORBA_ulong)); porbit_store_typecode ("IDL:omg.org/CORBA/ULongLong:1.0", duplicate_typecode(TC_CORBA_ulonglong)); porbit_store_typecode ("IDL:omg.org/CORBA/Float:1.0", duplicate_typecode(TC_CORBA_float)); porbit_store_typecode ("IDL:omg.org/CORBA/Double:1.0", duplicate_typecode(TC_CORBA_double)); porbit_store_typecode ("IDL:omg.org/CORBA/LongDouble:1.0", duplicate_typecode(TC_CORBA_longdouble)); porbit_store_typecode ("IDL:omg.org/CORBA/Boolean:1.0", duplicate_typecode(TC_CORBA_boolean)); porbit_store_typecode ("IDL:omg.org/CORBA/Char:1.0", duplicate_typecode(TC_CORBA_char)); porbit_store_typecode ("IDL:omg.org/CORBA/WChar:1.0", duplicate_typecode(TC_CORBA_wchar)); porbit_store_typecode ("IDL:omg.org/CORBA/Octet:1.0", duplicate_typecode(TC_CORBA_octet)); porbit_store_typecode ("IDL:omg.org/CORBA/Any:1.0", duplicate_typecode(TC_CORBA_any)); porbit_store_typecode ("IDL:omg.org/CORBA/TypeCode:1.0", duplicate_typecode(TC_CORBA_TypeCode)); porbit_store_typecode ("IDL:omg.org/CORBA/Principal:1.0", duplicate_typecode(TC_CORBA_Principal)); porbit_store_typecode ("IDL:omg.org/CORBA/Object:1.0", duplicate_typecode(TC_CORBA_Object)); porbit_store_typecode ("IDL:omg.org/CORBA/String:1.0", duplicate_typecode(TC_CORBA_string)); porbit_store_typecode ("IDL:omg.org/CORBA/WString:1.0", duplicate_typecode(TC_CORBA_wstring)); }