package Cipres::Registry; use File::Spec; use File::Basename; use Exception::Class::TCF; use Cipres::Registry::Observable; use Cipres::SuperClasses::CorbaClient; use Cipres::SuperClasses::Authenticator; use Cipres::SuperClasses::ProcessLauncher; use Cipres::IDL::CipresIDL_api1; use Cipres::IDL::CipresIDL_api1::Scriptable; use Cipres::IDL::CipresIDL_api1::Registry; use Cipres::IDL::CipresIDL_api1::LifeCycle; use vars '@ISA'; @ISA=qw( Cipres::SuperClasses::CorbaClient Cipres::SuperClasses::Authenticator Cipres::SuperClasses::ProcessLauncher ); # This is a perl representation of the cipres registry # application. This class can be used inside perl scripts # to find and instantiate services. It can also be used as # a model in an mvc context, as for the cipres registry # manager application. To this end, the registry contains # several observable attributes (whether the registry is # online, the latest cached version of the service tree, # the latest query result etc). Callbacks can be attached to # these attributes. The Callbacks are triggered when the # attribute's state changes, so that the view can be updated. # -- Rutger Vos, 17/Aug/2006 13:57 # this is the constructor for the registry wrapper. Note # how the wrapper's attributes consist mainly of a bunch # of observables that others can attach themselves to to # listen for state changes. Refer to Cipres::Registry::Observable # for the API of these attributes. sub new { my $class = shift; my $self = { # this is a list of the most recent search results returned # by the registry '_services' => Cipres::Registry::Observable->new([]), # this contains the most recent query (i.e. registry entry # info hash) that we send via corba to the registry '_queries' => Cipres::Registry::Observable->new(), # this contains the boolean to indicate whether the registry # is to be launched on a fixed port '_fixed' => Cipres::Registry::Observable->new(), }; # instantiate SUPER classes $_->new( $self ) for ( @ISA ); bless $self, __PACKAGE__; # hardcoded interface, method in Cipres::SuperClasses::CorbaClient, # used for narrowing $self->set_iface( 'Cipres::IDL::CipresIDL_api1::Registry' ); return $self; } # this flags whether the registry is to be run on a fixed port sub set_fixed_port { my ( $self, $bool ) = @_; $self->get_fixed_port_observable->set( $bool ); return $self; } # this returns whether the registry is to be run on a fixed port sub get_fixed_port { my $self = shift; return $self->get_fixed_port_observable->get; } # this returns the observable fixed port flag sub get_fixed_port_observable { my $self = shift; return $self->{'_fixed'}; } # hardcoded name, used to find log, pid file sub get_name { 'registry' } # generate launch command sub get_command { my $self = shift; my ( $name, $path, $suffix ) = fileparse( __FILE__ ); my $jar_file = File::Spec->canonpath( File::Spec->catfile( $path, '../../../cipres', 'cipres-classpath.jar' ) ); my ( $jar_name, $jar_path, $jar_suffix ) = fileparse( $jar_file ); my $jni_path = `java -classpath $jar_file org.cipres.jni.JavaLibPath`; chomp( $jni_path ); my $lib_path = $jar_path . ':' . $jni_path; my $fixed_port = $self->get_fixed_port ? '-DfixedPort=1' : ''; return "java -Djava.library.path=${lib_path} ${fixed_port} -ea -classpath ${jar_file} org.cipres.registry.RegistryApp & |"; } # find all services that match %match sub find { my ( $self, %match ) = @_; if ( $self->is_connected ) { my $find = $self->get_connection->find( _make_rei( %match ) ); $self->get_query_observable->set( _make_rei( %match ) ); $self->get_service_observable->set( $find ); return $self->get_service_observable->get; } else { throw new Cipres::Exception::ConnectionError Message => 'Not connected!'; } } # find first service that matches %match sub find_first { my ( $self, %match ) = @_; if ( $self->is_connected ) { my $first = $self->get_connection->findFirst( _make_rei( %match ) ); $self->get_query_observable->set( _make_rei( %match ) ); $self->get_service_observable->set( $first ); return $self->get_service_observable->get; } else { throw new Cipres::Exception::ConnectionError Message => 'Not connected!'; } } # registry instantiates service, returns reference sub get_object { my ( $self, $entry ) = @_; if ( $self->is_connected ) { my $id = 0; my $object = $self->get_connection->getObject( $entry, \$id ); $self->get_query_observable->set( $object ); return $self->get_query_observable->get; } else { throw new Cipres::Exception::ConnectionError Message => 'Not connected!'; } } # get ui xml for service sub get_ui_xml { my ( $self, $entry ) = @_; if ( $self->is_connected ) { my $xml = $self->get_connection->getUiXml( $entry ); $self->get_query_observable->set( $xml ); return $self->get_query_observable->get; } else { throw new Cipres::Exception::ConnectionError Message => 'Not connected!'; } } sub get_query_observable { my $self = shift; return $self->{'_queries'}; } sub get_services { my $self = shift; return $self->get_service_observable->get; } sub get_service_observable { my $self = shift; return $self->{'_services'}; } # restart, reconnect sub refresh { my $self = shift; $self->disconnect(); $self->stop(); $self->start(); $self->connect(); if ( $self->is_connected ) { $self->get_service_observable->set( $self->find() ); } else { $self->get_connection_observable->set( 0 ); } } # get registry's name sub registryInstanceID { my $self = shift; if ( $self->is_connected ) { return $self->get_connection->registryInstanceID; } else { throw new Cipres::Exception::ConnectionError Message => 'Not connected!'; } } # turns a (maybe partially incomplete) hash into a RegistryEntryInfo # data structure sub _make_rei { my %hash = @_; my $rei = Cipres::IDL::CipresIDL_api1::RegistryEntryInfo->new; for ( qw(registryInstanceID repositoryID applicationName description) ) { if ( not exists $hash{$_} ) { $rei->{$_} = ''; } else { $rei->{$_} = $hash{$_}; } } return $rei; } sub DESTROY { shift->stop } 1;