File Coverage

blib/lib/RPC/JSON/Shell.pm
Criterion Covered Total %
statement 18 83 21.6
branch 0 34 0.0
condition 0 32 0.0
subroutine 6 12 50.0
pod 6 6 100.0
total 30 167 17.9


line stmt bran cond sub pod time code
1             package RPC::JSON::Shell;
2              
3 2     2   19 use warnings;
  2         2  
  2         56  
4 2     2   9 use strict;
  2         3  
  2         58  
5              
6 2     2   10 use vars qw|$VERSION @EXPORT $DEBUG $META $AUTOLOAD|;
  2         4  
  2         215  
7              
8             $VERSION = '0.02';
9              
10             @RPC::JSON::Shell = qw|Exporter|;
11              
12 2     2   10 use RPC::JSON;
  2         4  
  2         45  
13 2     2   1931 use Term::ReadLine;
  2         6447  
  2         95  
14 2     2   2069 use Data::Dumper;
  2         15321  
  2         2248  
15              
16             my $rpcInstance;
17              
18             =head1 NAME
19              
20             RPC::JSON::Shell - Interactive JSON-RPC Shell
21              
22             =head1 SYNOPSIS
23              
24             perl -MRPC::JSON -e "RPC::JSON::shell"
25              
26             Not connected> connect http://www.dev.simplymapped.com/services/geocode/json.smd
27             GeocodeService > geocode "1600 Pennsylvania Ave Washington DC"
28             $VAR1 = [
29             {
30             'administrativearea' => 'DC',
31             'country' => 'US',
32             'longitude' => '-77.037691',
33             'subadministrativearea' => 'District of Columbia',
34             'locality' => 'Washington',
35             'latitude' => '38.898758',
36             'thoroughfare' => '1600 Pennsylvania Ave NW',
37             'postalcode' => 20004,
38             'address' => '1600 Pennsylvania Ave NW, Washington, DC 20004, USA'
39             }
40             ];
41              
42             =head1 DESCRIPTION
43              
44             This module is an interactive client to a JSON-RPC service. It is currently
45             in its infancy and is likely to be very unstable. There are many bugs in this
46             package.
47              
48             =cut
49              
50             =item shell
51              
52             Initiate a shell session
53              
54             =cut
55              
56             sub shell {
57 0     0 1   my ( $service ) = @_;
58 0           my $term = new Term::ReadLine 'RPC::JSON::Shell';
59 0           my $prompt = "Not connected > ";
60 0   0       my $out = $term->OUT || \*STDOUT;
61              
62 0 0         if ( $service ) {
63 0           __PACKAGE__->connect($out, $service);
64 0 0 0       if ( $rpcInstance and $rpcInstance->service ) {
65 0           $prompt = sprintf("%s > ", $rpcInstance->service);
66             }
67             }
68              
69 0           while ( defined ( $_ = $term->readline($prompt) ) ) {
70 0           s/^\s+|\s+$//g;
71 0           my ( $method, @args ) = split(/\s+/, $_);
72 0           my @d = (); my $curArg;
  0            
73 0           foreach my $arg ( @args ) {
74 0 0 0       if ( $curArg and $arg =~ /"\s*$/ ) {
    0 0        
    0          
75 0           $curArg .= " $arg";
76 0           $curArg =~ s/^(\s*")|("\s*)$//g;
77 0           push @d, $curArg;
78 0           $curArg = '';
79             }
80             elsif ( $arg =~ /^\s*"/ and not $curArg ) {
81 0           $curArg = $arg;
82             }
83             elsif ( $curArg ) {
84 0           $curArg .= " $arg";
85             }
86             else {
87 0           push @d, $arg;
88             }
89             }
90              
91 0 0         if ( __PACKAGE__->can(lc($method)) ) {
    0          
    0          
92 0           my $l = lc($method);
93 0           __PACKAGE__->$l($out, @d);
94             }
95             elsif ( $method =~ /^quit|exit$/i ) {
96 0           return 1;
97             }
98             elsif ( $rpcInstance->methods->{$method} ) {
99 0           __PACKAGE__->method($out, $method, @d);
100             } else {
101 0           print Dumper $rpcInstance->methods->{$method};
102 0           print $out "Unrecognized command $method, type help for a list of commands\n";
103             }
104 0 0 0       if ( $rpcInstance and $rpcInstance->service ) {
105 0           $prompt = sprintf("%s > ", $rpcInstance->service);
106             } else {
107 0           $prompt = "Not connected > ";
108             }
109             }
110             }
111              
112             =item help
113              
114             Display the help text.
115              
116             =cut
117              
118             sub help {
119 0     0 1   my ( $class, $out, @args ) = @_;
120 0           print $out qq|
121             RPC::JSON::Shell Help
122             ---------------------
123             Below is a full listing of commands, and how they can be used:
124             connect - Connect to a URI, must be an SMD.
125             disconnect - Close connection to a specific URI (if connected)
126              
127             ls - List available methods
128             LIST - Call method with parameters LIST
129              
130             quit - Exit RPC::JSON::Shell
131             |;
132              
133             }
134              
135             =item connect smdUrl
136              
137             Connect to the specified SMD URL
138              
139             =cut
140              
141             sub connect {
142 0     0 1   my ( $class, $out, @args ) = @_;
143 0 0         if ( @args == 1 ) {
144 0           print $out "Connecting to $args[0]\n";
145 0 0         if ( $rpcInstance ) {
146 0           print $out "Closing previous RPC connection\n";
147             }
148 0           $rpcInstance = new RPC::JSON({ smd => $args[0] });
149 0 0         unless ( $rpcInstance ) {
150 0           print $out "Can't connect to $args[0], check specified URI\n";
151 0           return 0;
152             }
153             } else {
154 0           print $out "Usage: connect \n";
155             }
156             }
157              
158             =item disconnect
159              
160             If connected, will disconnect from the existing service. This doesn't
161             necessarily mean that it will disconnect the socket (it will if the socket is
162             still open), because JSON-RPC does not require a dedicated connection.
163              
164             =cut
165              
166             sub disconnect {
167 0     0 1   my ( $class, $out, @args ) = @_;
168 0 0 0       if ( $rpcInstance and $rpcInstance->service ) {
169 0           print $out "Disconnecting from " . $rpcInstance->serviceURI . "\n";
170 0           $rpcInstance = undef;
171             }
172             }
173              
174             =item quit
175              
176             Aliased to disconnected
177              
178             =cut
179              
180             =item ls
181              
182             List available methods
183              
184             =cut
185              
186             sub ls {
187 0     0 1   my ( $class, $out, @args ) = @_;
188 0 0 0       if ( $rpcInstance and $rpcInstance->service ) {
189 0           my $methods = $rpcInstance->methods;
190 0 0 0       if ( $methods and ref $methods eq 'HASH' and %$methods ) {
      0        
191 0           foreach my $method ( keys %$methods ) {
192 0           my $params = join(" ",
193 0           map { "$_->{name}:$_->{type}" }
194 0           @{$methods->{$method}});
195 0           print $out "\t$method: $params\n";
196             }
197             } else {
198 0           print $out "Service seems empty (No Methods?)\n";
199             }
200             } else {
201 0           print $out "Connect first (use connect )\n";
202             }
203             }
204              
205             =item method Caller
206              
207             By entering [parameters] the shell will query the Service and display
208             results
209              
210             =cut
211              
212             sub method {
213 0     0 1   my ( $self, $out, $method, @args ) = @_;
214              
215 0 0 0       if ( $rpcInstance and $rpcInstance->service and $method ) {
      0        
216 0 0         if ( ( my $result = $rpcInstance->$method(@args) ) ) {
217 0           print $out Dumper($result);
218             } else {
219 0           print $out "Can't call method $method\n";
220             }
221             } else {
222 0           print $out "Connect first (use connect )\n";
223             }
224             }
225              
226             =head1 AUTHORS
227              
228             Copyright 2006 J. Shirley
229              
230             This program is free software; you can redistribute it and/or modify it under
231             the same terms as Perl itself. That means either (a) the GNU General Public
232             License or (b) the Artistic License.
233              
234             =cut
235              
236             1;