File Coverage

blib/lib/IO/Capture.pm
Criterion Covered Total %
statement 65 77 84.4
branch 20 26 76.9
condition 2 2 100.0
subroutine 14 14 100.0
pod 4 5 80.0
total 105 124 84.6


line stmt bran cond sub pod time code
1             package IO::Capture;
2              
3             $VERSION = 0.05;
4 16     16   114613 use strict;
  16         33  
  16         6914  
5 16     16   82 use Carp;
  16         29  
  16         14809  
6              
7             =head1 NAME
8              
9             C - Abstract Base Class to build modules to capture output.
10              
11             =head1 DESCRIPTION
12              
13             The C Module defines an abstract base class that can be
14             used to build modules that capture output being sent on a filehandle
15             such as STDOUT or STDERR.
16              
17             Several modules that come with the distribution do just that.
18             I.e., Capture STDOUT and STDERR. Also see James Keenan's
19             C on CPAN.
20              
21             See L for a
22             discussion of these modules and examples of how to build a module to
23             sub-class from C yourself. If after reading the overview,
24             you would like to build a class from C, look here for
25             details on the internals.
26              
27             =head1 METHODS
28              
29             These are the methods defined in the C Module. This page
30             will be discussing the module from the point of view of someone who wants
31             to build a sub-class of C.
32              
33             Each method defined in the C Module defines a public method,
34             that then calls one or more private methods. I<(Names starting with an
35             underscore)> This allows you to override methods at a finer level of
36             granularity, re-using as much of the functionality provided in the module
37             as possible.
38              
39             Of these internal methods, three are abstract methods that your will
40             B override if you want your module to B anything. The
41             three are C<_start()>, C<_retrieve_captured_text()>. and C<_stop()>.
42              
43             Below are the public methods with the private methods that each uses
44             immediately following.
45              
46             =head2 new
47              
48             The C method creates a new C object, and returns it
49             to its caller. The object is implemented with a hash. Each key used by
50             C is named with the class name. I.e., 'IO::Capture::'.
51             This is to prevent name clashes with keys added by sub-class authors.
52             Attributes can be set in the object by passing a hash reference as a single
53             argument to new().
54              
55             my $capture = IO::Capture->new( { Key => 'value' } );
56              
57             All elements from this hash will be added to the object, and will be
58             available for use by children of IO::Capture.
59              
60             my $key = $self->{'Key'};
61              
62             The internal methods used are:
63              
64             =over 4
65              
66             =item C<_initialize()>
67              
68             C<_initialize> is called as soon as the empty object has been blessed.
69             It adds the structure to the object that it will need. The C
70             module adds the following
71              
72             IO::Capture::messages => []
73             IO::Capture::line_pointer => 1
74             IO::Capture::status => 'Ready', # Busy when capturing
75              
76             =back
77              
78             =head2 start
79              
80             The C method is responsible for saving the current state of the
81             filehandle and or signal hander, and starting the data capture.
82              
83             Start cannot be called if there is already a capture in progress. The
84             C must be called first.
85              
86             These internal methods are called in this order.
87              
88             =over 4
89              
90             =item C<_check_pre_conditions>
91              
92             C<_check_pre_conditions> is used to make sure all the preconditions
93             are met before starting a capture. The only precondition checked in
94             C, is to insure the "Ready" flag is "on". I.e., There is
95             not already a capture in progress.
96              
97             If your module needs to make some checks, and you override this method, make
98             sure you call the parent class C<_check_pre_conditions> and check the results.
99              
100             sub _check_pre_conditions {
101             my $self = shift;
102              
103             return unless $self->SUPER::_check_pre_conditions;
104              
105             An example of something you might want to check would be,
106             to make sure STDERR is not already I if you are going to be
107             using C on it.
108              
109             B return a boolean true for success, or false for failure.
110             If a failure is indicated, an C will be returned to the
111             calling function, and an remaining private methods for C will
112             B be run.
113              
114             =item C<_save_current_configuration()>
115              
116             C<_save_current_configuration> in C will save the state of
117             C, C, and $SIG{__WARN__}. They are saved in the hash
118             keys 'IO::Capture::stderr_save', 'IO::Capture::stdout_save', and
119             'IO::Capture::handler_save'.
120              
121             # Save WARN handler
122             $self->{'IO::Capture::handler_save'} = $SIG{__WARN__};
123             # Dup stdout
124             open STDOUT_SAVE, ">&STDOUT";
125             # Save ref to dup
126             $self->{'IO::Capture::stdout_save'} = *STDOUT_SAVE;
127             # Dup stderr
128             open STDERR_SAVE, ">&STDOUT";
129             # Save ref to dup
130             $self->{'IO::Capture::stderr_save'} = *STDERR_SAVE;
131              
132              
133             These saved values can be used in the C<_stop> method to restore the
134             original value to any you changed.
135            
136             $SIG{__WARN__} = $self->{'IO::Capture::handler_save'};
137             STDOUT = $self->{'IO::Capture::stdout_save'};
138             STDERR = $self->{'IO::Capture::stderr_save'};
139              
140             B return a boolean true for success, or false for failure.
141             If a failure is indicated, an C will be returned to the
142             calling function.
143              
144             =item C<_start>
145              
146             B This is only an abstract method in C.
147             It will print a warning if called. Which should not happen, as the
148             author of the sub-class will always be sure to override it with her/his
149             own. :-)
150              
151             This is the first of the three you need to define. You will likely
152             use tie here. The included module C (see
153             L or other module of your own or from CPAN.
154             You will read it from the tied module and put it into the object
155             in C<_retrieve_captured_text>. See L<_retrieve_captured_text>
156              
157             B return a boolean true for success, or false for failure.
158             If a failure is indicated, an C will be returned to the
159             calling function.
160              
161             =back
162              
163             =head2 stop
164              
165             Stop capturing and return any filehandles and interrupt handlers that were
166             changed, to their pre-start state. This B be called B calling
167             C. If you are looking for a way to interact with the process on
168             the other side of the filehandle, take a look at the L<"Other Modules on CPAN">.
169              
170             B return a boolean true for success, or false for failure.
171             If a failure is indicated, an C will be returned to the
172             calling function.
173              
174             =over 4
175              
176             =item C<_retrieve_captured_text()>
177              
178             Copy any text captured into the object here. For example, The modules in this
179             package tie the filehandle to the (included) C to collect
180             the text. The data needs to be read out of the tied object before the filehandle
181             is untied, so that is done here. In short, if you need to do any work before
182             C<_stop> is called, do it here. The C<_retrieve_capture_text> in this base
183             class just returns true without doing anything.
184              
185             B return a boolean true for success, or false for failure. If a failure
186             is indicated, an C will be returned to the calling function. The C<_stop>
187             internal method will be called first.
188              
189             =item C<_stop>
190              
191             Do what needs to be done to put things back. Such as untie filehandles and
192             put interrupt handlers back to what they were. The default C<_stop> method
193             defined in won't do anything, so you should.
194              
195             B return a boolean true for success, or false for failure. If a failure
196             is indicated, an C will be returned to the calling function.
197              
198             =back
199              
200             =head2 read
201              
202             The C method is responsible for returning the data captured in the
203             object. These internal methods will be run, in this order.
204              
205             =over 4
206              
207             =item C<_read()>
208              
209             The internal method used to return the captured text. If called in I
210             context>, an array will be returned. (Could be a lot if you captured a lot)
211             or called in I, the line pointed to by the I
212             will be returned and the I incremented.
213              
214             =back
215              
216             =head1 Other Modules on CPAN
217              
218             If this module is not exactly what you were looking for, take a look at these.
219             Maybe one of them will fit the bill.
220              
221             =over 4
222              
223             =item *
224              
225             IO::Filter - Generic input/output filters for Perl IO handles
226              
227             =item *
228              
229             Expect - Expect for Perl
230              
231             =item *
232              
233             Tie::Syslog - Tie a filehandle to Syslog. If you Tie STDERR, then all
234             STDERR errors are automatically caught, or you can debug by Carp'ing to
235             STDERR, etc. (Good for CGI error logging.)
236              
237             =item *
238              
239             FileHandle::Rollback - FileHandle with commit and rollback
240              
241             =back
242              
243             =head1 See Also
244              
245             L
246              
247             L
248              
249             L
250              
251             =head1 AUTHORS
252              
253             Mark Reynolds
254             reynoldssgi.com
255              
256             Jon Morgan
257             jmorgansgi.com
258              
259             =head1 MAINTAINED
260              
261             Maintained by Mark Reynolds. reynoldssgi.com
262              
263             =head1 COPYRIGHT
264              
265             Copyright (c) 2003 Mark Reynolds and Jon Morgan
266             Copyright (c) 2004-2005 Mark Reynolds
267             All Rights Reserved. This module is free software. It may be used, redistributed
268             and/or modified under the same terms as Perl itself.
269              
270             =cut
271              
272              
273             sub new {
274 22     22 1 1125 my $class = shift;
275 22 50       192 if (ref $class) {
276 0         0 carp "WARNING: " . __PACKAGE__ . "::new cannot be called from existing object. (cloned)";
277 0         0 return;
278             }
279 22   100     161 my $object = shift || {};
280 22         60 bless $object, $class;
281 22         125 $object->_initialize;
282             }
283              
284             sub _check_pre_conditions {
285 28     28   50 my $self = shift;
286              
287 28 100       112 if( $self->{'IO::Capture::status'} ne "Ready") {
288 3         482 carp "Start issued on an in progress capture ". ref($self);
289 3         87 return;
290             }
291              
292 25         98 return 1;
293             }
294              
295             sub _initialize {
296 22     22   40 my $self = shift;
297 22 50       100 if (!ref $self) {
298 0         0 carp "WARNING: _initialize was called, but not called from a valid object";
299 0         0 return;
300             }
301              
302 22         138 $self->{'IO::Capture::messages'} = [];
303 22         58 $self->{'IO::Capture::line_pointer'} = 1;
304 22         50 $self->{'IO::Capture::status'} = "Ready";
305 22         118 return $self;
306             }
307              
308             sub start {
309 28     28 1 4766 my $self = shift;
310              
311 28 100       131 if (! $self->_check_pre_conditions) {
312 5         443 carp "Error: failed _check_pre_confitions in ". ref($self);
313 5         95 return;
314             }
315              
316 23 50       124 if (! $self->_save_current_configuration ) {
317 0         0 carp "Error saving configuration in " . ref($self);
318 0         0 return;
319             }
320              
321 23         55 $self->{'IO::Capture::status'} = "Busy";
322              
323 23 50       97 if (! $self->_start(@_)) {
324 0         0 carp "Error starting capture in " . ref($self);
325 0         0 return;
326             }
327 23         92 return 1;
328             }
329              
330             sub stop {
331 26     26 1 1386 my $self = shift;
332              
333 26 100       132 if( $self->{'IO::Capture::status'} ne "Busy") {
334 4         484 carp "Stop issued on an unstarted capture ". ref($self);
335 4         97 return;
336             }
337              
338 22 50       90 if (! $self->_retrieve_captured_text() ) {
339 0         0 carp "Error retreaving captured text in " . ref($self);
340 0         0 return;
341             }
342              
343 22 50       84 if (!$self->_stop() ) {
344 0         0 carp "Error return from _stop() " . ref($self) . "\n";
345 0         0 return;
346             }
347              
348 22         53 $self->{'IO::Capture::status'} = "Ready";
349              
350 22         57 return 1;
351             }
352              
353             sub read {
354 32     32 1 9468 my $self = shift;
355              
356 32         114 $self->_read;
357             }
358              
359             #
360             # Internal start routine. This needs to be overriden with instance
361             # method
362             #
363             sub _start {
364 5     5   10 my $self = shift;
365 5         19 return 1;
366             }
367              
368             sub _read {
369 32     32   44 my $self = shift;
370 32         39 my $messages = \@{$self->{'IO::Capture::messages'}};
  32         521  
371 32         65 my $line_pointer = \$self->{'IO::Capture::line_pointer'};
372              
373 32 100       105 if ($self->{'IO::Capture::status'} ne "Ready") {
374 2         169 carp "Read cannot be done while capture is in progress". ref($self);
375 2         31 return;
376             }
377              
378 30 100       96 return if $$line_pointer > @$messages;
379 24 100       116 return wantarray ? @$messages : $messages->[($$line_pointer++)-1];
380             }
381              
382             sub _retrieve_captured_text {
383 5     5   18 return 1;
384            
385             }
386              
387             sub _save_current_configuration {
388 23     23   47 my $self = shift;
389 23         74 $self->{'IO::Capture::handler_save'} = $SIG{__WARN__};
390 23         382 open STDOUT_SAVE, ">&STDOUT";
391 23         103 $self->{'IO::Capture::stdout_save'} = *STDOUT_SAVE;
392 23         267 open STDERR_SAVE, ">&STDOUT";
393 23         68 $self->{'IO::Capture::stderr_save'} = *STDERR_SAVE;
394 23         88 return $self;
395             }
396              
397             sub _stop {
398 5     5   10 my $self = shift;
399 5         17 return 1;
400             }
401              
402             sub line_pointer {
403 29     29 0 2565 my $self = shift;
404 29         72 my $new_number = shift;
405              
406 29 100       112 $self->{'IO::Capture::line_pointer'} = $new_number if $new_number;
407 29         75 return $self->{'IO::Capture::line_pointer'};
408             }
409             1;