Implenting Get and GetAll with libdbus-1 - c

Given libdbus-1 which is non-negotiable, I'd like to implement Get and GetAll for DBus properties.
I don't really see any examples for this.
Do I just have to match the method with dbus_message_is_method_call() and respond accordingly?
Or is there a built in way of doing this where I have some code to do the heavy lifting.
Once again, switching libraries is not an option so please don't say use Qt, glib, libnih, libsystemd, or anything else. Please be specific to libdbus-1 or don't answer.

Look at the libdbus-1 source code: git://anongit.freedesktop.org/dbus/dbus
There's an example here in bus/driver.c called bus_driver_handle_get_all(). This function implements a reply to "GetAll".
Of course, we need to have GetAll implemented in our xml file for introspection as well.
<interface name='org.freedesktop.DBus.Properties'>
<method name='Get'>
<arg name='interface' type='s' direction='in' />
<arg name='property' type='s' direction='in' />
<arg name='value' type='s' direction='out' />
</method>
<method name='GetAll'>
<arg name='interface' type='s' direction='in'/>
<arg name='properties' type='a{sv}' direction='out'/>
</method>
</interface>
So to reply to this, we need to iterate through all of our properties and load them up in a DBusMessageIter then send this reply to the sender.
Clearly the "Get" response is much easier, we merely have to return a string in this case which is obviously matched for our property. Again, this is in the same file, bus/driver.c in the function: bus_driver_handle_get().

Related

set/get property using dbus-send

I have made below sample xml and need some help in forming dbus-send command to set/get propoerty "Status". I know how to call methods, but not able to read/write property using dbus-send.
xml:
<node>
<interface name="com.pgaur.GDBUS">
<method name="HelloWorld">
<arg name="greeting" direction="in" type="s"/>
<arg name="response" direction="out" type="s"/>
</method>
<signal name="Notification">
<arg name="roll_number" type="i"/>
<arg name="name" type="s"/>
</signal>
<property name="Status" type="u" access="readwrite"/>
</interface>
</node>
You can Get/Set DBus properties for your DBus interface using below dbus-send commands. Replace $BUS_NAME and $OBJECT_PATH with respective names.
Get Property:
dbus-send --system --dest=$BUS_NAME --print-reply $OBJECT_PATH \
org.freedesktop.DBus.Properties.Get string:com.pgaur.GDBUS string:Status
Set Property:
dbus-send --system --dest=$BUS_NAME --print-reply $OBJECT_PATH \
org.freedesktop.DBus.Properties.Set string:com.pgaur.GDBUS string:Status variant:uint32:10
You can read DBus specification to know more about DBus Properties.
dbus-send --system --print-reply --type=method_call --dest=org.ofono /gemalto_0 org.ofono.Modem.SetProperty string:"Powered" variant:boolean:false

D-Bus method not found at object path despite the fact that method exist

