File Coverage

blib/lib/AMF/Perl/App/Executive.pm
Criterion Covered Total %
statement 6 87 6.9
branch 0 32 0.0
condition 0 12 0.0
subroutine 2 12 16.6
pod 3 10 30.0
total 11 153 7.1


line stmt bran cond sub pod time code
1             package AMF::Perl::App::Executive;
2             # Copyright (c) 2003 by Vsevolod (Simon) Ilyushchenko. All rights reserved.
3             # This program is free software; you can redistribute it and/or modify it
4             # under the same terms as Perl itself.
5             # The code is based on the -PHP project (http:#amfphp.sourceforge.net/)
6              
7             =head1 NAME
8              
9             AMF::Perl::App::Executive
10              
11             =head1 DESCRIPTION
12              
13             Executive package figures out whether to call an explicitly
14             registered package or to look one up in a registered directory.
15             Then it executes the desired method in the package.
16              
17             =head1 CHANGES
18              
19             =head2 Wed Apr 14 11:06:28 EDT 2004
20              
21             =item Added return type determination for registered methods.
22              
23             =head2 Sun Mar 23 13:27:00 EST 2003
24              
25             =over 4
26              
27             =item Synching with AMF-PHP:
28              
29             =item Replaced packagepath, packagename, packageConstruct with classpath, classname, classConstruct.
30              
31             =item Added _instanceName, _origClassPath and _headerFilter.
32              
33             =item Added subs setHeaderFilter(), setInstanceName()
34              
35             =item Renamed setClassPath to setTarget and removed extra junk from that function.
36              
37             =item Eliminated _getPackage() and _getMethod().
38              
39             =item Removed safeExecution().
40              
41             =back
42              
43             =head2 Tue Mar 11 21:59:27 EST 2003
44              
45             =item Passing @$a instead of $a to user functions. $a always is an array.
46              
47             =cut
48              
49              
50 1     1   5 use strict;
  1         2  
  1         34  
51 1     1   470 use AMF::Perl::Util::RemotingService;
  1         2  
  1         7249  
