[libnet-dbus-perl] 43/335: Merged introspection code from INTROSPECTION branch into mainline
Intrigeri
intrigeri at moszumanska.debian.org
Sat Mar 21 01:07:19 UTC 2015
This is an automated email from the git hooks/post-receive script.
intrigeri pushed a commit to branch experimental
in repository libnet-dbus-perl.
commit 149d28736d4fb98f9a19848f9008fa462298181d
Author: Daniel P. Berrange <dan at berrange.com>
Date: Tue Mar 29 19:37:22 2005 +0000
Merged introspection code from INTROSPECTION branch into mainline
---
examples/example-client.pl | 3 +
examples/example-service.pl | 25 ++-
examples/example-signal-emitter.pl | 23 ++-
examples/example-signal-receiver.pl | 13 +-
lib/Net/DBus.pm | 107 +----------
lib/Net/DBus/Binding/Iterator.pm | 66 ++++---
lib/Net/DBus/Introspector.pm | 369 ++++++++++++++++++++++++++++++++++++
lib/Net/DBus/Object.pm | 38 ++--
lib/Net/DBus/RemoteObject.pm | 35 +++-
t/40-introspector.t | 63 ++++++
10 files changed, 581 insertions(+), 161 deletions(-)
diff --git a/examples/example-client.pl b/examples/example-client.pl
index 8c8fa42..5fb97ef 100644
--- a/examples/example-client.pl
+++ b/examples/example-client.pl
@@ -1,6 +1,9 @@
#/usr/bin/perl
use Net::DBus;
+use Carp qw(cluck carp);
+#$SIG{__WARN__} = sub { cluck $_[0] };
+#$SIG{__DIE__} = sub { carp $_[0] };
my $bus = Net::DBus->session();
diff --git a/examples/example-service.pl b/examples/example-service.pl
index 964b1dd..530dc74 100644
--- a/examples/example-service.pl
+++ b/examples/example-service.pl
@@ -22,7 +22,24 @@ use base qw(Net::DBus::Object);
sub new {
my $class = shift;
my $self = $class->SUPER::new("/SomeObject",
- ["HelloWorld"],
+ {
+ "SomeObject" => {
+ methods => {
+ "HelloWorld" => {
+ params => ["string"],
+ returns => [["array",["string"]]],
+ },
+ "GetDict" => {
+ params => [],
+ returns => [["dict", ["string", "string"]]],
+ },
+ "GetTuple" => {
+ params => [],
+ returns => [["struct", ["string", "string"]]],
+ }
+ },
+ },
+ },
@_);
bless $self, $class;
@@ -30,9 +47,11 @@ sub new {
return $self;
}
+
sub HelloWorld {
my $self = shift;
my $message = shift;
+ print "Do hello world\n";
print $message, "\n";
return ["Hello", " from example-service.pl"];
}
@@ -40,11 +59,13 @@ sub HelloWorld {
sub GetDict {
my $self = shift;
my $message = shift;
+ print "Do get dict\n";
return {"first" => "Hello Dict", "second" => " from example-service.py"};
}
sub GetTuple {
my $self = shift;
my $message = shift;
- return Net::DBus::dstruct(["Hello Tuple", " from example-service.py"]);
+ print "Do get tuple\n";
+ return ["Hello Tuple", " from example-service.py"];
}
diff --git a/examples/example-signal-emitter.pl b/examples/example-signal-emitter.pl
index d095b2a..e4cec92 100644
--- a/examples/example-signal-emitter.pl
+++ b/examples/example-signal-emitter.pl
@@ -5,6 +5,11 @@ use Net::DBus::Reactor;
use Net::DBus::Service;
use Net::DBus::Object;
+use Carp qw(confess cluck);
+
+$SIG{__WARN__} = sub { cluck $_[0] };
+$SIG{__DIE__} = sub { confess $_[0] };
+
my $bus = Net::DBus->session();
my $service = Net::DBus::Service->new("org.designfu.TestService",
$bus);
@@ -21,7 +26,19 @@ use base qw(Net::DBus::Object);
sub new {
my $class = shift;
my $self = $class->SUPER::new("/org/designfu/TestService/object",
- ["emitHelloSignal"],
+ {
+ "org.designfu.TestService" => {
+ methods => {
+ "emitHelloSignal" => {
+ params => [],
+ returns => [],
+ },
+ },
+ signals => {
+ "hello" => [],
+ },
+ },
+ },
@_);
bless $self, $class;
@@ -31,7 +48,7 @@ sub new {
sub emitHelloSignal {
my $self = shift;
- $self->emit_signal("org.designfu.TestService",
- "hello");
+ return $self->emit_signal("org.designfu.TestService",
+ "hello");
}
diff --git a/examples/example-signal-receiver.pl b/examples/example-signal-receiver.pl
index f870a0c..0a7e295 100644
--- a/examples/example-signal-receiver.pl
+++ b/examples/example-signal-receiver.pl
@@ -3,6 +3,11 @@
use Net::DBus;
use Net::DBus::Reactor;
+use Carp qw(confess cluck);
+
+#$SIG{__WARN__} = sub { cluck $_[0] };
+#$SIG{__DIE__} = sub { confess $_[0] };
+
my $bus = Net::DBus->session();
my $service = $bus->get_service("org.designfu.TestService");
@@ -17,9 +22,11 @@ sub hello_signal_handler {
$object->connect_to_signal("hello", \&hello_signal_handler);
-# Tell the remote object to emit the signal
-$object->emitHelloSignal();
-
my $reactor = Net::DBus::Reactor->new();
$reactor->manage($bus->{connection});
+
+$reactor->add_timeout(1000, Net::DBus::Callback->new(method => sub {
+ $object->emitHelloSignal();
+}));
+
$reactor->run();
diff --git a/lib/Net/DBus.pm b/lib/Net/DBus.pm
index 47043cd..0c30818 100644
--- a/lib/Net/DBus.pm
+++ b/lib/Net/DBus.pm
@@ -5,25 +5,20 @@ use strict;
use warnings;
use Carp;
+
+
+BEGIN {
+our $VERSION = '0.0.1';
+require XSLoader;
+XSLoader::load('Net::DBus', $VERSION);
+}
+
use Net::DBus::Binding::Bus;
use Net::DBus::Binding::Message;
use Net::DBus::Binding::Value;
use Net::DBus::RemoteService;
-our $VERSION = '0.0.1';
-
-use Exporter;
-
-use base qw(Exporter);
-use vars qw(@EXPORT);
-
- at EXPORT = qw(dboolean dbyte dstring dint32
- duint32 dint64 duint64 ddouble
- dstruct dpack);
-
-require XSLoader;
-XSLoader::load('Net::DBus', $VERSION);
sub system {
my $class = shift;
@@ -203,92 +198,6 @@ sub _signal_func {
return $handled;
}
-
-sub dboolean {
- my $value = shift;
- return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_BOOLEAN,
- $value);
-}
-
-sub dbyte {
- my $value = shift;
- return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_BYTE,
- $value);
-}
-
-sub dstring {
- my $value = shift;
- return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_STRING,
- $value);
-}
-
-sub dint32 {
- my $value = shift;
- return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_INT32,
- $value);
-}
-
-sub duint32 {
- my $value = shift;
- return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_UINT32,
- $value);
-}
-
-sub dint64 {
- my $value = shift;
- return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_INT64,
- $value);
-}
-
-sub duint64 {
- my $value = shift;
- return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_UINT64,
- $value);
-}
-
-sub ddouble {
- my $value = shift;
- return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_DOUBLE,
- $value);
-}
-
-sub dstruct {
- my $value = shift;
- return Net::DBus::Binding::Value->new(&Net::DBus::Binding::Message::TYPE_STRUCT,
- $value);
-}
-
-our %flags = (
- 'o' => &Net::DBus::Binding::Message::TYPE_BOOLEAN,
- 'b' => &Net::DBus::Binding::Message::TYPE_BYTE,
- 's' => &Net::DBus::Binding::Message::TYPE_STRING,
- 'i' => &Net::DBus::Binding::Message::TYPE_INT32,
- 'I' => &Net::DBus::Binding::Message::TYPE_UINT32,
- 'l' => &Net::DBus::Binding::Message::TYPE_INT64,
- 'L' => &Net::DBus::Binding::Message::TYPE_UINT64,
- 'd' => &Net::DBus::Binding::Message::TYPE_DOUBLE,
- );
-
-sub dpack {
- my $format = shift;
- my @in = @_;
- if (length $format != ($#in+1)) {
- confess "incorrect number of arguments for format string";
- }
-
- my @out;
- foreach my $flag (split //, $format) {
- my $value = shift @in;
- if (!exists $flags{$flag}) {
- confess "unknown format flag '$flag'";
- }
- push @out, Net::DBus::Binding::Value->new($flags{$flag},
- $value);
- }
- return @out;
-}
-
-
1;
__END__
diff --git a/lib/Net/DBus/Binding/Iterator.pm b/lib/Net/DBus/Binding/Iterator.pm
index 7543174..f83662e 100644
--- a/lib/Net/DBus/Binding/Iterator.pm
+++ b/lib/Net/DBus/Binding/Iterator.pm
@@ -276,30 +276,20 @@ sub get_struct {
sub append {
my $self = shift;
my $value = shift;
+ my $type = shift;
- my $type;
- if (@_) {
- $type = shift;
- } elsif (ref($value) eq "Net::DBus::Binding::Value") {
- $type = $value->type;
- $value = $value->value;
- } else {
- $type = &Net::DBus::Binding::Message::TYPE_STRING;
- }
-
- #warn "Type $type value $value\n";
-
- if (ref($value)) {
- if (ref($value) eq "HASH") {
- $self->append_dict($value);
- } elsif (ref($value) eq "ARRAY") {
- if ($type == &Net::DBus::Binding::Message::TYPE_STRUCT) {
- $self->append_struct($value);
- } else {
- $self->append_array($value, $type);
- }
+ if (ref($type) eq "ARRAY") {
+ my $maintype = $type->[0];
+ my $subtype = $type->[1];
+
+ if ($maintype == &Net::DBus::Binding::Message::TYPE_DICT_ENTRY) {
+ $self->append_dict($value, $subtype);
+ } elsif ($maintype == &Net::DBus::Binding::Message::TYPE_STRUCT) {
+ $self->append_struct($value, $subtype);
+ } elsif ($maintype == &Net::DBus::Binding::Message::TYPE_ARRAY) {
+ $self->append_array($value, $subtype);
} else {
- confess "Unsupported reference type ", ref($value);
+ confess "Unsupported compound type ", $maintype;
}
} else {
if ($type == &Net::DBus::Binding::Message::TYPE_BOOLEAN) {
@@ -329,12 +319,21 @@ sub append_array {
my $self = shift;
my $array = shift;
my $type = shift;
-
- my $sig = chr($type);
+
+ die "array must only have one type"
+ if $#{$type} > 0;
+
+ my $sig;
+ if (ref($type->[0])) {
+ $sig = chr($type->[0]->[0]);
+ } else {
+ $sig = chr($type->[0]);
+ }
+
my $iter = $self->_open_container(&Net::DBus::Binding::Message::TYPE_ARRAY, $sig);
foreach my $value (@{$array}) {
- $iter->append($value, $type);
+ $iter->append($value, $type->[0]);
}
$self->_close_container($iter);
@@ -344,11 +343,17 @@ sub append_array {
sub append_struct {
my $self = shift;
my $struct = shift;
-
+ my $type = shift;
+
+ if ($#{$struct} != $#{$type}) {
+ die "number of values does not match type";
+ }
+
my $iter = $self->_open_container(&Net::DBus::Binding::Message::TYPE_STRUCT, undef);
+ my @type = @{$type};
foreach my $value (@{$struct}) {
- $iter->append($value);
+ $iter->append($value, shift @type);
}
$self->_close_container($iter);
@@ -358,7 +363,8 @@ sub append_struct {
sub append_dict {
my $self = shift;
my $hash = shift;
-
+ my $type = shift;
+
# XXX don't hardcode me - cf Python bindings
my $sig = "{ss}";
my $iter = $self->_open_container(&Net::DBus::Binding::Message::TYPE_ARRAY, $sig);
@@ -367,8 +373,8 @@ sub append_dict {
my $value = $hash->{$key};
my $entry = $iter->_open_container(&Net::DBus::Binding::Message::TYPE_DICT_ENTRY, $sig);
- $entry->append($key);
- $entry->append($value);
+ $entry->append($key, $type->[0]);
+ $entry->append($value, $type->[1]);
$iter->_close_container($entry);
}
$self->_close_container($iter);
diff --git a/lib/Net/DBus/Introspector.pm b/lib/Net/DBus/Introspector.pm
new file mode 100644
index 0000000..0edb420
--- /dev/null
+++ b/lib/Net/DBus/Introspector.pm
@@ -0,0 +1,369 @@
+=pod
+
+ name => "org.foo.bar.Object"
+ interfaces =>
+ "org.foo.bar.Wibble" => {
+ methods => {
+ foo => {
+ params => ["int32", "double", ["array", ["int32"]]],
+ return => ["string", "byte", ["dict", ["string", "variant"]]]
+ }
+ }
+ }
+ }
+ children => [
+ introspector...
+ ];
+
+=cut
+
+package Net::DBus::Introspector;
+
+use 5.006;
+use strict;
+use warnings;
+use Carp;
+use XML::Grove::Builder;
+use XML::Parser::PerlSAX;
+
+use Net::DBus;
+use Net::DBus::Binding::Message;
+
+our %simple_type_map = (
+ "byte" => &Net::DBus::Binding::Message::TYPE_BYTE,
+ "bool" => &Net::DBus::Binding::Message::TYPE_BOOLEAN,
+ "double" => &Net::DBus::Binding::Message::TYPE_DOUBLE,
+ "string" => &Net::DBus::Binding::Message::TYPE_STRING,
+ "int32" => &Net::DBus::Binding::Message::TYPE_INT32,
+ "uint32" => &Net::DBus::Binding::Message::TYPE_UINT32,
+ "int64" => &Net::DBus::Binding::Message::TYPE_INT64,
+ "uint64" => &Net::DBus::Binding::Message::TYPE_UINT64,
+);
+
+our %compound_type_map = (
+ "array" => &Net::DBus::Binding::Message::TYPE_ARRAY,
+ "struct" => &Net::DBus::Binding::Message::TYPE_STRUCT,
+ "dict" => &Net::DBus::Binding::Message::TYPE_DICT_ENTRY,
+);
+
+
+our $VERSION = '0.0.1';
+
+sub new {
+ my $class = shift;
+ my $self = {};
+ my %params = @_;
+
+ bless $self, $class;
+
+ if (defined $params{xml}) {
+ $self->_parse($params{xml});
+ } else {
+ $self->{name} = exists $params{name} ? $params{name} : die "name parameter is required";
+ $self->{interfaces} = exists $params{interfaces} ? $params{interfaces} : die "interfaces parameter is required";
+ $self->{children} = exists $params{children} ? $params{children} : [];
+ }
+
+ $self->{interfaces}->{"org.freedesktop.DBus.Introspectable"} = {
+ methods => {
+ "Introspect" => {
+ params => [],
+ returns => ["string"],
+ }
+ }
+ };
+
+ $self->{methods} = {};
+ $self->{signals} = {};
+ foreach my $name (keys %{$self->{interfaces}}) {
+ my $interface = $self->{interfaces}->{$name};
+ foreach my $method (keys %{$interface->{methods}}) {
+ $self->{methods}->{$method} = $interface->{methods}->{$method};
+ }
+ foreach my $signal (keys %{$interface->{signals}}) {
+ $self->{signals}->{$signal} = $interface->{signals}->{$signal};
+ }
+ }
+
+ return $self;
+}
+
+sub _parse {
+ my $self = shift;
+ my $xml = shift;
+
+ my $grove_builder = XML::Grove::Builder->new;
+ my $parser = XML::Parser::PerlSAX->new(Handler => $grove_builder);
+ my $document = $parser->parse ( Source => { String => $xml } );
+
+ my $root = $document->{Contents}->[0];
+
+ $self->{name} = $root->{Attributes}->{name};
+ $self->{interfaces} = {};
+ foreach my $child (@{$root->{Contents}}) {
+ if (ref($child) eq "XML::Grove::Element" &&
+ $child->{Name} eq "interface") {
+ $self->_parse_interface($child);
+ }
+ }
+}
+
+sub _parse_interface {
+ my $self = shift;
+ my $node = shift;
+
+ my $name = $node->{Attributes}->{name};
+ $self->{interfaces}->{$name} = {
+ methods => {},
+ signals => {},
+ };
+
+ foreach my $child (@{$node->{Contents}}) {
+ if (ref($child) eq "XML::Grove::Element" &&
+ $child->{Name} eq "method") {
+ $self->_parse_method($child, $name);
+ } elsif (ref($child) eq "XML::Grove::Element" &&
+ $child->{Name} eq "signal") {
+ $self->_parse_signal($child, $name);
+ }
+ }
+}
+
+sub _parse_method {
+ my $self = shift;
+ my $node = shift;
+ my $interface = shift;
+
+ my $name = $node->{Attributes}->{name};
+ my @params;
+ my @returns;
+ foreach my $child (@{$node->{Contents}}) {
+ if (ref($child) eq "XML::Grove::Element" &&
+ $child->{Name} eq "arg") {
+ my $type = $child->{Attributes}->{type};
+ my $direction = $child->{Attributes}->{direction};
+
+ if (exists $compound_type_map{lc $type}) {
+ my @subtype = $self->_parse_type($child);
+ if ($direction eq "in") {
+ push @params, [lc $type, \@subtype];
+ } elsif ($direction eq "out") {
+ push @returns, [lc $type, \@subtype];
+ }
+ } elsif (exists $simple_type_map{lc $type}) {
+ if ($direction eq "in") {
+ push @params, lc $type;
+ } elsif ($direction eq "out") {
+ push @returns, lc $type;
+ }
+ }
+ }
+ }
+
+ $self->{interfaces}->{$interface}->{methods}->{$name} = {
+ params => \@params,
+ returns => \@returns,
+ }
+}
+
+sub _parse_type {
+ my $self = shift;
+ my $node = shift;
+
+
+ my @types;
+ foreach my $child (@{$node->{Contents}}) {
+ if (ref($child) eq "XML::Grove::Element" &&
+ $child->{Name} eq "type") {
+ my $name = $child->{Attributes}->{name};
+
+ if (exists $compound_type_map{lc $name}) {
+ my @subtype = $self->_parse_type($child);
+ push @types, [lc $name, \@subtype];
+ } elsif (exists $simple_type_map{lc $name}) {
+ push @types, lc $name;
+ }
+ }
+ }
+
+ return @types;
+}
+
+sub _parse_signal {
+ my $self = shift;
+ my $node = shift;
+ my $interface = shift;
+
+ my $name = $node->{Attributes}->{name};
+ my @params;
+ foreach my $child (@{$node->{Contents}}) {
+ if (ref($child) eq "XML::Grove::Element" &&
+ $child->{Name} eq "arg") {
+ my $type = $child->{Attributes}->{type};
+
+ if (exists $compound_type_map{lc $type}) {
+ my @subtype = $self->_parse_type($child);
+ push @params, [lc $type, \@subtype];
+ } elsif (exists $simple_type_map{lc $type}) {
+ push @params, lc $type;
+ }
+ }
+ }
+
+ $self->{interfaces}->{$interface}->{signals}->{$name} =
+ \@params;
+}
+
+sub format {
+ my $self = shift;
+
+ my $xml = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"' . "\n";
+ $xml .= '"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">' . "\n";
+
+ return $xml . $self->to_xml("");
+}
+
+sub to_xml {
+ my $self = shift;
+ my $indent = shift;
+
+ my $xml = '';
+ $xml .= $indent . '<node name="' . $self->{name} . '">' . "\n";
+
+ foreach my $name (keys %{$self->{interfaces}}) {
+ my $interface = $self->{interfaces}->{$name};
+ $xml .= $indent . ' <interface name="' . $name . '">' . "\n";
+ foreach my $mname (keys %{$interface->{methods}}) {
+ my $method = $interface->{methods}->{$mname};
+ $xml .= $indent . ' <method name="' . $mname . '">' . "\n";
+
+ foreach my $type (@{$method->{params}}) {
+ if (ref($type) eq "ARRAY") {
+ $xml .= $indent . ' <arg type="' . $type->[0] . '" direction="in">' . "\n";
+ $xml .= $self->to_xml_type($type->[1], $indent . ' ');
+ $xml .= $indent . ' </arg>' . "\n";
+ } else {
+ $xml .= $indent . ' <arg type="' . $type . '" direction="in"/>' . "\n";
+ }
+ }
+
+ foreach my $type (@{$method->{returns}}) {
+ if (ref($type) eq "ARRAY") {
+ $xml .= $indent . ' <arg type="' . $type->[0] . '" direction="out">' . "\n";
+ $xml .= $self->to_xml_type($type->[1], $indent . ' ');
+ $xml .= $indent . ' </arg>' . "\n";
+ } else {
+ $xml .= $indent . ' <arg type="' . $type . '" direction="out"/>' . "\n";
+ }
+ }
+
+
+ $xml .= $indent . ' </method>' . "\n";
+ }
+ foreach my $sname (keys %{$interface->{signals}}) {
+ my $signal = $interface->{signals}->{$sname};
+ $xml .= $indent . ' <signal name="' . $sname . '">' . "\n";
+
+ foreach my $type (@{$signal}) {
+ if (ref($type) eq "ARRAY") {
+ $xml .= $indent . ' <arg type="' . $type->[0] . '">' . "\n";
+ $xml .= $self->to_xml_type($type->[1], $indent . ' ');
+ $xml .= $indent . ' </arg>' . "\n";
+ } else {
+ $xml .= $indent . ' <arg type="' . $type . '"/>' . "\n";
+ }
+ }
+ $xml .= $indent . ' </signal>' . "\n";
+ }
+
+ $xml .= $indent . ' </interface>' . "\n";
+ }
+
+ foreach my $child (@{$self->{children}}) {
+ if (ref($child) eq "Net::DBus::Introspector") {
+ $xml .= $child->to_xml($indent . " ") . "\n";
+ } else {
+ $xml .= $indent . ' <node name="' . $child . '"/>' . "\n";
+ }
+ }
+ $xml .= $indent . "</node>";
+}
+
+
+sub to_xml_type {
+ my $self = shift;
+ my $type = shift;
+ my $indent = shift;
+ my $xml = '';
+ foreach my $subtype (@{$type}) {
+ if (ref($subtype) eq "ARRAY") {
+ $xml .= $indent . ' <type name="' . $subtype->[0] . '">' . "\n";
+ $xml .= $self->to_xml_type($subtype->[1], $indent . ' ');
+ $xml .= $indent . ' </type>' . "\n";
+ } else {
+ $xml .= $indent . ' <type name="' . $subtype . '"/>' . "\n";
+ }
+ }
+ return $xml;
+}
+
+sub encode {
+ my $self = shift;
+ my $message = shift;
+ my $type = shift;
+ my $name = shift;
+ my $direction = shift;
+ my @args = @_;
+
+ die "no introspection data for such $name ($type)" unless exists $self->{$type}->{$name};
+
+ my @types = $type eq "signals" ?
+ @{$self->{$type}->{$name}} :
+ @{$self->{$type}->{$name}->{$direction}};
+
+ die "expected " . int(@types) . " params, but got " . int(@args)
+ unless $#types == $#args;
+
+ my $iter = $message->iterator(1);
+ foreach my $t ($self->convert(@types)) {
+ $iter->append(shift @args, $t);
+ }
+}
+
+
+sub convert {
+ my $self = shift;
+ my @in = @_;
+
+ my @out;
+ foreach my $in (@in) {
+ if (ref($in) eq "ARRAY") {
+ my @subout = $self->convert(@{$in->[1]});
+ die "unknown compound type " . $in->[0] unless
+ exists $compound_type_map{lc $in->[0]};
+ push @out, [$compound_type_map{lc $in->[0]}, \@subout];
+ } else {
+ die "unknown simple type " . $in unless
+ exists $simple_type_map{lc $in};
+ push @out, $simple_type_map{lc $in};
+ }
+ }
+ return @out;
+}
+
+sub decode {
+ my $self = shift;
+ my $message = shift;
+ my $type = shift;
+ my $name = shift;
+ my $direction = shift;
+ my @args = @_;
+
+ die "no introspection data for such $name ($type)" unless exists $self->{$type}->{$name};
+
+ my @type = $type eq "signal" ?
+ @{$self->{$type}->{$name}} :
+ @{$self->{$type}->{$name}->{$direction}};
+
+
+}
diff --git a/lib/Net/DBus/Object.pm b/lib/Net/DBus/Object.pm
index 1ee77dc..07340af 100644
--- a/lib/Net/DBus/Object.pm
+++ b/lib/Net/DBus/Object.pm
@@ -8,6 +8,7 @@ use Carp;
our $VERSION = '0.0.1';
use Net::DBus::RemoteObject;
+use Net::DBus::Introspector;
use Net::DBus::Binding::Message::Error;
use Net::DBus::Binding::Message::MethodReturn;
@@ -16,10 +17,10 @@ sub new {
my $self = {};
$self->{object_path} = shift;
-
- my $methods = shift;
- $self->{methods} = {};
- map { $self->{methods}->{$_} = 1 } @{$methods};
+
+ my $interfaces = shift;
+ $self->{introspector} = Net::DBus::Introspector->new(name => $self->{object_path},
+ interfaces => $interfaces);
$self->{service} = shift;
@@ -35,18 +36,28 @@ sub new {
}
+sub Introspect {
+ my $self = shift;
+ #warn "Asked for introspection data\n";
+ my $xml = $self->{introspector}->format;
+ #warn $xml;
+ return $xml;
+}
+
+
sub emit_signal {
my $self = shift;
my $interface = shift;
my $signal_name = shift;
+ my @args = @_;
my $signal = Net::DBus::Binding::Message::Signal->new(object_path => $self->{object_path},
interface => $interface,
signal_name => $signal_name);
- my $iter = $signal->iterator(1);
- foreach my $ret (@_) {
- $iter->append($ret);
- }
+
+ $self->{introspector}->encode($signal, "signals", $signal_name, "params", @args);
$self->{service}->get_bus()->get_connection()->send($signal);
+
+ return ();
}
sub _dispatch {
@@ -68,15 +79,8 @@ sub _dispatch {
description => $@);
} else {
$reply = Net::DBus::Binding::Message::MethodReturn->new(call => $message);
- if (@ret == 1) {
- my $iter = $reply->iterator(1);
- $iter->append(shift @ret);
- } elsif (@ret > 1) {
- my $iter = $reply->iterator(1);
- foreach my $ret (@ret) {
- $iter->append($ret);
- }
- }
+
+ $self->{introspector}->encode($reply, "methods", $method_name, "returns", @ret);
}
} else {
$reply = Net::DBus::Binding::Message::Error->new(replyto => $message,
diff --git a/lib/Net/DBus/RemoteObject.pm b/lib/Net/DBus/RemoteObject.pm
index 78ffbca..811d3d1 100644
--- a/lib/Net/DBus/RemoteObject.pm
+++ b/lib/Net/DBus/RemoteObject.pm
@@ -9,6 +9,7 @@ our $VERSION = '0.0.1';
our $AUTOLOAD;
use Net::DBus::Binding::Message::MethodCall;
+use Net::DBus::Introspector;
sub new {
my $class = shift;
@@ -17,12 +18,34 @@ sub new {
$self->{service} = shift;
$self->{object_path} = shift;
$self->{interface} = shift;
-
+
bless $self, $class;
+ $self->{introspector} = @_ ? shift : $self->_introspect();
+
return $self;
}
+sub _introspect {
+ my $self = shift;
+
+ my $call = Net::DBus::Binding::Message::MethodCall->
+ new(service_name => $self->{service}->get_service_name(),
+ object_path => $self->{object_path},
+ method_name => "Introspect",
+ interface => "org.freedesktop.DBus.Introspectable");
+
+ my $reply = $self->{service}->
+ get_bus()->
+ get_connection()->
+ send_with_reply_and_block($call, 5000);
+
+ my $iter = $reply->iterator;
+ my $xml = $iter->get(&Net::DBus::Binding::Message::TYPE_STRING);
+
+ return Net::DBus::Introspector->new(xml => $xml);
+}
+
sub connect_to_signal {
my $self = shift;
my $signal_name = shift;
@@ -54,17 +77,15 @@ sub AUTOLOAD {
method_name => $method,
interface => $self->{interface});
- my $iter = $call->iterator(1);
- foreach my $arg (@_) {
- $iter->append($arg);
- }
-
+ $self->{introspector}->encode($call, "methods", $method, "params", @_);
+
my $reply = $self->{service}->
get_bus()->
get_connection()->
send_with_reply_and_block($call, 5000);
- my @reply = $reply->get_args_list;
+ my @reply = $reply->get_args_list();
+ #my @reply = $self->{introspector}->decode($reply, $method, "return");
return wantarray ? @reply : $reply[0];
}
diff --git a/t/40-introspector.t b/t/40-introspector.t
new file mode 100644
index 0000000..77512de
--- /dev/null
+++ b/t/40-introspector.t
@@ -0,0 +1,63 @@
+# -*- perl -*-
+use Test::More tests => 2;
+BEGIN {
+ use_ok('Net::DBus::Introspector');
+ };
+
+
+TEST_ONE: {
+ my $other_object = Net::DBus::Introspector->new(
+ name => "org.example.OtherObject",
+ interfaces => {
+ "org.example.SomeInterface" => {
+ methods => {
+ "hello" => {
+ params => ["int32", "int32", ["struct", ["int32","byte"]]],
+ returns => ["int32"],
+ },
+ "goodbye" => {
+ params => [["array", [["struct", ["int32", "string"]]]]],
+ returns => ["string", "string"],
+ },
+ },
+ signals => {
+ "meltdown" => ["int32", "byte"],
+ }
+ }
+ });
+ my $object = Net::DBus::Introspector->new(
+ name => "org.example.Object",
+ interfaces => {
+ "org.example.SomeInterface" => {
+ methods => {
+ "hello" => {
+ params => ["int32", "int32", ["struct", ["int32","byte"]]],
+ returns => ["int32"],
+ },
+ "goodbye" => {
+ params => [["array", [["struct", ["int32", "string"]]]]],
+ returns => ["string", "string"],
+ },
+ },
+ signals => {
+ "meltdown" => ["int32", "byte"],
+ },
+ },
+ "org.example.OtherInterface" => {
+ methods => {
+ "hitme" => {
+ params => ["int32", "uint32"],
+ return => [],
+ }
+ }
+ },
+ },
+ children => [
+ "org.example.AnotherObject",
+ $other_object,
+ ]);
+
+ isa_ok($object, "Net::DBus::Introspector");
+
+ warn $object->format;
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libnet-dbus-perl.git
More information about the Pkg-perl-cvs-commits
mailing list