Mercurial > repos > mahtabm > ensembl
comparison variant_effect_predictor/Bio/Root/IO.pm @ 0:1f6dce3d34e0
Uploaded
author | mahtabm |
---|---|
date | Thu, 11 Apr 2013 02:01:53 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1f6dce3d34e0 |
---|---|
1 # $Id: IO.pm,v 1.37.2.3 2003/06/28 21:57:04 jason Exp $ | |
2 # | |
3 # BioPerl module for Bio::Root::IO | |
4 # | |
5 # Cared for by Hilmar Lapp <hlapp@gmx.net> | |
6 # | |
7 # Copyright Hilmar Lapp | |
8 # | |
9 # You may distribute this module under the same terms as perl itself | |
10 | |
11 # POD documentation - main docs before the code | |
12 | |
13 =head1 NAME | |
14 | |
15 Bio::Root::IO - module providing several methods often needed when dealing with file IO | |
16 | |
17 =head1 SYNOPSIS | |
18 | |
19 # utilize stream I/O in your module | |
20 $self->{'io'} = Bio::Root::IO->new(-file => "myfile"); | |
21 $self->{'io'}->_print("some stuff"); | |
22 $line = $self->{'io'}->_readline(); | |
23 $self->{'io'}->_pushback($line); | |
24 $self->{'io'}->close(); | |
25 | |
26 # obtain platform-compatible filenames | |
27 $path = Bio::Root::IO->catfile($dir, $subdir, $filename); | |
28 # obtain a temporary file (created in $TEMPDIR) | |
29 ($handle) = $io->tempfile(); | |
30 | |
31 =head1 DESCRIPTION | |
32 | |
33 This module provides methods that will usually be needed for any sort | |
34 of file- or stream-related input/output, e.g., keeping track of a file | |
35 handle, transient printing and reading from the file handle, a close | |
36 method, automatically closing the handle on garbage collection, etc. | |
37 | |
38 To use this for your own code you will either want to inherit from | |
39 this module, or instantiate an object for every file or stream you are | |
40 dealing with. In the first case this module will most likely not be | |
41 the first class off which your class inherits; therefore you need to | |
42 call _initialize_io() with the named parameters in order to set file | |
43 handle, open file, etc automatically. | |
44 | |
45 Most methods start with an underscore, indicating they are private. In | |
46 OO speak, they are not private but protected, that is, use them in | |
47 your module code, but a client code of your module will usually not | |
48 want to call them (except those not starting with an underscore). | |
49 | |
50 In addition this module contains a couple of convenience methods for | |
51 cross-platform safe tempfile creation and similar tasks. There are | |
52 some CPAN modules related that may not be available on all | |
53 platforms. At present, File::Spec and File::Temp are attempted. This | |
54 module defines $PATHSEP, $TEMPDIR, and $ROOTDIR, which will always be set, | |
55 and $OPENFLAGS, which will be set if either of File::Spec or File::Temp fails. | |
56 | |
57 The -noclose boolean (accessed via the noclose method) prevents a | |
58 filehandle from being closed when the IO object is cleaned up. This | |
59 is special behavior when a object like a parser might share a | |
60 filehandle with an object like an indexer where it is not proper to | |
61 close the filehandle as it will continue to be reused until the end of the | |
62 stream is reached. In general you won't want to play with this flag. | |
63 | |
64 =head1 FEEDBACK | |
65 | |
66 =head2 Mailing Lists | |
67 | |
68 User feedback is an integral part of the evolution of this | |
69 and other Bioperl modules. Send your comments and suggestions preferably | |
70 to one of the Bioperl mailing lists. | |
71 Your participation is much appreciated. | |
72 | |
73 bioperl-l@bioperl.org - General discussion | |
74 http://bio.perl.org/MailList.html - About the mailing lists | |
75 | |
76 =head2 Reporting Bugs | |
77 | |
78 Report bugs to the Bioperl bug tracking system to help us keep track | |
79 the bugs and their resolution. | |
80 Bug reports can be submitted via email or the web: | |
81 | |
82 bioperl-bugs@bio.perl.org | |
83 http://bugzilla.bioperl.org/ | |
84 | |
85 =head1 AUTHOR - Hilmar Lapp | |
86 | |
87 Email hlapp@gmx.net | |
88 | |
89 Describe contact details here | |
90 | |
91 =head1 APPENDIX | |
92 | |
93 The rest of the documentation details each of the object methods. Internal methods are usually preceded with a _ | |
94 | |
95 =cut | |
96 | |
97 | |
98 # Let the code begin... | |
99 | |
100 | |
101 package Bio::Root::IO; | |
102 use vars qw(@ISA $FILESPECLOADED $FILETEMPLOADED $FILEPATHLOADED | |
103 $TEMPDIR $PATHSEP $ROOTDIR $OPENFLAGS $VERBOSE); | |
104 use strict; | |
105 | |
106 use Symbol; | |
107 use POSIX qw(dup); | |
108 use IO::Handle; | |
109 use Bio::Root::Root; | |
110 | |
111 @ISA = qw(Bio::Root::Root); | |
112 | |
113 my $TEMPCOUNTER; | |
114 my $HAS_WIN32 = 0; | |
115 | |
116 BEGIN { | |
117 $TEMPCOUNTER = 0; | |
118 $FILESPECLOADED = 0; | |
119 $FILETEMPLOADED = 0; | |
120 $FILEPATHLOADED = 0; | |
121 $VERBOSE = 1; | |
122 | |
123 # try to load those modules that may cause trouble on some systems | |
124 eval { | |
125 require File::Path; | |
126 $FILEPATHLOADED = 1; | |
127 }; | |
128 if( $@ ) { | |
129 print STDERR "Cannot load File::Path: $@" if( $VERBOSE > 0 ); | |
130 # do nothing | |
131 } | |
132 | |
133 | |
134 # If on Win32, attempt to find Win32 package | |
135 | |
136 if($^O =~ /mswin/i) { | |
137 eval { | |
138 require Win32; | |
139 $HAS_WIN32 = 1; | |
140 }; | |
141 } | |
142 | |
143 # Try to provide a path separator. Why doesn't File::Spec export this, | |
144 # or did I miss it? | |
145 if($^O =~ /mswin/i) { | |
146 $PATHSEP = "\\"; | |
147 } elsif($^O =~ /macos/i) { | |
148 $PATHSEP = ":"; | |
149 } else { # unix | |
150 $PATHSEP = "/"; | |
151 } | |
152 eval { | |
153 require File::Spec; | |
154 $FILESPECLOADED = 1; | |
155 $TEMPDIR = File::Spec->tmpdir(); | |
156 $ROOTDIR = File::Spec->rootdir(); | |
157 require File::Temp; # tempfile creation | |
158 $FILETEMPLOADED = 1; | |
159 }; | |
160 if( $@ ) { | |
161 if(! defined($TEMPDIR)) { # File::Spec failed | |
162 # determine tempdir | |
163 if (defined $ENV{'TEMPDIR'} && -d $ENV{'TEMPDIR'} ) { | |
164 $TEMPDIR = $ENV{'TEMPDIR'}; | |
165 } elsif( defined $ENV{'TMPDIR'} && -d $ENV{'TMPDIR'} ) { | |
166 $TEMPDIR = $ENV{'TMPDIR'}; | |
167 } | |
168 if($^O =~ /mswin/i) { | |
169 $TEMPDIR = 'C:\TEMP' unless $TEMPDIR; | |
170 $ROOTDIR = 'C:'; | |
171 } elsif($^O =~ /macos/i) { | |
172 $TEMPDIR = "" unless $TEMPDIR; # what is a reasonable default on Macs? | |
173 $ROOTDIR = ""; # what is reasonable?? | |
174 } else { # unix | |
175 $TEMPDIR = "/tmp" unless $TEMPDIR; | |
176 $ROOTDIR = "/"; | |
177 } | |
178 if (!( -d $TEMPDIR && -w $TEMPDIR )) { | |
179 $TEMPDIR = '.'; # last resort | |
180 } | |
181 } | |
182 # File::Temp failed (alone, or File::Spec already failed) | |
183 # | |
184 # determine open flags for tempfile creation -- we'll have to do this | |
185 # ourselves | |
186 use Fcntl; | |
187 use Symbol; | |
188 $OPENFLAGS = O_CREAT | O_EXCL | O_RDWR; | |
189 for my $oflag (qw/FOLLOW BINARY LARGEFILE EXLOCK NOINHERIT TEMPORARY/){ | |
190 my ($bit, $func) = (0, "Fcntl::O_" . $oflag); | |
191 no strict 'refs'; | |
192 $OPENFLAGS |= $bit if eval { $bit = &$func(); 1 }; | |
193 } | |
194 } | |
195 } | |
196 | |
197 =head2 new | |
198 | |
199 Title : new | |
200 Usage : | |
201 Function: Overridden here to automatically call _initialize_io(). | |
202 Example : | |
203 Returns : new instance of this class | |
204 Args : named parameters | |
205 | |
206 | |
207 =cut | |
208 | |
209 sub new { | |
210 my ($caller, @args) = @_; | |
211 my $self = $caller->SUPER::new(@args); | |
212 | |
213 $self->_initialize_io(@args); | |
214 return $self; | |
215 } | |
216 | |
217 =head2 _initialize_io | |
218 | |
219 Title : initialize_io | |
220 Usage : $self->_initialize_io(@params); | |
221 Function: Initializes filehandle and other properties from the parameters. | |
222 | |
223 Currently recognizes the following named parameters: | |
224 -file name of file to open | |
225 -input name of file, or GLOB, or IO::Handle object | |
226 -fh file handle (mutually exclusive with -file) | |
227 -flush boolean flag to autoflush after each write | |
228 -noclose boolean flag, when set to true will not close a | |
229 filehandle (must explictly call close($io->_fh) | |
230 Returns : TRUE | |
231 Args : named parameters | |
232 | |
233 | |
234 =cut | |
235 | |
236 sub _initialize_io { | |
237 my($self, @args) = @_; | |
238 | |
239 $self->_register_for_cleanup(\&_io_cleanup); | |
240 | |
241 my ($input, $noclose, $file, $fh, $flush) = $self->_rearrange([qw(INPUT | |
242 NOCLOSE | |
243 FILE FH | |
244 FLUSH)], @args); | |
245 | |
246 delete $self->{'_readbuffer'}; | |
247 delete $self->{'_filehandle'}; | |
248 $self->noclose( $noclose) if defined $noclose; | |
249 # determine whether the input is a file(name) or a stream | |
250 if($input) { | |
251 if(ref(\$input) eq "SCALAR") { | |
252 # we assume that a scalar is a filename | |
253 if($file && ($file ne $input)) { | |
254 $self->throw("input file given twice: $file and $input disagree"); | |
255 } | |
256 $file = $input; | |
257 } elsif(ref($input) && | |
258 ((ref($input) eq "GLOB") || $input->isa('IO::Handle'))) { | |
259 # input is a stream | |
260 $fh = $input; | |
261 } else { | |
262 # let's be strict for now | |
263 $self->throw("unable to determine type of input $input: ". | |
264 "not string and not GLOB"); | |
265 } | |
266 } | |
267 if(defined($file) && defined($fh)) { | |
268 $self->throw("Providing both a file and a filehandle for reading - only one please!"); | |
269 } | |
270 | |
271 if(defined($file) && ($file ne '')) { | |
272 $fh = Symbol::gensym(); | |
273 open ($fh,$file) || | |
274 $self->throw("Could not open $file: $!"); | |
275 $self->file($file); | |
276 } | |
277 $self->_fh($fh) if $fh; # if not provided, defaults to STDIN and STDOUT | |
278 | |
279 $self->_flush_on_write(defined $flush ? $flush : 1); | |
280 | |
281 return 1; | |
282 } | |
283 | |
284 =head2 _fh | |
285 | |
286 Title : _fh | |
287 Usage : $obj->_fh($newval) | |
288 Function: Get/set the file handle for the stream encapsulated. | |
289 Example : | |
290 Returns : value of _filehandle | |
291 Args : newvalue (optional) | |
292 | |
293 =cut | |
294 | |
295 sub _fh { | |
296 my ($obj, $value) = @_; | |
297 if ( defined $value) { | |
298 $obj->{'_filehandle'} = $value; | |
299 } | |
300 return $obj->{'_filehandle'}; | |
301 } | |
302 | |
303 =head2 mode | |
304 | |
305 Title : mode | |
306 Usage : $obj->mode() | |
307 Function: | |
308 Example : | |
309 Returns : mode of filehandle: | |
310 'r' for readable | |
311 'w' for writeable | |
312 '?' if mode could not be determined | |
313 Args : -force (optional), see notes. | |
314 Notes : once mode() has been called, the filehandle's mode is cached | |
315 for further calls to mode(). to override this behavior so | |
316 that mode() re-checks the filehandle's mode, call with arg | |
317 -force | |
318 | |
319 =cut | |
320 | |
321 sub mode { | |
322 my ($obj, @arg) = @_; | |
323 my %param = @arg; | |
324 return $obj->{'_mode'} if defined $obj->{'_mode'} and !$param{-force}; | |
325 | |
326 print STDERR "testing mode... " if $obj->verbose; | |
327 | |
328 # we need to dup() the original filehandle because | |
329 # doing fdopen() calls on an already open handle causes | |
330 # the handle to go stale. is this going to work for non-unix | |
331 # filehandles? -allen | |
332 | |
333 my $fh = Symbol::gensym(); | |
334 | |
335 my $iotest = new IO::Handle; | |
336 | |
337 #test for a readable filehandle; | |
338 $iotest->fdopen( dup(fileno($obj->_fh)) , 'r' ); | |
339 if($iotest->error == 0){ | |
340 | |
341 # note the hack here, we actually have to try to read the line | |
342 # and if we get something, pushback() it into the readbuffer. | |
343 # this is because solaris and windows xp (others?) don't set | |
344 # IO::Handle::error. for non-linux the r/w testing is done | |
345 # inside this read-test, instead of the write test below. ugh. | |
346 | |
347 if($^O eq 'linux'){ | |
348 $obj->{'_mode'} = 'r'; | |
349 my $line = $iotest->getline; | |
350 $obj->_pushback($line) if defined $line; | |
351 $obj->{'_mode'} = defined $line ? 'r' : 'w'; | |
352 return $obj->{'_mode'}; | |
353 } else { | |
354 my $line = $iotest->getline; | |
355 $obj->_pushback($line) if defined $line; | |
356 $obj->{'_mode'} = defined $line ? 'r' : 'w'; | |
357 return $obj->{'_mode'}; | |
358 } | |
359 } | |
360 $iotest->clearerr; | |
361 | |
362 #test for a writeable filehandle; | |
363 $iotest->fdopen( dup(fileno($obj->_fh)) , 'w' ); | |
364 if($iotest->error == 0){ | |
365 $obj->{'_mode'} = 'w'; | |
366 # return $obj->{'_mode'}; | |
367 } | |
368 | |
369 #wtf type of filehandle is this? | |
370 # $obj->{'_mode'} = '?'; | |
371 return $obj->{'_mode'}; | |
372 } | |
373 | |
374 =head2 file | |
375 | |
376 Title : file | |
377 Usage : $obj->file($newval) | |
378 Function: Get/set the filename, if one has been designated. | |
379 Example : | |
380 Returns : value of file | |
381 Args : newvalue (optional) | |
382 | |
383 | |
384 =cut | |
385 | |
386 sub file { | |
387 my ($obj, $value) = @_; | |
388 if ( defined $value) { | |
389 $obj->{'_file'} = $value; | |
390 } | |
391 return $obj->{'_file'}; | |
392 } | |
393 | |
394 =head2 _print | |
395 | |
396 Title : _print | |
397 Usage : $obj->_print(@lines) | |
398 Function: | |
399 Example : | |
400 Returns : writes output | |
401 | |
402 =cut | |
403 | |
404 sub _print { | |
405 my $self = shift; | |
406 my $fh = $self->_fh() || \*STDOUT; | |
407 print $fh @_; | |
408 } | |
409 | |
410 =head2 _readline | |
411 | |
412 Title : _readline | |
413 Usage : $obj->_readline(%args) | |
414 Function: Reads a line of input. | |
415 | |
416 Note that this method implicitely uses the value of $/ that is | |
417 in effect when called. | |
418 | |
419 Note also that the current implementation does not handle pushed | |
420 back input correctly unless the pushed back input ends with the | |
421 value of $/. | |
422 | |
423 Example : | |
424 Args : Accepts a hash of arguments, currently only -raw is recognized | |
425 passing (-raw => 1) prevents \r\n sequences from being changed | |
426 to \n. The default value of -raw is undef, allowing \r\n to be | |
427 converted to \n. | |
428 Returns : | |
429 | |
430 =cut | |
431 | |
432 sub _readline { | |
433 my $self = shift; | |
434 my %param =@_; | |
435 my $fh = $self->_fh || \*ARGV; | |
436 my $line; | |
437 | |
438 # if the buffer been filled by _pushback then return the buffer | |
439 # contents, rather than read from the filehandle | |
440 $line = shift @{$self->{'_readbuffer'}} || <$fh>; | |
441 | |
442 #don't strip line endings if -raw is specified | |
443 $line =~ s/\r\n/\n/g if( (!$param{-raw}) && (defined $line) ); | |
444 | |
445 return $line; | |
446 } | |
447 | |
448 =head2 _pushback | |
449 | |
450 Title : _pushback | |
451 Usage : $obj->_pushback($newvalue) | |
452 Function: puts a line previously read with _readline back into a buffer. | |
453 buffer can hold as many lines as system memory permits. | |
454 Example : | |
455 Returns : | |
456 Args : newvalue | |
457 | |
458 =cut | |
459 | |
460 sub _pushback { | |
461 my ($obj, $value) = @_; | |
462 | |
463 $obj->{'_readbuffer'} ||= []; | |
464 push @{$obj->{'_readbuffer'}}, $value; | |
465 } | |
466 | |
467 =head2 close | |
468 | |
469 Title : close | |
470 Usage : $io->close() | |
471 Function: Closes the file handle associated with this IO instance. | |
472 Will not close the FH if -noclose is specified | |
473 Returns : none | |
474 Args : none | |
475 | |
476 =cut | |
477 | |
478 sub close { | |
479 my ($self) = @_; | |
480 return if $self->noclose; # don't close if we explictly asked not to | |
481 if( defined $self->{'_filehandle'} ) { | |
482 $self->flush; | |
483 return if( \*STDOUT == $self->_fh || | |
484 \*STDERR == $self->_fh || | |
485 \*STDIN == $self->_fh | |
486 ); # don't close STDOUT fh | |
487 if( ! ref($self->{'_filehandle'}) || | |
488 ! $self->{'_filehandle'}->isa('IO::String') ) { | |
489 close($self->{'_filehandle'}); | |
490 } | |
491 } | |
492 $self->{'_filehandle'} = undef; | |
493 delete $self->{'_readbuffer'}; | |
494 } | |
495 | |
496 | |
497 =head2 flush | |
498 | |
499 Title : flush | |
500 Usage : $io->flush() | |
501 Function: Flushes the filehandle | |
502 Returns : none | |
503 Args : none | |
504 | |
505 =cut | |
506 | |
507 sub flush { | |
508 my ($self) = shift; | |
509 | |
510 if( !defined $self->{'_filehandle'} ) { | |
511 $self->throw("Attempting to call flush but no filehandle active"); | |
512 } | |
513 | |
514 if( ref($self->{'_filehandle'}) =~ /GLOB/ ) { | |
515 my $oldh = select($self->{'_filehandle'}); | |
516 $| = 1; | |
517 select($oldh); | |
518 } else { | |
519 $self->{'_filehandle'}->flush(); | |
520 } | |
521 } | |
522 | |
523 =head2 noclose | |
524 | |
525 Title : noclose | |
526 Usage : $obj->noclose($newval) | |
527 Function: Get/Set the NOCLOSE flag - setting this to true will | |
528 prevent a filehandle from being closed | |
529 when an object is cleaned up or explicitly closed | |
530 This is a bit of hack | |
531 Returns : value of noclose (a scalar) | |
532 Args : on set, new value (a scalar or undef, optional) | |
533 | |
534 | |
535 =cut | |
536 | |
537 sub noclose{ | |
538 my $self = shift; | |
539 | |
540 return $self->{'_noclose'} = shift if @_; | |
541 return $self->{'_noclose'}; | |
542 } | |
543 | |
544 sub _io_cleanup { | |
545 my ($self) = @_; | |
546 | |
547 $self->close(); | |
548 my $v = $self->verbose; | |
549 | |
550 # we are planning to cleanup temp files no matter what | |
551 if( exists($self->{'_rootio_tempfiles'}) && | |
552 ref($self->{'_rootio_tempfiles'}) =~ /array/i) { | |
553 if( $v > 0 ) { | |
554 print STDERR "going to remove files ", | |
555 join(",", @{$self->{'_rootio_tempfiles'}}), "\n"; | |
556 } | |
557 unlink (@{$self->{'_rootio_tempfiles'}} ); | |
558 } | |
559 # cleanup if we are not using File::Temp | |
560 if( $self->{'_cleanuptempdir'} && | |
561 exists($self->{'_rootio_tempdirs'}) && | |
562 ref($self->{'_rootio_tempdirs'}) =~ /array/i) { | |
563 | |
564 if( $v > 0 ) { | |
565 print STDERR "going to remove dirs ", | |
566 join(",", @{$self->{'_rootio_tempdirs'}}), "\n"; | |
567 } | |
568 $self->rmtree( $self->{'_rootio_tempdirs'}); | |
569 } | |
570 } | |
571 | |
572 =head2 exists_exe | |
573 | |
574 Title : exists_exe | |
575 Usage : $exists = $obj->exists_exe('clustalw'); | |
576 $exists = Bio::Root::IO->exists_exe('clustalw') | |
577 $exists = Bio::Root::IO::exists_exe('clustalw') | |
578 Function: Determines whether the given executable exists either as file | |
579 or within the path environment. The latter requires File::Spec | |
580 to be installed. | |
581 On Win32-based system, .exe is automatically appended to the program | |
582 name unless the program name already ends in .exe. | |
583 Example : | |
584 Returns : 1 if the given program is callable as an executable, and 0 otherwise | |
585 Args : the name of the executable | |
586 | |
587 =cut | |
588 | |
589 sub exists_exe { | |
590 my ($self, $exe) = @_; | |
591 $exe = $self if(!(ref($self) || $exe)); | |
592 $exe .= '.exe' if(($^O =~ /mswin/i) && ($exe !~ /\.(exe|com|bat|cmd)$/i)); | |
593 return $exe if(-e $exe); # full path and exists | |
594 | |
595 # Ewan's comment. I don't think we need this. People should not be | |
596 # asking for a program with a pathseparator starting it | |
597 | |
598 # $exe =~ s/^$PATHSEP//; | |
599 | |
600 # Not a full path, or does not exist. Let's see whether it's in the path. | |
601 if($FILESPECLOADED) { | |
602 foreach my $dir (File::Spec->path()) { | |
603 my $f = Bio::Root::IO->catfile($dir, $exe); | |
604 return $f if(-e $f && -x $f ); | |
605 } | |
606 } | |
607 return 0; | |
608 } | |
609 | |
610 =head2 tempfile | |
611 | |
612 Title : tempfile | |
613 Usage : my ($handle,$tempfile) = $io->tempfile(); | |
614 Function: Returns a temporary filename and a handle opened for writing and | |
615 and reading. | |
616 | |
617 Caveats : If you do not have File::Temp on your system you should avoid | |
618 specifying TEMPLATE and SUFFIX. (We don't want to recode | |
619 everything, okay?) | |
620 Returns : a 2-element array, consisting of temporary handle and temporary | |
621 file name | |
622 Args : named parameters compatible with File::Temp: DIR (defaults to | |
623 $Bio::Root::IO::TEMPDIR), TEMPLATE, SUFFIX. | |
624 | |
625 =cut | |
626 | |
627 #' | |
628 sub tempfile { | |
629 my ($self, @args) = @_; | |
630 my ($tfh, $file); | |
631 my %params = @args; | |
632 | |
633 # map between naming with and without dash | |
634 foreach my $key (keys(%params)) { | |
635 if( $key =~ /^-/ ) { | |
636 my $v = $params{$key}; | |
637 delete $params{$key}; | |
638 $params{uc(substr($key,1))} = $v; | |
639 } else { | |
640 # this is to upper case | |
641 my $v = $params{$key}; | |
642 delete $params{$key}; | |
643 $params{uc($key)} = $v; | |
644 } | |
645 } | |
646 $params{'DIR'} = $TEMPDIR if(! exists($params{'DIR'})); | |
647 unless (exists $params{'UNLINK'} && | |
648 defined $params{'UNLINK'} && | |
649 ! $params{'UNLINK'} ) { | |
650 $params{'UNLINK'} = 1; | |
651 } else { $params{'UNLINK'} = 0 } | |
652 | |
653 if($FILETEMPLOADED) { | |
654 if(exists($params{'TEMPLATE'})) { | |
655 my $template = $params{'TEMPLATE'}; | |
656 delete $params{'TEMPLATE'}; | |
657 ($tfh, $file) = File::Temp::tempfile($template, %params); | |
658 } else { | |
659 ($tfh, $file) = File::Temp::tempfile(%params); | |
660 } | |
661 } else { | |
662 my $dir = $params{'DIR'}; | |
663 $file = $self->catfile($dir, | |
664 (exists($params{'TEMPLATE'}) ? | |
665 $params{'TEMPLATE'} : | |
666 sprintf( "%s.%s.%s", | |
667 $ENV{USER} || 'unknown', $$, | |
668 $TEMPCOUNTER++))); | |
669 | |
670 # sneakiness for getting around long filenames on Win32? | |
671 if( $HAS_WIN32 ) { | |
672 $file = Win32::GetShortPathName($file); | |
673 } | |
674 | |
675 # taken from File::Temp | |
676 if ($] < 5.006) { | |
677 $tfh = &Symbol::gensym; | |
678 } | |
679 # Try to make sure this will be marked close-on-exec | |
680 # XXX: Win32 doesn't respect this, nor the proper fcntl, | |
681 # but may have O_NOINHERIT. This may or may not be in Fcntl. | |
682 local $^F = 2; | |
683 # Store callers umask | |
684 my $umask = umask(); | |
685 # Set a known umaskr | |
686 umask(066); | |
687 # Attempt to open the file | |
688 if ( sysopen($tfh, $file, $OPENFLAGS, 0600) ) { | |
689 # Reset umask | |
690 umask($umask); | |
691 } else { | |
692 $self->throw("Could not open tempfile $file: $!\n"); | |
693 } | |
694 } | |
695 | |
696 if( $params{'UNLINK'} ) { | |
697 push @{$self->{'_rootio_tempfiles'}}, $file; | |
698 } | |
699 | |
700 | |
701 return wantarray ? ($tfh,$file) : $tfh; | |
702 } | |
703 | |
704 =head2 tempdir | |
705 | |
706 Title : tempdir | |
707 Usage : my ($tempdir) = $io->tempdir(CLEANUP=>1); | |
708 Function: Creates and returns the name of a new temporary directory. | |
709 | |
710 Note that you should not use this function for obtaining "the" | |
711 temp directory. Use $Bio::Root::IO::TEMPDIR for that. Calling this | |
712 method will in fact create a new directory. | |
713 | |
714 Returns : The name of a new temporary directory. | |
715 Args : args - ( key CLEANUP ) indicates whether or not to cleanup | |
716 dir on object destruction, other keys as specified by File::Temp | |
717 | |
718 =cut | |
719 | |
720 sub tempdir { | |
721 my ( $self, @args ) = @_; | |
722 if($FILETEMPLOADED && File::Temp->can('tempdir') ) { | |
723 return File::Temp::tempdir(@args); | |
724 } | |
725 | |
726 # we have to do this ourselves, not good | |
727 # | |
728 # we are planning to cleanup temp files no matter what | |
729 my %params = @args; | |
730 $self->{'_cleanuptempdir'} = ( defined $params{CLEANUP} && | |
731 $params{CLEANUP} == 1); | |
732 my $tdir = $self->catfile($TEMPDIR, | |
733 sprintf("dir_%s-%s-%s", | |
734 $ENV{USER} || 'unknown', $$, | |
735 $TEMPCOUNTER++)); | |
736 mkdir($tdir, 0755); | |
737 push @{$self->{'_rootio_tempdirs'}}, $tdir; | |
738 return $tdir; | |
739 } | |
740 | |
741 =head2 catfile | |
742 | |
743 Title : catfile | |
744 Usage : $path = Bio::Root::IO->catfile(@dirs,$filename); | |
745 Function: Constructs a full pathname in a cross-platform safe way. | |
746 | |
747 If File::Spec exists on your system, this routine will merely | |
748 delegate to it. Otherwise it tries to make a good guess. | |
749 | |
750 You should use this method whenever you construct a path name | |
751 from directory and filename. Otherwise you risk cross-platform | |
752 compatibility of your code. | |
753 | |
754 You can call this method both as a class and an instance method. | |
755 | |
756 Returns : a string | |
757 Args : components of the pathname (directories and filename, NOT an | |
758 extension) | |
759 | |
760 =cut | |
761 | |
762 sub catfile { | |
763 my ($self, @args) = @_; | |
764 | |
765 return File::Spec->catfile(@args) if($FILESPECLOADED); | |
766 # this is clumsy and not very appealing, but how do we specify the | |
767 # root directory? | |
768 if($args[0] eq '/') { | |
769 $args[0] = $ROOTDIR; | |
770 } | |
771 return join($PATHSEP, @args); | |
772 } | |
773 | |
774 =head2 rmtree | |
775 | |
776 Title : rmtree | |
777 Usage : Bio::Root::IO->rmtree($dirname ); | |
778 Function: Remove a full directory tree | |
779 | |
780 If File::Path exists on your system, this routine will merely | |
781 delegate to it. Otherwise it runs a local version of that code. | |
782 | |
783 You should use this method to remove directories which contain | |
784 files. | |
785 | |
786 You can call this method both as a class and an instance method. | |
787 | |
788 Returns : number of files successfully deleted | |
789 Args : roots - rootdir to delete or reference to list of dirs | |
790 | |
791 verbose - a boolean value, which if TRUE will cause | |
792 C<rmtree> to print a message each time it | |
793 examines a file, giving the name of the file, and | |
794 indicating whether it's using C<rmdir> or | |
795 C<unlink> to remove it, or that it's skipping it. | |
796 (defaults to FALSE) | |
797 | |
798 safe - a boolean value, which if TRUE will cause C<rmtree> | |
799 to skip any files to which you do not have delete | |
800 access (if running under VMS) or write access (if | |
801 running under another OS). This will change in the | |
802 future when a criterion for 'delete permission' | |
803 under OSs other than VMS is settled. (defaults to | |
804 FALSE) | |
805 | |
806 =cut | |
807 | |
808 # taken straight from File::Path VERSION = "1.0403" | |
809 sub rmtree { | |
810 my($self,$roots, $verbose, $safe) = @_; | |
811 if( $FILEPATHLOADED ) { | |
812 return File::Path::rmtree ($roots, $verbose, $safe); | |
813 } | |
814 | |
815 my $force_writeable = ($^O eq 'os2' || $^O eq 'dos' || $^O eq 'MSWin32' | |
816 || $^O eq 'amigaos'); | |
817 my $Is_VMS = $^O eq 'VMS'; | |
818 | |
819 my(@files); | |
820 my($count) = 0; | |
821 $verbose ||= 0; | |
822 $safe ||= 0; | |
823 if ( defined($roots) && length($roots) ) { | |
824 $roots = [$roots] unless ref $roots; | |
825 } else { | |
826 $self->warn("No root path(s) specified\n"); | |
827 return 0; | |
828 } | |
829 | |
830 my($root); | |
831 foreach $root (@{$roots}) { | |
832 $root =~ s#/\z##; | |
833 (undef, undef, my $rp) = lstat $root or next; | |
834 $rp &= 07777; # don't forget setuid, setgid, sticky bits | |
835 if ( -d _ ) { | |
836 # notabene: 0777 is for making readable in the first place, | |
837 # it's also intended to change it to writable in case we have | |
838 # to recurse in which case we are better than rm -rf for | |
839 # subtrees with strange permissions | |
840 chmod(0777, ($Is_VMS ? VMS::Filespec::fileify($root) : $root)) | |
841 or $self->warn("Can't make directory $root read+writeable: $!") | |
842 unless $safe; | |
843 if (opendir(DIR, $root) ){ | |
844 @files = readdir DIR; | |
845 closedir(DIR); | |
846 } else { | |
847 $self->warn( "Can't read $root: $!"); | |
848 @files = (); | |
849 } | |
850 | |
851 # Deleting large numbers of files from VMS Files-11 filesystems | |
852 # is faster if done in reverse ASCIIbetical order | |
853 @files = reverse @files if $Is_VMS; | |
854 ($root = VMS::Filespec::unixify($root)) =~ s#\.dir\z## if $Is_VMS; | |
855 @files = map("$root/$_", grep $_!~/^\.{1,2}\z/s,@files); | |
856 $count += $self->rmtree([@files],$verbose,$safe); | |
857 if ($safe && | |
858 ($Is_VMS ? !&VMS::Filespec::candelete($root) : !-w $root)) { | |
859 print "skipped $root\n" if $verbose; | |
860 next; | |
861 } | |
862 chmod 0777, $root | |
863 or $self->warn( "Can't make directory $root writeable: $!") | |
864 if $force_writeable; | |
865 print "rmdir $root\n" if $verbose; | |
866 if (rmdir $root) { | |
867 ++$count; | |
868 } | |
869 else { | |
870 $self->warn( "Can't remove directory $root: $!"); | |
871 chmod($rp, ($Is_VMS ? VMS::Filespec::fileify($root) : $root)) | |
872 or $self->warn("and can't restore permissions to " | |
873 . sprintf("0%o",$rp) . "\n"); | |
874 } | |
875 } | |
876 else { | |
877 | |
878 if ($safe && | |
879 ($Is_VMS ? !&VMS::Filespec::candelete($root) | |
880 : !(-l $root || -w $root))) | |
881 { | |
882 print "skipped $root\n" if $verbose; | |
883 next; | |
884 } | |
885 chmod 0666, $root | |
886 or $self->warn( "Can't make file $root writeable: $!") | |
887 if $force_writeable; | |
888 print "unlink $root\n" if $verbose; | |
889 # delete all versions under VMS | |
890 for (;;) { | |
891 unless (unlink $root) { | |
892 $self->warn( "Can't unlink file $root: $!"); | |
893 if ($force_writeable) { | |
894 chmod $rp, $root | |
895 or $self->warn("and can't restore permissions to " | |
896 . sprintf("0%o",$rp) . "\n"); | |
897 } | |
898 last; | |
899 } | |
900 ++$count; | |
901 last unless $Is_VMS && lstat $root; | |
902 } | |
903 } | |
904 } | |
905 | |
906 $count; | |
907 } | |
908 | |
909 =head2 _flush_on_write | |
910 | |
911 Title : _flush_on_write | |
912 Usage : $obj->_flush_on_write($newval) | |
913 Function: Boolean flag to indicate whether to flush | |
914 the filehandle on writing when the end of | |
915 a component is finished (Sequences,Alignments,etc) | |
916 Returns : value of _flush_on_write | |
917 Args : newvalue (optional) | |
918 | |
919 | |
920 =cut | |
921 | |
922 sub _flush_on_write { | |
923 my ($self,$value) = @_; | |
924 if( defined $value) { | |
925 $self->{'_flush_on_write'} = $value; | |
926 } | |
927 return $self->{'_flush_on_write'}; | |
928 } | |
929 | |
930 1; |