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

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

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