I implement an app with this com.example.appname.desktop file as follows:
$ cat /usr/local/share/applications/com.example.appname.desktop
[Desktop Entry]
Version=1.0
Terminal=false
Type=Application
Name=appname
Exec=/opt/app/appname %u
DBusActivatable=true
Categories=Network;
MimeType=x-scheme-handler/itmm;
NoDisplay=false
$ cat /usr/share/dbus-1/services/com.example.appname.service
[D-BUS Service]
Name=com.example.appname
Exec=/opt/app/appname
Introspection XML looks like this:
$ qdbus com.example.appname /com/example/appname org.freedesktop.DBus.Introspectable.Introspect
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.Application">
<method name="ActivateAction">
<arg name="action_name" type="s" direction="in"/>
<arg name="parameter" type="av" direction="in"/>
<arg name="platform_data" type="a{sv}" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QVariantMap"/>
</method>
<method name="Activate">
<arg name="platform_data" type="a{sv}" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
</method>
<method name="Open">
<arg name="uris" type="as" direction="in"/>
<arg name="platform_data" type="a{sv}" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
</method>
</interface>
<interface name="org.freedesktop.DBus.Properties">
<method name="Get">
<arg name="interface_name" type="s" direction="in"/>
<arg name="property_name" type="s" direction="in"/>
<arg name="value" type="v" direction="out"/>
</method>
----<snipped>-----
But when i try to launch the method it gives me an error:
$ gapplication launch com.example.appname
error sending Activate message to application: GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: No such method 'Activate' in interface 'org.freedesktop.Application' at object path '/com/example/appname' (signature 'a{sv}')
Is "annotation name=.." XML tag (see introspection XML) the reason this method is not found?
Browsing to itmm://192.168.1.1/query?version=1.0 via browser launches the application with command line parameter, but it is not launched via D-Bus service and thats what my requirement is. Is there a way to debug this via firefox or google chrome browsers?
I use QT's D-Bus binding to implement D-Bus service. My issue were
My class that implemented D-Bus interface was not inheriting QDBusAbstractAdaptor .
Methods to be exported were not marked as public slots
My original class looked like this below:
class DBusService : public Application
{
QOBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Application")
public:
void Activate(QMap<QString, QVariant> platform_data)
{
Q_UNUSED(platform_data);
}
void Open(QStringList uris, QMap<QString, QVariant> platform_data)
{
Q_UNUSED(platform_data);
if( ! uris.size() ) {
return;
}
QUrl url(uris[0]);
//use url
}
}
Following one works:
class DBusService : public QDBusAbstractAdaptor //<----- Inherit from this class
{
QOBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.Application")
public slots: // <------ mark public slots
void Activate(QMap<QString, QVariant> platform_data)
{
Q_UNUSED(platform_data);
}
void Open(QStringList uris, QMap<QString, QVariant> platform_data)
{
Q_UNUSED(platform_data);
if( ! uris.size() ) {
return;
}
QUrl url(uris[0]);
qApp->MyCustomMethod(url);
}
}
D-Bus debugging tools
These tools helped me debugging D-Bus issues.
dbus-monitor - sniffs traffic on the bus
gapplication - lets you debug DBusActivatable services.

JAXB Example in camel

Can any one provide me simple example in camel with JAXB using spring XML? I searched on net but did not find anything.
I just want to create simple Student class with fields name, id and convert it into xml.
Not sure what in particular you're struggling with, but here are some snippets:
<util:map id="jaxbNamespacePrefixMap">
<!-- In my case, we dont want a prefix for our namespace; YMMV -->
<entry key="http://www.nmcourts.gov" value=""/>
</util:map>
<marshal>
<jaxb prettyPrint="true" contextPath="generated.gov.nmcourts.ecitation.shared.odyssey"
partClass="generated.gov.nmcourts.ecitation.shared.odyssey.NMCitationEFileBatch" partNamespace="EFileBatch"
namespacePrefixRef="jaxbNamespacePrefixMap"/>
</marshal>
<unmarshal>
<jaxb prettyPrint="true" contextPath="generated.gov.nmcourts.ecitation.shared.odyssey"
partClass="generated.gov.nmcourts.ecitation.shared.odyssey.NMCitationEFileBatch"
partNamespace="EFileBatch" namespacePrefixRef="jaxbNamespacePrefixMap" />
</unmarshal>
What do you need exactly?
http://camel.apache.org/jaxb shows perfectly well how to marshal to xml via spring.

WSO2 ESB calling parameterized endpoint Looping on Parameters

In my usecase i have to chain two service calls. In particular:
1) The first call returns an xml listing several IDs
2) i have to iterate through the returned ID list and to make an ID parameterized service call for each id-item.
3) Finally i have to collect a whole response made up of each single ID-service-response.
Suppose the first service call returns a response like this one:
<result>
<Link>
<Id>93451</Id>
</Link>
<Link>
<Id>93450</Id>
</Link>
...
The second step is to perform a series of calling to parameterized endpoint like this:
http://myEndpoint/entry/eutils/efetch.fcgi?db=pubmed&rettype=abstract&retmode=xml&id=<ID>
each call of which returns an xml response like this:
<response>
<field1>value1</field1>
<field2>value2</field2>
<field3>value3</field3>
<response>
I have to collect a whole response like this one:
<finalResponse>
<response>
<field1>value1</field1>
<field2>value2</field2>
<field3>value3</field3>
<response>
<response>
<field1>value1</field1>
<field2>value2</field2>
<field3>value3</field3>
<response>
<response>
<field1>value1</field1>
<field2>value2</field2>
<field3>value3</field3>
<response>
</finalResponse>
How can i do? Could you give me some example? Thanks
You need to use iterate mediator and aggregate mediator in combination. Here is a sample code, but you may need to do some modification in order to make it work for your requirements.
<definitions xmlns="http://ws.apache.org/ns/synapse">
<proxy name="SampleProxy">
<target>
<inSequence>
<iterate expression="//result/link/id" preservePayload="true"
attachPath="//link">
<target>
<property name="uri.var.servicepath" expression="//link/id/text()"/>
<sequence>
<send>
<endpoint key="MyEndpoint"/>
</send>
</sequence>
</target>
</iterate>
</inSequence>
<outSequence>
<property name="FinalResponse" scope="default">
<finalResponse />
</property>
<aggregate>
<onComplete expression="//response"
enclosingElementProperty="FinalResponse">
<send/>
</onComplete>
</aggregate>
</outSequence>
</target>
</proxy>
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="MyEndpoint">
<http uri-template="http://myEndpoint/entry/eutils/efetch.fcgi?db=pubmed&rettype=abstract&retmode=xml&id={ID}" method="GET">
</http>
</endpoint>
</definitions>
Full documentation on related sample here.
Find how you can parameterize you url here.

