00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include <dbus-c++/introspection.h>
00029 #include <dbus-c++/object.h>
00030 #include <dbus-c++/message.h>
00031
00032 #include <dbus/dbus.h>
00033
00034 #include <sstream>
00035
00036 using namespace DBus;
00037
00038 static const char *introspectable_name = "org.freedesktop.DBus.Introspectable";
00039
00040 IntrospectableAdaptor::IntrospectableAdaptor()
00041 : InterfaceAdaptor(introspectable_name)
00042 {
00043 register_method(IntrospectableAdaptor, Introspect, Introspect);
00044 }
00045
00046 Message IntrospectableAdaptor::Introspect(const CallMessage &call)
00047 {
00048 debug_log("requested introspection data");
00049
00050 std::ostringstream xml;
00051
00052 xml << DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE;
00053
00054 const std::string path = object()->path();
00055
00056 xml << "<node name=\"" << path << "\">";
00057
00058 InterfaceAdaptorTable::const_iterator iti;
00059
00060 for (iti = _interfaces.begin(); iti != _interfaces.end(); ++iti)
00061 {
00062 debug_log("introspecting interface %s", iti->first.c_str());
00063
00064 IntrospectedInterface *const intro = iti->second->introspect();
00065 if (intro)
00066 {
00067 xml << "\n\t<interface name=\"" << intro->name << "\">";
00068
00069 for (const IntrospectedProperty *p = intro->properties; p->name; ++p)
00070 {
00071 std::string access;
00072
00073 if (p->read) access += "read";
00074 if (p->write) access += "write";
00075
00076 xml << "\n\t\t<property name=\"" << p->name << "\""
00077 << " type=\"" << p->type << "\""
00078 << " access=\"" << access << "\"/>";
00079 }
00080
00081 for (const IntrospectedMethod *m = intro->methods; m->args; ++m)
00082 {
00083 xml << "\n\t\t<method name=\"" << m->name << "\">";
00084
00085 for (const IntrospectedArgument *a = m->args; a->type; ++a)
00086 {
00087 xml << "\n\t\t\t<arg direction=\"" << (a->in ? "in" : "out") << "\""
00088 << " type=\"" << a->type << "\"";
00089
00090 if (a->name) xml << " name=\"" << a->name << "\"";
00091
00092 xml << "/>";
00093 }
00094
00095 xml << "\n\t\t</method>";
00096 }
00097
00098 for (const IntrospectedMethod *m = intro->signals; m->args; ++m)
00099 {
00100 xml << "\n\t\t<signal name=\"" << m->name << "\">";
00101
00102 for (const IntrospectedArgument *a = m->args; a->type; ++a)
00103 {
00104 xml << "<arg type=\"" << a->type << "\"";
00105
00106 if (a->name) xml << " name=\"" << a->name << "\"";
00107
00108 xml << "/>";
00109 }
00110 xml << "\n\t\t</signal>";
00111 }
00112
00113 xml << "\n\t</interface>";
00114 }
00115 }
00116
00117 const ObjectPathList nodes = ObjectAdaptor::child_nodes_from_prefix(path + '/');
00118 ObjectPathList::const_iterator oni;
00119
00120 for (oni = nodes.begin(); oni != nodes.end(); ++oni)
00121 {
00122 xml << "\n\t<node name=\"" << (*oni) << "\"/>";
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 xml << "\n</node>";
00140
00141 ReturnMessage reply(call);
00142 MessageIter wi = reply.writer();
00143 wi.append_string(xml.str().c_str());
00144 return reply;
00145 }
00146
00147 IntrospectedInterface *IntrospectableAdaptor::introspect() const
00148 {
00149 static IntrospectedArgument Introspect_args[] =
00150 {
00151 { "data", "s", false },
00152 { 0, 0, 0 }
00153 };
00154 static IntrospectedMethod Introspectable_methods[] =
00155 {
00156 { "Introspect", Introspect_args },
00157 { 0, 0 }
00158 };
00159 static IntrospectedMethod Introspectable_signals[] =
00160 {
00161 { 0, 0 }
00162 };
00163 static IntrospectedProperty Introspectable_properties[] =
00164 {
00165 { 0, 0, 0, 0 }
00166 };
00167 static IntrospectedInterface Introspectable_interface =
00168 {
00169 introspectable_name,
00170 Introspectable_methods,
00171 Introspectable_signals,
00172 Introspectable_properties
00173 };
00174 return &Introspectable_interface;
00175 }
00176
00177 IntrospectableProxy::IntrospectableProxy()
00178 : InterfaceProxy(introspectable_name)
00179 {}
00180
00181 std::string IntrospectableProxy::Introspect()
00182 {
00183 DBus::CallMessage call;
00184
00185 call.member("Introspect");
00186
00187 DBus::Message ret = invoke_method(call);
00188
00189 DBus::MessageIter ri = ret.reader();
00190 const char *str = ri.get_string();
00191
00192 return str;
00193 }