/[cvs]/nfo/perl/libs/Data/Rap/Engine.pm
ViewVC logotype

Diff of /nfo/perl/libs/Data/Rap/Engine.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by joko, Tue Feb 18 15:35:25 2003 UTC revision 1.8 by joko, Sat Mar 29 07:11:54 2003 UTC
# Line 2  Line 2 
2  ##  $Id$  ##  $Id$
3  ## ----------------------------------------------------------------------  ## ----------------------------------------------------------------------
4  ##  $Log$  ##  $Log$
5    ##  Revision 1.8  2003/03/29 07:11:54  joko
6    ##  modified: sub run_executable
7    ##  new: sub run_script
8    ##
9    ##  Revision 1.7  2003/03/28 07:02:56  joko
10    ##  modified structure around '$wrapper_program'
11    ##
12    ##  Revision 1.6  2003/03/27 15:31:05  joko
13    ##  fixes to modules regarding new namespace(s) below Data::Mungle::*
14    ##
15    ##  Revision 1.5  2003/03/27 15:03:03  joko
16    ##  enhanced 'sub run_executable'
17    ##
18    ##  Revision 1.4  2003/02/22 16:51:21  joko
19    ##  + enhanced run_executable
20    ##  modified logging output
21    ##
22    ##  Revision 1.3  2003/02/21 01:46:17  joko
23    ##  renamed core function
24    ##
25    ##  Revision 1.2  2003/02/20 19:46:33  joko
26    ##  renamed and revamped some of modules
27    ##  renamed methods
28    ##  + sub run_executable
29    ##
30  ##  Revision 1.1  2003/02/18 15:35:25  joko  ##  Revision 1.1  2003/02/18 15:35:25  joko
31  ##  + initial commit  ##  + initial commit
32  ##  ##
# Line 15  use warnings; Line 40  use warnings;
40    
41    
42  use Data::Dumper;  use Data::Dumper;
 use Data::Transform::Deep qw( refexpr2perlref );  
 use Iterate;  