Ant script -- split string and access via indexing

I need to write an Ant script which would load a properties file, read a single property out of it. The value (multiline) is something like:
path/to/file1a;path/to/file1b,
path/to/file2a;path/to/file2b,
..
..
I need to iterate over every line, and execute a shell command which looks like:
myCommand -param1 path/to/file1a -param2 path/to/file1b #Command inside a single iteration
I have able to figure out how to loop:
<for list="${ValueFromPropertyFile}" param="a">
<sequential>
<exec executable="myCommand">
<arg value="-param1" />
<arg value="---- split(#{a}, ";")[0] ----" />
<arg value="-param2" />
<arg value="---- split(#{a}, ";")[1] ----" />
</exec>
</sequential>
</for>
This is quite a simple task in my opinion. I tried searching, but without any success.
I would appreciate if someone could help me out with this, or point me to a relevant document.
Many thanks,
Pratik
Couple of problems with your assumptions:
The format of your input file is not a standard Java properties file, so it can't be loaded using the standard loadproperties task in ANT.
ANT is not a programming language. The "for" task you've quoted is not part of core ANT (Requires the 3rd party ant-contrib.jar)
So I'd suggest using an embedded script to solve your problem.
Example
The project is self documenting:
$ ant -p
Buildfile: /home/mark/tmp/build.xml
This is a demo project answering the following stackoverflow question:
http://stackoverflow.com/questions/14625896
First install 3rd party dependencies and generate the test files
ant bootstrap generate-test-files
Then run the build
ant
Expect the following output
parse-data-file:
[exec] build/myCommand -param1 path/to/file1a -param2 path/to/file1b
[exec] build/myCommand -param1 path/to/file2a -param2 path/to/file2b
build.xml
<project name="demo" default="parse-data-file">
<description>
This is a demo project answering the following stackoverflow question:
http://stackoverflow.com/questions/14625896
First install 3rd party dependencies and generate the test files
ant bootstrap generate-test-files
Then run the build
ant
Expect the following output
parse-data-file:
[exec] build/myCommand -param1 path/to/file1a -param2 path/to/file1b
[exec] build/myCommand -param1 path/to/file2a -param2 path/to/file2b
</description>
<target name="bootstrap" description="Install 3rd party dependencies">
<mkdir dir="${user.home}/.ant/lib"/>
<get dest="${user.home}/.ant/lib/groovy-all.jar" src="http://search.maven.org/remotecontent?filepath=org/codehaus/groovy/groovy-all/2.1.0/groovy-all-2.1.0.jar"/>
</target>
<target name="generate-test-files" description="Generate the input data and sample script">
<echo file="build/input.txt">path/to/file1a;path/to/file1b,
path/to/file2a;path/to/file2b,</echo>
<echo file="build/myCommand"> #!/bin/bash
echo $0 $*</echo>
<chmod file="build/myCommand" perm="755"/>
</target>
<target name="parse-data-file" description="Parse data file">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"/>
<groovy>
new File("build/input.txt").eachLine { line ->
def fields = line.split(/[;,]/)
ant.exec(executable:"build/myCommand") {
arg(value:"-param1")
arg(value:fields[0])
arg(value:"-param2")
arg(value:fields[1])
}
}
</groovy>
</target>
<target name="clean" description="Cleanup build files">
<delete dir="build"/>
</target>
</project>

Resources