File Coverage

blib/lib/Siebel/Srvrmgr/Log/Enterprise.pm
Criterion Covered Total %
statement 69 76 90.7
branch 8 18 44.4
condition 1 3 33.3
subroutine 13 13 100.0
pod 2 2 100.0
total 93 112 83.0


line stmt bran cond sub pod time code
1             package Siebel::Srvrmgr::Log::Enterprise;
2              
3 2     2   193885 use Moose;
  2         329649  
  2         15  
4 2     2   14548 use namespace::autoclean;
  2         8163  
  2         12  
5 2     2   1845 use File::Copy;
  2         4880  
  2         126  
6 2     2   12 use File::Temp qw(tempfile);
  2         3  
  2         143  
7 2     2   11 use Carp qw(cluck confess);
  2         4  
  2         115  
8 2     2   2772 use String::BOM qw(strip_bom_from_string);
  2         36  
  2         11  
9              
10             =pod
11              
12             =head1 NAME
13              
14             Siebel::Srvrmgr::Log::Enterprise - module to read a Siebel Enterprise log file
15              
16             =head1 SYNOPSIS
17              
18             use Siebel::Srvrmgr::Log::Enterprise;
19             my $enterprise_log = Siebel::Srvrmgr::Log::Enterprise->new( { path => File::Spec->catfile('somewhere', 'under', 'the', 'rainbow')} );
20             my $next = $enterprise_log->read();
21              
22             while (my $line = $next->()) {
23              
24             # do something
25              
26             }
27              
28              
29             =head1 DESCRIPTION
30              
31             A class that knows how to read Siebel Enterprise log files: it knows the header details and how to safely read lines from the file.
32              
33             =head1 ATTRIBUTES
34              
35             =head2 path
36              
37             A string with the complete pathname to the Siebel Enterprise log file.
38              
39             This attribute is required during object creation.
40              
41             =cut
42              
43             has path => ( is => 'ro', isa => 'Str', reader => 'get_path', required => 1 );
44              
45             =head2 eol
46              
47             A string identifying the character(s) used as end-of-line in the Siebel Enterprise log file is configured.
48              
49             This attribute is read-only, this class will automatically try to define the field separator being used.
50              
51             =cut
52              
53             has eol => (
54             is => 'ro',
55             isa => 'Str',
56             reader => 'get_eol',
57             writer => '_set_eol',
58             default => 0
59             );
60              
61             =head2 fs
62              
63             A string identifying the character(s) used to separate the fields ("fs" stands for "field separator") in the Siebel Enterprise log file is configured.
64              
65             This attribute is read-only, this class will automatically try to define the EOL being used.
66              
67             =cut
68              
69             has fs => (
70             is => 'ro',
71             isa => 'Str',
72             reader => 'get_fs',
73             writer => '_set_fs',
74             default => 0
75             );
76              
77             =head2 fh
78              
79             The file handle reference to the Siebel Enterprise log file, after was opened.
80              
81             =cut
82              
83             has fh =>
84             ( is => 'ro', isa => 'FileHandle', reader => 'get_fh', writer => '_set_fh' );
85              
86             =head2 filename
87              
88             The complete path to the temporary filename that this class uses to store the lines of the Siebel Enterprise Log file.
89              
90             =cut
91              
92             has filename => (
93             is => 'ro',
94             isa => 'Str',
95             reader => 'get_filename',
96             writer => '_set_filename'
97             );
98              
99             =head2 header
100              
101             The header of the Siebel Enterprise log file, without the BOM.
102              
103             =cut
104              
105             has header => (
106             is => 'ro',
107             isa => 'Str',
108             reader => 'get_header',
109             writer => '_set_header',
110             trigger => \&_check_header
111             );
112              
113             =head1 SEE ALSO
114              
115             =over
116              
117             =item *
118              
119             L<Moose>
120              
121             =item *
122              
123             L<Siebel::Srvrmgr::OS::Unix>
124              
125             =back
126              
127             =head1 METHODS
128              
129             =head2 read
130              
131             Reads the Siebel Enterprise log file, returning a iterator over the lines of the file.
132              
133             The method will try to read the file as safely as possible, copying it to a temporary location before reading.
134              
135             Several attributes will be defined during the file reading, automatically whenever it is possible. In some cases, if unable to
136             define those attributes, an exception will be raised.
137              
138             =cut
139              
140             sub read {
141              
142 2     2 1 2342 my $self = shift;
143 2         5 my $template = __PACKAGE__ . '_XXXXXX';
144 2         22 $template =~ s/\:{2}/_/g;
145              
146             # :TODO:09/18/2015 09:14:14 PM:: insecure, must check if it not possible to keep the file handle, copy the file
147             # over and use seek to go back to the beginning of the file
148 2         34 my ( $fh, $filename ) = tempfile($template);
149 2         1180 close($fh);
150 2         935 copy( $self->get_path(), $filename );
151              
152 2 50   2   27 open( $fh, '<:encoding(utf8)', $filename )
  2         4  
  2         23  
  2         889  
153             or die "Cannot read $filename: $!";
154 2         28973 $self->_set_filename($filename);
155 2         50 my $header = <$fh>;
156              
157             # remove BOM, see https://rt.cpan.org/Public/Bug/Display.html?id=101175
158 2         93 $header = strip_bom_from_string($header);
159 2         171 $header =~ s/^\x{feff}//;
160              
161             # don't know which EOL is available
162 2         21 $header =~ tr/\012//d;
163 2         15 $header =~ tr/\015//d;
164              
165 2         100 $self->_set_fh($fh);
166              
167 2         107 $self->_set_header($header);
168 2         87 my $eol = $self->get_eol();
169              
170             return sub {
171              
172 51     51   881 local $/ = $eol;
173 51         370 return <$fh>;
174              
175             }
176              
177 2         36 }
178              
179             =head2 DEMOLISH
180              
181             During object termination, the associated temporary log file will be cloased and removed automatically, if available.
182              
183             =cut
184              
185             sub DEMOLISH {
186              
187 2     2 1 7 my $self = shift;
188              
189 2         88 my $fh = $self->get_fh();
190              
191 2 50       8 if ( defined($fh) ) {
192              
193 2         38 close($fh);
194              
195             }
196              
197 2         99 my $file = $self->get_filename();
198              
199 2 50 33     115 if ( ( defined($file) ) and ( -e $self->get_filename() ) ) {
200              
201 2 50       242 unlink $file or cluck "Could not remove $file: $!";
202              
203             }
204              
205             }
206              
207             sub _check_header {
208              
209 2     2   5 my $self = shift;
210 2         99 my @parts = split( /\s/, $self->get_header() );
211 2         12 $self->_define_eol( $parts[0] );
212 2         9 $self->_define_fs( $parts[9], $parts[10] );
213              
214             }
215              
216             sub _define_fs {
217              
218 2     2   4 my $self = shift;
219 2         6 my $field_del_length = shift;
220 2         4 my $field_delim = shift;
221 2         4 my $num;
222              
223 2         15 for my $i ( 1 .. 4 ) {
224              
225 4         11 my $temp = chop($field_del_length);
226 4 100       13 if ( $temp != 0 ) {
227              
228 2         5 $num .= $temp;
229              
230             }
231             else {
232              
233 2         5 last;
234              
235             }
236              
237             }
238              
239 2 50       14 confess "field delimiter unimplemented" if ( $num > 1 );
240              
241             # converting hex number to the corresponding character as defined in ASCII table
242 2         125 $self->_set_fs( chr( unpack( 's', pack 's', hex($field_delim) ) ) );
243              
244             }
245              
246             sub _define_eol {
247              
248 2     2   4 my $self = shift;
249 2         5 my $part = shift;
250 2         11 my $eol = substr $part, 0, 1;
251              
252             CASE: {
253              
254 2 50       4 if ( $eol eq '2' ) {
  2         8  
255              
256 2         104 $self->_set_eol("\015\012");
257 2         7 last CASE;
258              
259             }
260              
261 0 0         if ( $eol eq '1' ) {
262              
263 0           $self->_set_eol("\012");
264 0           last CASE;
265              
266             }
267              
268 0 0         if ( $eol eq '0' ) {
269              
270 0           $self->_set_eol("\015");
271 0           last CASE;
272              
273             }
274             else {
275              
276 0           confess "EOL is custom, don't know what to use!";
277              
278             }
279              
280             }
281              
282             }
283              
284             =head1 AUTHOR
285              
286             Alceu Rodrigues de Freitas Junior, E<lt>arfreitas@cpan.orgE<gt>
287              
288             =head1 COPYRIGHT AND LICENSE
289              
290             This software is copyright (c) 2015 of Alceu Rodrigues de Freitas Junior, E<lt>arfreitas@cpan.orgE<gt>
291              
292             This file is part of Siebel Monitoring Tools.
293              
294             Siebel Monitoring Tools is free software: you can redistribute it and/or modify
295             it under the terms of the GNU General Public License as published by
296             the Free Software Foundation, either version 3 of the License, or
297             (at your option) any later version.
298              
299             Siebel Monitoring Tools is distributed in the hope that it will be useful,
300             but WITHOUT ANY WARRANTY; without even the implied warranty of
301             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
302             GNU General Public License for more details.
303              
304             You should have received a copy of the GNU General Public License
305             along with Siebel Monitoring Tools. If not, see <http://www.gnu.org/licenses/>.
306              
307             =cut
308              
309             __PACKAGE__->meta->make_immutable;