43  use Hash::Merge qw( merge );  use Hash::Merge qw( merge );
44    use Iterate;
45    
46    use shortcuts qw( run_cmd );
47    use Data::Mungle::Code::Ref qw( ref_slot );
48    use Data::Mungle::Transform::Deep qw( expand deep_copy );
49    use File::Temp qw/ tempfile tempdir /;
50    
51    
52  sub performTarget {  sub performTarget {
53    my $self = shift;    my $self = shift;
54    my $targetname = shift;    my $targetname = shift;
55    my $target = $self->getTargetMetadata($targetname);    $self->perform_target($targetname);
56    }
57    
58    sub perform_target {
59      my $self = shift;
60      my $targetname = shift;
61    
62      my $header = ("- " x 12) . "   " . $targetname . "   " . ("- " x 6);
63      
64      # V1
65      #$self->log("- " x 35, 'notice');
66      #$self->log("Performing Target '$targetname'.", 'notice');
67    
68      # V2
69      #$self->log($header, 'notice');
70    
71      # V3
72      $self->log("- " x 35, 'info');
73      $self->log("Performing Target '$targetname'.", 'notice');
74    
75      #exit;
76    
77      my $target = $self->getTargetDetails($targetname);
78    
79    # trace    # trace
80      #print Dumper($target);      #print Dumper($target);
81      #exit;      #exit;
82            
83      $self->perform_dependencies($target);
84      $self->perform_details($target);
85    
86    }
87    
88    sub perform_dependencies {
89      my $self = shift;
90      my $target = shift;
91    # resolve dependencies (just run prior)    # resolve dependencies (just run prior)
92    if (my $targetname_dep = $target->{attrib}->{depends}) {    if (my $targetname_dep = $target->{attrib}->{depends}) {
93      $self->performTarget($targetname_dep);      my @targets = split(/,\s|,/, $targetname_dep);
94        #print Dumper(@targets);
95        #$self->perform($targetname_dep);
96        #delete $target->{attrib}->{depends};
97        foreach (@targets) {
98          if (!$self->{__rap}->{dependencies}->{resolved}->{$_}++) {
99            $self->perform_target($_);
100          }
101        }
102      delete $target->{attrib}->{depends};      delete $target->{attrib}->{depends};
103    }    }
104    }
105    
106    sub perform_details {
107      my $self = shift;
108      my $target = shift;
109      
110      #print Dumper($target);
111      #exit;
112      
113    foreach my $entry (@{$target->{content}}) {    foreach my $entry (@{$target->{content}}) {
114      my $command = $entry->{name};      my $command = $entry->{name};
115      my $args = $entry->{attrib};      my $args = $entry->{attrib};
116      $self->run_command($command, $args);      my $content = $entry->{content};
117        $self->perform_command($command, $args, $content);
118        # check recursiveness
119        if ($entry->{content} && ref $entry->{content}) {
120          $self->perform_details($entry);
121        }
122    }    }
123  }  }
124    
125  sub rc {  sub rc {
126    my $self = shift;    my $self = shift;
127    return $self->run_command(@_);    return $self->perform_command(@_);
128  }  }
129    
130  sub run_command {  sub perform_command {
131    my $self = shift;    my $self = shift;
132    my $command = shift;    my $command = shift;
133        my $args_list = shift;
134      my $content = shift;
135    
136    if (!$command) {    if (!$command) {
137      $self->log("Command was empty!", 'warning');      $self->log("Command was empty!", 'debug');
138      return;      return;
139    }    }
140    
141      # FIXME: make '__PACKAGE__' go one level deeper properly!
142      $self->log( __PACKAGE__ . "->perform_command: " . $command, 'debug');
143        
   my $args_list = shift;  
144    my $args = {};    my $args = {};
145    #print Dumper($args_list);    #print Dumper($args_list);
146    if ($args_list) {    if ($args_list) {
# Line 69  sub run_command { Line 153  sub run_command {
153      }      }
154    }    }
155    $command = '_' . $command;    $command = '_' . $command;
156    if ($self->can($command)) {    
157      $self->$command($args);    
158      # determine container
159      my $container; # = $self->getInstance();
160      $container ||= $self;
161      
162      if ($container->can($command)) {
163        $container->$command($args, $content);
164    } else {    } else {
165      $self->log("Command \"$command\" not implemented.", "warning");      $self->log("Command '$command' not implemented.", "warning");
166    }    }
167      
168  }  }
169    
 sub set_property {  
   my $self = shift;  
   my $args = shift;  
170    
171    my $name;  sub merge_properties {
172    my $value;    my $self = shift;
173        my $name = shift;
174    if (ref $args) {    my $data = shift;
     $self->interpolate($args) ;  
     $name = $args->{name};  
     $value = $args->{value};  
175    
176    } else {    $self->log("merge-name: $name");
177      $name = $args;    #print "name: $name", "\n";
178      $value = shift;    #print Dumper($data);
179    }    #exit;
180    
181    # check if slot (or childs of it) is/are already occupied    # check if slot (or childs of it) is/are already occupied
182    if (my $oldvalue = refexpr2perlref($self, $name, undef, '.')) {    #if (my $data_old = ref_slot($self, $name, undef, '.')) {
183      if (my $data_old = $self->get_property($name)) {
184        #print "old:", "\n";
185        #print Dumper($data_old);
186        
187      # FIXME: review - any options for 'merge' here?      # FIXME: review - any options for 'merge' here?
188      $value = merge($oldvalue, $value);      my $data_new = merge($data_old, $data);
189        #print "DATA NEE! - MERGE!", "\n";
190        #print Dumper($data_new);
191        #exit;
192        #merge_to($self, $data_new);
193        $self->set_property( { name => $name, value => $data_new } );
194        
195      } else {
196    
197    =pod    
198        # make up a dummy hash matching the structure of the destination one
199          my $dummy = {};
200          ref_slot($dummy, $name, $data, '.');
201          print Dumper($dummy);
202        
203        # mix into destination
204          mixin($self, $dummy, { init => 1 });
205    =cut
206    
207          ref_slot($self, $name, $data, '.');
208    
209    }    }
210      
211      
212      #print Dumper($self);
213      #exit;
214      #$self->
215    
216    }
217    
218    sub set_property {
219      my $self = shift;
220      my $args = shift;
221    
222      $self->interpolate($args) ;
223      my $name = $args->{name};
224      my $value = $args->{value};
225      $name = '__rap.properties.' . $name;
226    
227      $self->log("set-name: $name");
228    
229    # fill property slot with given value    # fill property slot with given value
230    if ($value) {    if ($value) {
231      refexpr2perlref($self, $name, $value, '.');      ref_slot($self, $name, $value, '.');
232    }    }
233        
234      #print Dumper($self);
235      
236    # FIXME!!!    # FIXME!!!
237    return if ! ref $args;    #return if ! ref $args;
238    
239    # fill property slot with (probably bigger) data structure from property-/configuration-style - file    # fill property slot with (probably bigger) data structure from property-/configuration-style - file
240    if (my $file = $args->{file}) {    if (my $file = $args->{file}) {
# Line 123  sub set_property { Line 252  sub set_property {
252      }      }
253    
254    } elsif (my $command = $args->{command}) {    } elsif (my $command = $args->{command}) {
255      $self->run_command($command, $args);      $self->perform_command($command, $args);
256        
257    }    }
258    
# Line 137  sub get_property { Line 266  sub get_property {
266    #$self->interpolate($args);    #$self->interpolate($args);
267    
268    #my $name = $args->{name};    #my $name = $args->{name};
269      my $result;
270    
271      if (!$name) {
272        $self->log( __PACKAGE__ . ": no name!", 'critical');
273        
274      } elsif ($name eq '/') {
275        $result = expand($self);
276    
277      } elsif ($name eq '.') {
278        if (my $instance = $self->getInstance()) {
279          $result = expand($instance);
280        } else {
281          $result = ref_slot($self, '__rap.properties', undef, '.');
282          
283        }
284    
285      } else {
286    
287    # get property slot and return value      $name = '__rap.properties.' . $name;
288    return refexpr2perlref($self, $name, undef, '.');      
289        $self->log("get-name: $name");
290        
291        # get property slot and return value
292        $result = ref_slot($self, $name, undef, '.');
293        
294        # FIXME: Is this okay? It's provided for now in order not
295        # to deliver an 'undef' to the regex below inside 'interpolate'.
296        # revamp this, maybe!
297        #$result ||= '';    # NO!!!
298      }
299        
300      return $result;
301  }  }
302    
303  sub interpolate {  sub interpolate {
# Line 152  sub interpolate { Line 309  sub interpolate {
309    }    }
310  }  }
311    
312    sub run_executable {
313      my $self = shift;
314      my $opts = shift;
315    
316      my $meta = deep_copy($opts);
317    
318      delete $opts->{caption};
319      delete $opts->{async};
320    
321      #print Dumper($meta);
322    
323      if ($opts->{executable}) {
324    
325        my $program = $opts->{executable};
326        delete $opts->{executable};
327    
328        # determine execution method
329        my $wrapper_program = '';
330        
331        # check if program is a namespace-string (contains '::') - use 'do' in this case!
332        if ($program =~ /::/) {
333          #$wrapper_program = 'rap.pl';
334          $wrapper_program = $0;
335        }
336    
337        # prepare arguments
338        my @buf;
339        foreach (keys %$opts) {
340          my $value = $opts->{$_};
341          if (m/^_/) {
342            if ($_ eq '_switches') {
343              my @switches = split(/,\s|,/, $value);
344              foreach my $switch (@switches) {
345                push @buf, '--' . $switch;
346              }
347            }
348            next;
349          }
350          
351          if ($value =~ /\s/) {
352            $value = "\"$value\"";
353          }
354          push @buf, "--$_=$value";
355        }
356    
357        # build {program} & {arguments}  
358        my $cmd = ($wrapper_program ? $wrapper_program . ' ' : '') . $program . ' ' . join(' ', @buf);
359        
360        # trace
361          #print "command: $cmd", "\n";
362        
363        # start process
364          # V1: via shortcut
365          #$ENV{PERL5LIB} = join(' ', @INC);
366          
367          # FIXME!!! what about the other slots of @INC?
368          $ENV{PERL5LIB} = $INC[0];
369          
370          #print Dumper(%ENV);
371          
372          #print "command: '$cmd'", "\n";
373    
374          # V1 - basic
375          #run_cmd($cmd);
376    
377          # V1.b - enhanced: variable local method
378          $meta->{caption} ||= '';
379          $meta->{async} ||= 0;
380          my $evalstr = "run_cmd('$cmd', '$meta->{caption}', { async => $meta->{async} });";
381          eval($evalstr);
382          #my $res = do "$cmd";
383          #print $res, "\n" if $res;
384    
385          #$self->log("run_executable: $evalstr", 'info');
386          $self->raiseException("run_executable: $evalstr\n$@") if $@;
387    
388          # V2: via IPC::Run
389          # ....  (TODO)
390          
391        
392      }
393      
394    }
395    
396    
397    sub run_script {
398    
399      my $self = shift;
400      my $args = shift;
401      my $code = shift;
402    
403      if ($args->{language} eq 'msdos/bat') {
404        
405        #print "code: $code", "\n";
406        
407        # reporting
408        $self->log("Executing some arbitrary unsigned code (probably unsafe). [language=$args->{language}]", 'info');
409        $self->log("\n<code>\n$code\n</code>", 'info');
410        
411        # create temporary intermediate file to execute code
412        my $tmpdir = '/tmp/rap';
413        mkdir $tmpdir;
414        (my $fh, my $filename) = tempfile( DIR => $tmpdir, SUFFIX => '.bat' );
415        print $fh $code, "\n";
416        run_cmd( $filename, '', { async => 1 } );
417        
418        # FIXME: DELETE code inside temp-files as soon as possible!
419        #print $fh '';
420        
421        # TODO: delete FILE completely!
422        # required for this: wait until execution has finished, then unlink....
423        # but: "how to wait until execution is finished"?
424        # i believe the best is to spawn *another* process directly from here,
425        # let's call it 'watcher-agent'.
426        # This one should monitor a certain running process and delete its
427        # executable file after it has finished execution.
428        # Possible extensions could be:
429        #   keep track of all stuff sent to STDOUT or STDERR and
430        #   send that stuff to the task-owner indirectly (not via shell/console)
431        #   (e.g. via email, by posting report to a newsgroup or publishing on a specified web-page: use mod-dav!)
432        
433      } elsif ($args->{language} eq 'bash') {
434        $self->log("FIXME: - - - - - -- - - --  BASH -  - -    -  - -   -    --   - ", 'error');
435        
436      } else {
437        $self->log("FIXME: Script language '$args->{language}' not implemented.", 'error');
438        
439      }
440    
441    }
442    
443  1;  1;
444  __END__  __END__

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.8

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed