package InfoSys::FreeDB::Connection; use 5.006; use base qw( Exporter ); use strict; use warnings; use AutoLoader qw(AUTOLOAD); use Error qw(:try); require Exporter; our $FINAL_DOT_RX = '[\r\n]\.[\r\n]'; our $FINAL_EOL_RX = '[\r\n]'; # Used by _initialize our %DEFAULT_VALUE = ( 'proto_level' => 1, 'proxy_port' => 8080, ); # Exporter variable our %EXPORT_TAGS = ( 'line_parse' => [ qw( $FINAL_DOT_RX $FINAL_EOL_RX ) ], ); # Package version our ($VERSION) = '$Revision: 0.92 $' =~ /\$Revision:\s+([^\s]+)/; # Exporter variable our @EXPORT = qw( ); # Exporter variable our @EXPORT_OK = qw( $FINAL_DOT_RX $FINAL_EOL_RX ); 1; __END__ =head1 NAME InfoSys::FreeDB::Connection - FreeDB abstract connection =head1 SYNOPSIS None. This is an abstract class. =head1 ABSTRACT FreeDB abstract connection =head1 DESCRIPTION C is the abstract connection class of the C module hierarchy. =head1 EXPORT By default nothing is exported. =head2 line_parse This tag contains variables useful to parse the messages from C servers. =over =item $FINAL_DOT_RX Regular expression to parse the end of message dot. =item $FINAL_EOL_RX Regular expression to parse the end of line. =back =head1 CONSTRUCTOR =over =item new(OPT_HASH_REF) Creates a new C object. C is a hash reference used to pass initialization options. C is mandatory. On error an exception C is thrown. Options for C may include: =over =item B> Passed to L. Mandatory option. =item B> Passed to L. Mandatory option. =item B> Passed to L. Mandatory option. =item B> Passed to L. Mandatory option. =item B> Passed to L. Mandatory option. =item B> Passed to L. Mandatory option. =item B> Passed to L. Defaults to B<1>. =item B> Passed to L. =item B> Passed to L. =item B> Passed to L. Defaults to B<8080>. =item B> Passed to L. =back =back =head1 METHODS =over =item connect() This is an interface method. Connects the object to the FreeDB information service using the object's attributes. A C commend is sent out, the protocol level is queried and set to the highest level available. On error an exception C is thrown. =item discid(ENTRY) Issues a C command on the FreeDB database. C is a C object. On error an exception C is thrown. =item disconnect() Disconnects the object from the FreeDB information service. =item get_client_host() Returns the connecting client host. =item get_client_name() Returns the connecting client name. =item get_client_user() Returns the connecting client user. =item get_client_version() Returns the connecting client version. =item get_freedb_host() Returns the FreeDB host. =item get_freedb_port() Returns the FreeDB port. =item get_proto_level() Returns the current protocol level. =item get_proxy_host() Returns the proxy host to use. =item get_proxy_passwd() Returns the proxy password to use. =item get_proxy_port() Returns the proxy port to use. =item get_proxy_user() Returns the proxy user name to use. =item log() This is an interface method. Issues a C command on the FreeDB database. TO BE SPECIFIED =item lscat() Issues an C command on the FreeDB database. Returns a C object. On error an exception C is thrown. =item motd() Issues an C command on the FreeDB database. Returns C object. On error an exception C is thrown. =item proto([ LEVEL ]) This is an interface method. Issues a C command on the FreeDB database. If C is not specified, the protocol level is queried. If C is specified it is used to set the protocol level. Returns C object. On error an exception C is thrown. =item query(ENTRY) Queries the FreeDB database. C is a C object. Returns a C object. On error an exception C is thrown. =item quit() This is an interface method. Issues a C command on the FreeDB database and disconnects. Returns C object. On error an exception C is thrown. =item read(MATCH) Reads an entry from the FreeDB database. C is a C object. Returns a C object. On error an exception C is thrown. =item set_client_host(VALUE) Set the connecting client host. C is the value. C may not be C. On error an exception C is thrown. =item set_client_name(VALUE) Set the connecting client name. C is the value. C may not be C. On error an exception C is thrown. =item set_client_user(VALUE) Set the connecting client user. C is the value. C may not be C. On error an exception C is thrown. =item set_client_version(VALUE) Set the connecting client version. C is the value. C may not be C. On error an exception C is thrown. =item set_freedb_host(VALUE) Set the FreeDB host. C is the value. C may not be C. On error an exception C is thrown. =item set_freedb_port(VALUE) Set the FreeDB port. C is the value. C may not be C. On error an exception C is thrown. =item set_proto_level(VALUE) Set the current protocol level. C is the value. Default value at initialization is C<1>. On error an exception C is thrown. =item set_proxy_host(VALUE) Set the proxy host to use. C is the value. On error an exception C is thrown. =item set_proxy_passwd(VALUE) Set the proxy password to use. C is the value. On error an exception C is thrown. =item set_proxy_port(VALUE) Set the proxy port to use. C is the value. Default value at initialization is C<8080>. On error an exception C is thrown. =item set_proxy_user(VALUE) Set the proxy user name to use. C is the value. On error an exception C is thrown. =item sites() Issues a C command on the FreeDB database. Returns a C object. On error an exception C is thrown. =item stat() Issues a C command on the FreeDB database. Returns a C object. On error an exception C is thrown. =item update() This is an interface method. Issues a C command on the FreeDB database. TO BE SPECIFIED =item ver() Issues a C command on the FreeDB database. Returns a C object. On error an exception C is thrown. =item whom() Issues a C command on the FreeDB database. Returns a C object. On error an exception C is thrown. =item write(ENTRY, CATEGORY) This is an interface method. Writes an entry to the FreeDB database. C is a C object. C is a valid FreeDB category. Returns a C object in the case an error occurred in the first pass of the writing. Otherwise a C object is returned. On error an exception C is thrown. =back =head1 SEE ALSO L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L =head1 BUGS None known (yet.) =head1 HISTORY First development: September 2003 Last update: December 2003 =head1 AUTHOR Vincenzo Zocca =head1 COPYRIGHT Copyright 2003 by Vincenzo Zocca =head1 LICENSE This file is part of the C module hierarchy for Perl by Vincenzo Zocca. The InfoSys::FreeDB module hierarchy is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The InfoSys::FreeDB module hierarchy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the InfoSys::FreeDB module hierarchy; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA =cut sub new { my $class = shift; my $self = {}; bless( $self, ( ref($class) || $class ) ); return( $self->_initialize(@_) ); } sub _initialize { my $self = shift; my $opt = defined($_[0]) ? shift : {}; # Check $opt ref($opt) eq 'HASH' || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::_initialize, first argument must be 'HASH' reference."); # _connection_, SINGLE exists( $opt->{_connection_} ) && $self->set__connection_( $opt->{_connection_} ); # client_host, SINGLE, mandatory exists( $opt->{client_host} ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::_initialize, option 'client_host' is mandatory."); $self->set_client_host( $opt->{client_host} ); # client_name, SINGLE, mandatory exists( $opt->{client_name} ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::_initialize, option 'client_name' is mandatory."); $self->set_client_name( $opt->{client_name} ); # client_user, SINGLE, mandatory exists( $opt->{client_user} ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::_initialize, option 'client_user' is mandatory."); $self->set_client_user( $opt->{client_user} ); # client_version, SINGLE, mandatory exists( $opt->{client_version} ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::_initialize, option 'client_version' is mandatory."); $self->set_client_version( $opt->{client_version} ); # freedb_host, SINGLE, mandatory exists( $opt->{freedb_host} ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::_initialize, option 'freedb_host' is mandatory."); $self->set_freedb_host( $opt->{freedb_host} ); # freedb_port, SINGLE, mandatory exists( $opt->{freedb_port} ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::_initialize, option 'freedb_port' is mandatory."); $self->set_freedb_port( $opt->{freedb_port} ); # proto_level, SINGLE, with default value $self->set_proto_level( exists( $opt->{proto_level} ) ? $opt->{proto_level} : $DEFAULT_VALUE{proto_level} ); # proxy_host, SINGLE exists( $opt->{proxy_host} ) && $self->set_proxy_host( $opt->{proxy_host} ); # proxy_passwd, SINGLE exists( $opt->{proxy_passwd} ) && $self->set_proxy_passwd( $opt->{proxy_passwd} ); # proxy_port, SINGLE, with default value $self->set_proxy_port( exists( $opt->{proxy_port} ) ? $opt->{proxy_port} : $DEFAULT_VALUE{proxy_port} ); # proxy_user, SINGLE exists( $opt->{proxy_user} ) && $self->set_proxy_user( $opt->{proxy_user} ); # Return $self return($self); } sub _value_is_allowed { return(1); } sub _wait_command_reply { throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::_wait_command_reply, call this method in a subclass that has implemented it."); } sub connect { throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::connect, call this method in a subclass that has implemented it."); } sub discid { my $self = shift; my $entry = shift; # Send command and wait for reply my @cmd = ( 'discid', scalar( $entry->get_track() ) ); foreach my $track ( $entry->get_track() ) { push( @cmd, $track->get_offset() ); } push( @cmd, $entry->get_disc_length() ); my $cmd = join( ' ', @cmd ); my $content_ref = $self->_wait_command_reply($cmd, { 200 => $FINAL_EOL_RX, 500 => $FINAL_EOL_RX, } ); # Parse the result require InfoSys::FreeDB::Response::DiscId; my $res = InfoSys::FreeDB::Response::DiscId->new_from_content_ref( $content_ref ); # Write the discid in the entry $res->is_error() || $entry->set_discid( $res->get_discid() ); # Return the result return($res); } sub disconnect { my $self = shift; # Call quit return( $self->quit() ); } sub get__connection_ { my $self = shift; return( $self->{InfoSys_FreeDB_Connection}{_connection_} ); } sub get_client_host { my $self = shift; return( $self->{InfoSys_FreeDB_Connection}{client_host} ); } sub get_client_name { my $self = shift; return( $self->{InfoSys_FreeDB_Connection}{client_name} ); } sub get_client_user { my $self = shift; return( $self->{InfoSys_FreeDB_Connection}{client_user} ); } sub get_client_version { my $self = shift; return( $self->{InfoSys_FreeDB_Connection}{client_version} ); } sub get_freedb_host { my $self = shift; return( $self->{InfoSys_FreeDB_Connection}{freedb_host} ); } sub get_freedb_port { my $self = shift; return( $self->{InfoSys_FreeDB_Connection}{freedb_port} ); } sub get_proto_level { my $self = shift; return( $self->{InfoSys_FreeDB_Connection}{proto_level} ); } sub get_proxy_host { my $self = shift; return( $self->{InfoSys_FreeDB_Connection}{proxy_host} ); } sub get_proxy_passwd { my $self = shift; return( $self->{InfoSys_FreeDB_Connection}{proxy_passwd} ); } sub get_proxy_port { my $self = shift; return( $self->{InfoSys_FreeDB_Connection}{proxy_port} ); } sub get_proxy_user { my $self = shift; return( $self->{InfoSys_FreeDB_Connection}{proxy_user} ); } sub log { throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::log, call this method in a subclass that has implemented it."); } sub lscat { my $self = shift; # Send command and wait for reply my $cmd = 'cddb lscat'; my $content_ref = $self->_wait_command_reply($cmd, { 210 => $FINAL_DOT_RX, } ); # Parse the result and return it require InfoSys::FreeDB::Response::LsCat; return( InfoSys::FreeDB::Response::LsCat->new_from_content_ref( $content_ref ) ); } sub motd { my $self = shift; # Send command and wait for reply my $cmd = 'motd'; my $content_ref = $self->_wait_command_reply($cmd, { 210 => $FINAL_DOT_RX, 401 => $FINAL_EOL_RX, } ); # Parse the result and return it require InfoSys::FreeDB::Response::Motd; return( InfoSys::FreeDB::Response::Motd->new_from_content_ref( $content_ref ) ); } sub proto { throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::proto, call this method in a subclass that has implemented it."); } sub query { my $self = shift; my $entry = shift; # Make the discid $self->discid( $entry ); # Send command and wait for reply my @cmd = ( 'cddb', 'query', $entry->get_discid(), scalar( $entry->get_track() ) ); foreach my $track ( $entry->get_track() ) { push( @cmd, $track->get_offset() ); } push( @cmd, $entry->get_disc_length() ); my $cmd = join( ' ', @cmd ); my $content_ref = $self->_wait_command_reply($cmd, { 200 => $FINAL_EOL_RX, 210 => $FINAL_EOL_RX, 211 => $FINAL_DOT_RX, 202 => $FINAL_EOL_RX, 403 => $FINAL_EOL_RX, 409 => $FINAL_EOL_RX, } ); # Parse the result and return it require InfoSys::FreeDB::Response::Query; return( InfoSys::FreeDB::Response::Query->new_from_content_ref( $content_ref ) ); } sub quit { throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::quit, call this method in a subclass that has implemented it."); } sub read { my $self = shift; my $match = shift; # Send command and wait for reply my @cmd = ( 'cddb', 'read', $match->get_categ(), $match->get_discid(), ); my $cmd = join( ' ', @cmd ); my $content_ref = $self->_wait_command_reply($cmd, { 210 => $FINAL_DOT_RX, 211 => $FINAL_DOT_RX, 401 => $FINAL_EOL_RX, 402 => $FINAL_EOL_RX, 403 => $FINAL_EOL_RX, 409 => $FINAL_EOL_RX, } ); # Parse the result and return it require InfoSys::FreeDB::Response::Read; return( InfoSys::FreeDB::Response::Read->new_from_content_ref( $content_ref ) ); } sub set__connection_ { my $self = shift; my $val = shift; # Check if isa/ref/rx/value is allowed &_value_is_allowed( '_connection_', $val ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set__connection_, the specified value '$val' is not allowed."); # Assignment $self->{InfoSys_FreeDB_Connection}{_connection_} = $val; } sub set_client_host { my $self = shift; my $val = shift; # Value for 'client_host' is not allowed to be empty defined($val) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_client_host, value may not be empty."); # Check if isa/ref/rx/value is allowed &_value_is_allowed( 'client_host', $val ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_client_host, the specified value '$val' is not allowed."); # Assignment $self->{InfoSys_FreeDB_Connection}{client_host} = $val; } sub set_client_name { my $self = shift; my $val = shift; # Value for 'client_name' is not allowed to be empty defined($val) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_client_name, value may not be empty."); # Check if isa/ref/rx/value is allowed &_value_is_allowed( 'client_name', $val ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_client_name, the specified value '$val' is not allowed."); # Assignment $self->{InfoSys_FreeDB_Connection}{client_name} = $val; } sub set_client_user { my $self = shift; my $val = shift; # Value for 'client_user' is not allowed to be empty defined($val) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_client_user, value may not be empty."); # Check if isa/ref/rx/value is allowed &_value_is_allowed( 'client_user', $val ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_client_user, the specified value '$val' is not allowed."); # Assignment $self->{InfoSys_FreeDB_Connection}{client_user} = $val; } sub set_client_version { my $self = shift; my $val = shift; # Value for 'client_version' is not allowed to be empty defined($val) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_client_version, value may not be empty."); # Check if isa/ref/rx/value is allowed &_value_is_allowed( 'client_version', $val ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_client_version, the specified value '$val' is not allowed."); # Assignment $self->{InfoSys_FreeDB_Connection}{client_version} = $val; } sub set_freedb_host { my $self = shift; my $val = shift; # Value for 'freedb_host' is not allowed to be empty defined($val) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_freedb_host, value may not be empty."); # Check if isa/ref/rx/value is allowed &_value_is_allowed( 'freedb_host', $val ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_freedb_host, the specified value '$val' is not allowed."); # Assignment $self->{InfoSys_FreeDB_Connection}{freedb_host} = $val; } sub set_freedb_port { my $self = shift; my $val = shift; # Value for 'freedb_port' is not allowed to be empty defined($val) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_freedb_port, value may not be empty."); # Check if isa/ref/rx/value is allowed &_value_is_allowed( 'freedb_port', $val ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_freedb_port, the specified value '$val' is not allowed."); # Assignment $self->{InfoSys_FreeDB_Connection}{freedb_port} = $val; } sub set_proto_level { my $self = shift; my $val = shift; # Check if isa/ref/rx/value is allowed &_value_is_allowed( 'proto_level', $val ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_proto_level, the specified value '$val' is not allowed."); # Assignment $self->{InfoSys_FreeDB_Connection}{proto_level} = $val; } sub set_proxy_host { my $self = shift; my $val = shift; # Check if isa/ref/rx/value is allowed &_value_is_allowed( 'proxy_host', $val ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_proxy_host, the specified value '$val' is not allowed."); # Assignment $self->{InfoSys_FreeDB_Connection}{proxy_host} = $val; } sub set_proxy_passwd { my $self = shift; my $val = shift; # Check if isa/ref/rx/value is allowed &_value_is_allowed( 'proxy_passwd', $val ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_proxy_passwd, the specified value '$val' is not allowed."); # Assignment $self->{InfoSys_FreeDB_Connection}{proxy_passwd} = $val; } sub set_proxy_port { my $self = shift; my $val = shift; # Check if isa/ref/rx/value is allowed &_value_is_allowed( 'proxy_port', $val ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_proxy_port, the specified value '$val' is not allowed."); # Assignment $self->{InfoSys_FreeDB_Connection}{proxy_port} = $val; } sub set_proxy_user { my $self = shift; my $val = shift; # Check if isa/ref/rx/value is allowed &_value_is_allowed( 'proxy_user', $val ) || throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::set_proxy_user, the specified value '$val' is not allowed."); # Assignment $self->{InfoSys_FreeDB_Connection}{proxy_user} = $val; } sub sites { my $self = shift; # Send command and wait for reply my $cmd = 'sites'; my $content_ref = $self->_wait_command_reply($cmd, { 210 => $FINAL_DOT_RX, 401 => $FINAL_EOL_RX, } ); # Parse the result and return it require InfoSys::FreeDB::Response::Sites; return( InfoSys::FreeDB::Response::Sites->new_from_content_ref( $content_ref ) ); } sub stat { my $self = shift; # Send command and wait for reply my $cmd = 'stat'; my $content_ref = $self->_wait_command_reply($cmd, { 210 => $FINAL_DOT_RX, } ); # Parse the result and return it require InfoSys::FreeDB::Response::Stat; return( InfoSys::FreeDB::Response::Stat->new_from_content_ref( $content_ref ) ); } sub update { throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::update, call this method in a subclass that has implemented it."); } sub ver { my $self = shift; # Send command and wait for reply my $cmd = 'ver'; my $content_ref = $self->_wait_command_reply($cmd, { 200 => $FINAL_EOL_RX, 211 => $FINAL_DOT_RX, } ); # Parse the result and return it require InfoSys::FreeDB::Response::Ver; return( InfoSys::FreeDB::Response::Ver->new_from_content_ref( $content_ref ) ); } sub whom { my $self = shift; # Send command and wait for reply my $cmd = 'whom'; my $content_ref = $self->_wait_command_reply($cmd, { 210 => $FINAL_DOT_RX, 401 => $FINAL_EOL_RX, } ); # Parse the result and return it require InfoSys::FreeDB::Response::Whom; return( InfoSys::FreeDB::Response::Whom->new_from_content_ref( $content_ref ) ); } sub write { throw Error::Simple("ERROR: InfoSys::FreeDB::Connection::write, call this method in a subclass that has implemented it."); }