From: Chris W. <la...@us...> - 2005-01-24 17:00:54
|
Update of /cvsroot/openinteract/OpenInteract2/lib/OpenInteract2 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14923 Modified Files: Util.pm Log Message: move code to find factory subclasses from OI2::Manage; this is also used by the updated OI2::Setup (coming shortly) Index: Util.pm =================================================================== RCS file: /cvsroot/openinteract/OpenInteract2/lib/OpenInteract2/Util.pm,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** Util.pm 5 Dec 2004 21:08:20 -0000 1.16 --- Util.pm 24 Jan 2005 17:00:43 -0000 1.17 *************** *** 4,8 **** --- 4,10 ---- use strict; + use Carp qw( carp ); use Digest::MD5; + use File::Spec::Functions qw( catdir catfile ); use Log::Log4perl qw( get_logger ); use Mail::Sendmail (); *************** *** 216,220 **** my $website_dir = CTX->lookup_directory( 'website' ); ! my $cleaned_filename = File::Spec->catfile( $website_dir, $filename ); if ( -f $cleaned_filename ) { $log->is_debug && --- 218,222 ---- my $website_dir = CTX->lookup_directory( 'website' ); ! my $cleaned_filename = catfile( $website_dir, $filename ); if ( -f $cleaned_filename ) { $log->is_debug && *************** *** 242,245 **** --- 244,311 ---- } + ######################################## + # FACTORY IMPLEMENTATIONS + + # Find all subclasses of a particular factory class anywhere on @INC + + my %FACTORY_FILES = (); + + sub find_factory_subclasses { + my ( $class, $factory_class, @dirs ) = @_; + + foreach my $lib_dir ( @dirs ) { + next unless ( $lib_dir ); + my $manage_dir = catdir( $lib_dir, split( '::', $factory_class ) ); + next unless ( -d $manage_dir ); + eval { _find_descend( $manage_dir ) }; + if ( $@ ) { + carp "Error trying to find subclasses of '$factory_class' in $lib_dir: $@\n"; + } + } + + # Now grab the class names from the files stored in %FACTORY_FILES + # so we don't try to include the same class from different files + # -- this normally only happens for developers who have the OI2 + # lib directory in their PERL5LIB and who are running tests + + my %FACTORY_CLASSES = (); + foreach my $file ( sort keys %FACTORY_FILES ) { + my $file_class = $file; + $file_class =~ s/^.*OpenInteract2/OpenInteract2/; + $file_class =~ s/\.pm$//; + $file_class =~ s/\W/::/g; + $FACTORY_CLASSES{ $file_class } ||= $file; + } + + # Why 'sort'? It ensures that classes further up the hierarchy + # (e.g., 'OI2::Manage::Website') get required before their + # children; otherwise we get lots of 'subroutine foo redefined' + # messages under '-w', irritating. + + foreach my $factory_subclass ( sort keys %FACTORY_CLASSES ) { + eval "require $factory_subclass"; + if ( $@ ) { + carp "Failed to bring in library '$factory_subclass': $@"; + } + } + } + + sub _find_descend { + my ( $lib_dir ) = @_; + opendir( FACTORYDIR, $lib_dir ) + || die "Cannot open directory '$lib_dir': $!"; + my @entries = grep ! /^\./, readdir( FACTORYDIR ); + foreach my $entry ( @entries ) { + my $full_entry_dir = catdir( $lib_dir, $entry ); + if ( -d $full_entry_dir ) { + _find_descend( $full_entry_dir ); # let this error bubble + } + next unless ( $entry =~ /\.pm$/ ); + my $full_filename = catfile( $lib_dir, $entry ); + $FACTORY_FILES{ $full_filename } = 1; + } + } + + 1; *************** *** 424,427 **** --- 490,513 ---- match up to one, undef is returned. + =head1 FACTORY SUBCLASSES + + B<find_factory_subclasses( $factory_class, @directories )> + + Finds all subclasses of C<$factory_class> using C<@directories> as the + list of directories from which to start. So to discover all the + L<OpenInteract2::Manage> subclasses from all Perl module directories + we would do: + + OpenInteract2::Util->find_factory_subclasses( + 'OpenInteract2::Manage', @INC + ); + + And to find them from the temporary library directory, we'd do: + + my $temp_lib_dir = CTX->lookup_temp_lib_directory; + OpenInteract2::Util->find_factory_subclasses( + 'OpenInteract2::Manage', $temp_lib_dir + ); + =head1 TO DO |