package SPOPS::Tool::LDAP::Datasource; # $Id: Datasource.pm,v 3.3 2004/06/02 00:48:24 lachoy Exp $ use strict; use Log::Log4perl qw( get_logger ); use SPOPS; use SPOPS::ClassFactory qw( ERROR OK NOTIFY ); my $log = get_logger(); $SPOPS::Tool::LDAP::Datasource::VERSION = sprintf("%d.%02d", q$Revision: 3.3 $ =~ /(\d+)\.(\d+)/); sub behavior_factory { my ( $class ) = @_; $log->is_info && $log->info( "Installing LDAP datasource configuration for ($class)" ); return { manipulate_configuration => \&datasource_access }; } my $generic_ds_sub = <<'DS'; sub %%CLASS%%::global_datasource_handle { my ( $class ) = @_; unless ( $%%CLASS%%::LDAP ) { require Net::LDAP; $%%CLASS%%::LDAP = Net::LDAP->new( '%%HOST%%', port => %%PORT%%, version => %%VERSION%% ) or SPOPS::Exception->throw( "Cannot connect to LDAP directory: $@" ); $%%CLASS%%::LDAP->bind(%%BIND_INFO%%); } return $%%CLASS%%::LDAP; } DS sub datasource_access { my ( $class ) = @_; my $ldap_config = $class->CONFIG->{ldap_config}; my $host = $ldap_config->{host} || 'localhost'; my $port = $ldap_config->{port} || 389; my $version = $ldap_config->{version} || 2; my $bind_info = ''; if ( $ldap_config->{bind_dn} ) { $bind_info = " dn => '$ldap_config->{bind_dn}', " . " password => '$ldap_config->{bind_password}' "; } my $ds_code = $generic_ds_sub; $ds_code =~ s/%%CLASS%%/$class/g; $ds_code =~ s/%%HOST%%/$host/g; $ds_code =~ s/%%PORT%%/$port/g; $ds_code =~ s/%%VERSION%%/$version/g; $ds_code =~ s/%%BIND_INFO%%/$bind_info/g; { local $SIG{__WARN__} = sub { return undef }; eval $ds_code; } if ( $@ ) { warn "Code: $ds_code\n"; return ( ERROR, "Cannot create 'global_datasource_handle() for ($class): $@" ); } return ( OK, undef ); } 1; __END__ =head1 NAME SPOPS::Tool::LDAP::Datasource -- Embed the parameters for a LDAP handle in object configuration =head1 SYNOPSIS # Connect to a server running on localhost:389 using an anonymous # bind (no username/password) my $spops = { myobject => { class => 'My::Object', rules_from => [ 'SPOPS::Tool::LDAP::Datasource' ] field => [ qw/ cn sn givenname displayname mail telephonenumber objectclass uid ou / ], id_field => 'uid', ldap_base_dn => 'ou=People,dc=MyCompany,dc=com', ... }, }; SPOPS::Initialize->process({ config => $spops }); my $ldap_filter = '&(objectclass=inetOrgPerson)(mail=*cwinters.com)'; my $list = My::Object->fetch_group({ where => $ldap_filter }); foreach my $object ( @{ $list } ) { print "Name: $object->{givenname} at $object->{mail}\n"; } =head1 DESCRIPTION This rule allows you to embed the LDAP connection information in your object rather than using the strategies described elsewhere. This is very handy for creating simple, one-off scripts, but you should still use the subclassing strategy from L if you will have multiple objects using the same datasource. =head1 METHODS B Generates a behavior to generate the datasource retrieval code during the 'manipulate_configuration' phase. B Generates the 'global_datasource_handle()' method that retrieves an opened database handle if it exists or creates one otherwise. =head1 BUGS None known. =head1 TO DO Nothing known. =head1 SEE ALSO L L =head1 COPYRIGHT Copyright (c) 2001-2004 intes.net, inc.. All rights reserved. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 AUTHORS Chris Winters Echris@cwinters.comE Thanks to jeffa on PerlMonks (http://www.perlmonks.org/index.pl?node_id=18800) for suggesting this!