52              
53              
54             #The above variable declarations are not needed, as hash keys are used. They are useful just for the comments.
55             # the directory which should be used for the basic packages default "../"
56             # my $_basecp = "../";
57             # the classpath which is the path of the file from $_basecp
58             #my $_classpath;
59             # the string name of the package derived from the classpath
60             #my $_classname;
61             # the object we build from the package
62             #my $_classConstruct;
63             # the method to execute in the construct
64             #my $_methodname;
65             # the defined return type
66             #my $_returnType;
67             # the instance name to use for this gateway executive
68             #my $_instanceName;
69             # the list with registered service-packagees
70             #my $services = {};
71             # The original incoming classpath
72             #my $_target;
73             # The original classpath
74             #my $_origClassPath;
75             # switch to take different actions based on the header
76             #my $_headerFilter;
77            
78             # constructor
79             sub new
80             {
81 0     0 0   my ($proto)=@_;
82 0           my $self={};
83 0           bless $self, $proto;
84 0           return $self;
85             # nothing really to do here yet?
86             }
87              
88              
89             # setter for the _headerFilter
90             sub setHeaderFilter
91             {
92 0     0 1   my ($self, $header) = @_;
93 0           $self->{_headerFilter} = $header;
94             }
95              
96             # Set the base classpath. This is the path from which will be search for the packagees and functions
97             # $basecp should end with a "/";
98             sub setBaseClassPath
99             {
100 0     0 0   my ($self, $basecp) = @_;
101 0           $self->{_basecp} = $basecp;
102             }
103              
104             sub setInstanceName
105             {
106 0     0 1   my ($self, $name) = @_;
107 0           $self->{_instanceName} = $name;
108             }
109              
110             # you pass directory.script.method to this and it will build
111             # the classpath, classname and methodname values
112             sub setTarget
113             {
114 0     0 1   my ($self, $target)=@_;
115 0           $self->{target} = $target;
116             # grab the position of the last . char
117 0           my $lpos = strrpos($target, ".");
118             # there were none
119 0 0         unless ($lpos)
120             {
121 0           print STDERR "Service name $target does not contain a dot.\n";
122             # throw an error because there has to be atleast 1
123             }
124             else
125             {
126             # the method name is the very last part
127 0           $self->{_methodname} = substr($target, $lpos+1);
128             }
129             # truncate the method name from the string
130 0           my $trunced = substr($target, 0, $lpos);
131            
132 0           $self->{_classname} = $trunced;
133             }
134              
135             sub registerService
136             {
137 0     0 0   my ($self, $package, $servicepackage) = @_;
138 0           $self->{services}->{$package} = $servicepackage;
139             }
140              
141             # returns the return type for this method
142             sub getReturnType
143             {
144 0     0 0   my ($self)=@_;
145 0           return $self->{_returnType};
146             }
147              
148             # execute the method using dynamic inclusion of Perl files
149             sub doMethodCall
150             {
151 0     0 0   my ($self, $a) = @_;
152            
153             #First try to call a registered class...
154 0           my $package = $self->{_classname};
155 0           my $method = $self->{_methodname};
156            
157 0           my $calledMethod = $method;
158            
159 0 0         if(exists $self->{services}->{$package})
160             {
161 0           return $self->doMethodCall_registered($package, $method, $a);
162             }
163            
164             #Otherwise, browse in the directory specified by the user.
165              
166 0           push @INC, $self->{_basecp};
167              
168             # build the class object
169            
170 0           $package =~ s#\.#::#g;
171            
172 0 0         unless (eval ("require " . $package))
173             {
174             # report back to flash that the class wasn't properly formatted
175 0           print STDERR "Class $package does not exist or could not be loaded.\n";
176 0           print STDERR $@;
177 0           return;
178             }
179              
180             # build the construct from the extended class
181 0           my $object = $package->new;
182            
183             # Check to see if the DescribeService header has been turned on
184 0 0 0       if ($self->{_headerFilter} && $self->{_headerFilter} eq "DescribeService")
185             {
186 0           my $wrapper = new AMF::Perl::Util::RemotingService($package, $object);
187              
188 0           $self->{_classConstruct} = $wrapper;
189              
190 0           $method = "__describeService";
191              
192             # override the method name to the __describeService method
193 0           $self->{_methodname} = $method;
194              
195             # add the instance to the methodrecord to control registered discover
196 0           my $methodTable = $self->{_classConstruct}->methodTable;
197 0           $methodTable->{$method}{'instance'} = $self->{_instanceName};
198              
199             }
200             else
201             {
202 0           $self->{_classConstruct} = $object;
203             }
204              
205             # was this defined in the methodTable -- required to enable AMF::Perl service approach
206 0 0         if (exists ($self->{_classConstruct}->methodTable->{$method}))
207             {
208             # create a shortcut to the methodTable
209 0           my %methodrecord = %{$self->{_classConstruct}->methodTable->{$method}};
  0            
210              
211             # check to see if this method name is aliased
212 0 0         if (exists ($methodrecord{'alias'}))
213             {
214             # map the _methodname to the alias
215 0           $method = $methodrecord{'alias'};
216             }
217              
218 0 0         if (exists($methodrecord{'instance'}))
219             {
220             # check the instance names to see if they match. If so, then let this happen
221 0 0 0       if (!exists($methodrecord{'instance'}) || $self->{_instanceName} != $methodrecord{'instance'})
222             {
223             # if they don't match then print STDERR with this error
224 0           print STDERR "Access error for " . $self->{_headerFilter} . ".\n";
225 0           return;
226             }
227             }
228            
229             # check to see if an explicit return type was defined
230 0 0         if (exists($methodrecord{'returns'}))
231             {
232 0           $self->{_returnType} = $methodrecord{'returns'};
233             }
234             # set the default return type of "unknown"
235             else
236             {
237 0           $self->{_returnType} = "unknown";
238             }
239             # set to see if the access was set and the method as remote permissions.
240 0 0 0       if ( (exists($methodrecord{'access'})) && (lc ($methodrecord{'access'}) eq "remote"))
241             {
242             # finally check to see if the method existed
243 0 0         if ($self->{_classConstruct}->can($method))
244             {
245             # execute the method and return it's results to the gateway
246 0           return $self->{_classConstruct}->$method(@$a);
247             }
248             else
249             {
250             # print STDERR with error
251 0           print STDERR "Method " . $calledMethod . " does not exist in class ".$self->{_classConstruct}.".\n";
252             }
253             }
254             else
255             {
256             # print STDERR with error
257 0           print STDERR "Access Denied to " . $calledMethod . "\n";
258             }
259            
260            
261             }
262             else
263             {
264             # print STDERR with error
265 0           print STDERR "Function " . $calledMethod . " does not exist in class ".$self->{_classConstruct}.".\n";
266             }
267              
268             }
269              
270             sub doMethodCall_registered
271             {
272 0     0 0   my ($self, $package, $method, $a) = @_;
273            
274 0           my $serviceobject = $self->{services}->{$package};
275              
276 0 0         if(length($package) == 0)
    0          
    0          
277             {
278             # TODO: handle non packaged functions
279             #trigger_error("ERROR: no package in call",E_USER_ERROR);
280 0           return;
281             }
282             elsif(!$serviceobject)
283             {
284 0           print STDERR "Package ".$package." not registerd on server\n";
285 0           return;
286             }
287             elsif(!$serviceobject->can($method))
288             {
289 0           print STDERR "Function ".$method." does not exist in package ".$package."\n";
290 0           return;
291             }
292             else
293             {
294 0           $self->{_returnType} = "unknown";
295              
296 0 0 0       if ($serviceobject->can("methodTable") && exists ($serviceobject->methodTable->{$method}))
297             {
298             # create a shortcut to the methodTable
299 0           my %methodrecord = %{$serviceobject->methodTable->{$method}};
  0            
300             # check to see if an explicit return type was defined
301 0 0         if (exists($methodrecord{'returns'}))
302             {
303 0           $self->{_returnType} = $methodrecord{'returns'};
304             }
305             # set the default return type of "unknown"
306             else
307             {
308 0           $self->{_returnType} = "unknown";
309             }
310             }
311 0           return $serviceobject->$method(@$a);
312             }
313             }
314              
315             sub strrpos
316             {
317 0     0 0   my ($string)=@_;
318 0           my $reversed = reverse $string;
319 0           my $firstDotIndex = index($reversed, ".");
320 0           return length($string)-$firstDotIndex-1;
321             }
322              
323             1;