use strict;
use warnings;
-use Getopt::Long;
+use Getopt::Long qw(:DEFAULT GetOptionsFromArray);
use OpenSRF::System;
use OpenSRF::AppSession;
use OpenSRF::Utils::JSON;
# (2) provides hashspace for the rest of the arbitrary options from the command-line
#
# TODO: allow more options to be passed here, maybe mimic Getopt::Long::GetOptions style
+#
+# If an arrayref argument is passed, then @ARGV will NOT be touched.
+# Instead, the array will be passed to GetOptionsFromArray.
+#
sub MyGetOptions {
my $self = shift;
+ my $arrayref = @_ ? shift : undef;
+ if ($arrayref and ref($arrayref) ne 'ARRAY') {
+ carp "MyGetOptions argument is not an array ref. Expect GetOptionsFromArray to explode";
+ }
$self->{got_options} and carp "MyGetOptions called after options were already retrieved previously";
my @keys = sort {is_clean($b) <=> is_clean($a)} keys %{$self->{default_opts}};
$debug and print "KEYS: ", join(", ", @keys), "\n";
foreach (@keys) {
my $clean = clean($_);
- $self->{opts_clean}->{$clean} = $self->{default_opts_clean}->{$clean}; # prepopulate default
- $self->{opts}->{$_} = \$self->{opts_clean}->{$clean}; # pointer for GetOptions
+ my $place = $self->{default_opts_clean}->{$clean};
+ $self->{opts_clean}->{$clean} = $place; # prepopulate default
+ # $self->{opts}->{$_} = $self->{opts_clean}->{$clean}; # pointer for GetOptions
+ $self->{opts}->{$_} = sub {
+ my $opt = shift;
+ my $val = shift;
+ ref ( $self->{opts_clean}->{$opt} ) and ref($self->{opts_clean}->{$opt}) eq 'SCALAR'
+ and ${$self->{opts_clean}->{$opt}} = $val; # set the referent's value
+ $self->{opts_clean}->{$opt} = $val; # burn the map, stick the value there
+ }; # pointer for GetOptions
}
- GetOptions($self->{opts}, @keys);
+ $arrayref ? GetOptionsFromArray($arrayref, $self->{opts}, @keys)
+ : GetOptions( $self->{opts}, @keys) ;
+
foreach (@keys) {
delete $self->{opts}->{$_}; # now remove the mappings from (1) so we just have (2)
}
$self->clean_mirror('opts'); # populate clean_opts w/ cleaned versions of (2), plus everything else
print $self->help() and exit if $self->{opts_clean}->{help};
- $debug and $OpenILS::Utils::Lockfile::debug = $debug;
+ $self->new_lockfile();
+ $self->{got_options}++;
+ return wantarray ? %{$self->{opts_clean}} : $self->{opts_clean};
+}
+sub new_lockfile {
+ my $self = shift;
+ $debug and $OpenILS::Utils::Lockfile::debug = $debug;
unless ($self->{opts_clean}->{nolockfile} || $self->{default_opts_clean}->{nolockfile}) {
$self->{lockfile_obj} = OpenILS::Utils::Lockfile->new($self->first_defined('lock-file'));
$self->{lockfile} = $self->{lockfile_obj}->filename;
}
- $self->{got_options}++;
- return $self;
}
sub first_defined {
my $val = shift;
my $clean = clean($key);
my @others = grep {/$clean/ and $_ ne $key} keys %{$self->{default_opts}};
+ unless (@others) {
+ $debug and print "unique key $key => $val\n";
+ $self->{default_opts}->{$key} = $val; # no purge, just add
+ return;
+ }
foreach (@others) {
$debug and print "variant of $key => $_\n";
if ($key ne $clean) { # if it is a dirtier key, delete the clean one
# TODO: check $opts is hashref; then check verbose/debug first. maybe check negations e.g. "no-verbose" ?
@extra_opts = keys %$opts;
foreach (@extra_opts) { # add any other keys w/ default values
+ $debug and print "init() adding option $_, default value: $opts->{$_}\n";
$self->add_and_purge($_, $opts->{$_});
}
$self->clean_mirror;
}
sub usage {
- my $self = shift;
+ # my $self = shift;
return "\nUSAGE: $0 [OPTIONS]";
}
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-=head1 NAME
-
-marc_stream_importer.pl - Import MARC records via bare socket connection.
-
-=head1 SYNOPSIS
-
-./marc_stream_importer.pl /openils/conf/opensrf_core.xml \
- <eg_username> <eg_password> <bib_source> --port <port> --min_servers 2 \
- --max_servers 20 --log_file /openils/var/log/marc_net_importer.log &
-
-Note: this script has to be run in the same directory as oils_header.pl
-
-=head1 DESCRIPTION
-
-This script is a Net::Server::PreFork instance for shoving records into Evergreen from a remote system.
-
-=head2 Configuration
-
-=head3 OCLC Connexion
-
-To use this script with OCLC Connexion, configure the client as follows:
-
-Under Tools -> Options -> Export (tab)
- Create -> Choose Connection -> OK -> Leave translation at "None"
- -> Create -> Create -> choose TCP/IP (internet)
- -> Enter hostname and Port, leave 'Use Telnet Protocol' checked
- -> Create/OK your way out of the dialogs
- Record Characteristics (button) -> Choose 'UTF-8 Unicode' for the Character Set
-
-
-OCLC and Connexion are trademark/service marks of OCLC Online Computer Library Center, Inc.
-
-=head1 CAVEATS
-
-WARNING: This script provides no inherent security layer. Any client that has
-access to the server+port can inject MARC records into the system.
-Use the available options (like allow/deny) in the Net::Server config file
-or via the command line to restrict access as necessary.
-
-=head1 EXAMPLES
-
-./marc_stream_importer.pl /openils/conf/opensrf_core.xml \
- admin open-ils connexion --port 5555 --min_servers 2 \
- --max_servers 20 --log_file /openils/var/log/marc_net_importer.log &
-
-=head1 SEE ALSO
-
-L<Net::Server::PreFork>, L<marc_stream_importer.conf>
-
-=head1 AUTHORS
-
- Bill Erickson <erickson@esilibrary.com>
- Joe Atzberger <jatzberger@esilibrary.com>
-
-
-=cut
use strict; use warnings;
use Net::Server::PreFork;
use MARC::Batch;
use MARC::File::XML;
use MARC::File::USMARC;
+
+use Data::Dumper;
use File::Basename qw/fileparse/;
-use Getopt::Long;
+use Getopt::Long qw(:DEFAULT GetOptionsFromArray);
+use Pod::Usage;
use OpenSRF::Utils::Logger qw/$logger/;
use OpenILS::Utils::Cronscript;
require 'oils_header.pl';
use vars qw/$apputils/;
-# DEFAULTS
-my $bufsize = 4096;
+my $debug = 0;
+
+my %defaults = (
+ 'buffsize=i' => 4096,
+ 'source=s' => 1,
+ 'osrf-config=s' => '/openils/conf/opensrf_core.xml',
+ 'user=s' => 'admin',
+ 'password=s' => '',
+ 'nolockfile' => 1,
+);
+
+$OpenILS::Utils::Cronscript::debug=1 if $debug;
+$Getopt::Long::debug=1 if $debug > 1;
+my $o = OpenILS::Utils::Cronscript->new(\%defaults);
+
+my @script_args = ();
+
+if (grep {$_ eq '--'} @ARGV) {
+ print "Splitting options into groups\n" if $debug;
+ while (@ARGV) {
+ $_ = shift @ARGV;
+ $_ eq '--' and last; # stop at the first --
+ push @script_args, $_;
+ }
+} else {
+ @script_args = @ARGV;
+}
+
+print "Calling MyGetOptions ",
+ (@script_args ? "with options: " . join(' ', @script_args) : 'without options from command line'),
+ "\n" if $debug;
+
+my $real_opts = $o->MyGetOptions(\@script_args);
+# GetOptionsFromArray(\@script_args, \%defaults, %defaults); # similar to
+
+my $bufsize = $real_opts->{buffsize};
+my $bib_source = $real_opts->{source};
+my $osrf_config = $real_opts->{'osrf-config'};
+my $oils_username = $real_opts->{user};
+my $oils_password = $real_opts->{password};
+my $help = $real_opts->{help};
+ $debug += $real_opts->{debug};
+
+foreach (keys %$real_opts) {
+ print("real_opt->{$_} = ", $real_opts->{$_}, "\n") if $real_opts->{debug} or $debug;
+}
my $wait_time = 5;
-my $bib_source = 'connexion';
-my $osrf_config = '/openils/conf/opensrf_core.xml';
-my $oils_username = 'admin';
+my $authtoken = '';
# DEFAULTS for Net::Server
my $filename = fileparse($0, '.pl');
my $conf_file = (-r "$filename.conf") ? "$filename.conf" : undef;
# $conf_file is the Net::Server config for THIS script (not EG), if it exists and is readable
-# $script->session('open-ils.cat') or die "No session created";
-my $oils_password = shift;
-my $authtoken;
+pod2usage(1) if $help;
+unless ($oils_password) {
+ print STDERR "\nERROR: password option required for session login\n\n";
+ # pod2usage(1);
+}
+
+print Dumper($o) if $debug;
+
+if ($debug) {
+ foreach my $ref (qw/bufsize bib_source osrf_config oils_username oils_password help conf_file debug/) {
+ no strict 'refs';
+ printf "%16s => %s\n", $ref, (eval("\$$ref") || '');
+ }
+}
sub warning {
return <<WARNING;
}
print warning();
-# $0 = 'Evergreen MARC Stream Listener';
+print Dumper($real_opts);
+
sub xml_import {
return $apputils->simplereq(
return $index;
}
-sub process_request {
+sub process_request { # The core Net::Server method
my $self = shift;
my $socket = $self->{server}->{client};
my $data = '';
# When that happens, get a new one.
sub new_auth_token {
$authtoken = oils_login($oils_username, $oils_password, 'staff')
- or die "Unable to login to Evergreen";
+ or die "Unable to login to Evergreen as user $oils_username";
return $authtoken;
}
+##### MAIN ######
+
osrf_connect($osrf_config);
new_auth_token();
-__PACKAGE__->run();
+print "Calling Net::Server run ", (@ARGV ? "with options: " . join(' ', @ARGV) : ''), "\n";
+__PACKAGE__->run(conf_file => $conf_file);
+
+__END__
+
+=head1 NAME
+
+marc_stream_importer.pl - Import MARC records via bare socket connection.
+
+=head1 SYNOPSIS
+
+ ./marc_stream_importer.pl /openils/conf/opensrf_core.xml
+ --user=<eg_username> \
+ --pass=<eg_password> --source=<bib_source> \
+ -- --port=<port> --min_servers=2 \
+ --max_servers=20 --log_file=/openils/var/log/marc_net_importer.log &
+
+Note the extra -- to separate options for the script wrapper from options for the
+underlying Net::Server instance.
+Note: this script has to be run in the same directory as oils_header.pl
+
+Run perldoc marc_stream_importer.pl for more documentation.
+
+=head1 DESCRIPTION
+
+This script is a Net::Server::PreFork instance for shoving records into Evergreen from a remote system.
+
+=head2 Configuration
+
+=head3 OCLC Connexion
+
+To use this script with OCLC Connexion, configure the client as follows:
+
+Under Tools -> Options -> Export (tab)
+ Create -> Choose Connection -> OK -> Leave translation at "None"
+ -> Create -> Create -> choose TCP/IP (internet)
+ -> Enter hostname and Port, leave 'Use Telnet Protocol' checked
+ -> Create/OK your way out of the dialogs
+ Record Characteristics (button) -> Choose 'UTF-8 Unicode' for the Character Set
+
+
+OCLC and Connexion are trademark/service marks of OCLC Online Computer Library Center, Inc.
+
+=head1 CAVEATS
+
+WARNING: This script provides no inherent security layer. Any client that has
+access to the server+port can inject MARC records into the system.
+Use the available options (like allow/deny) in the Net::Server config file
+or via the command line to restrict access as necessary.
+
+=head1 EXAMPLES
+
+./marc_stream_importer.pl /openils/conf/opensrf_core.xml \
+ admin open-ils connexion --port 5555 --min_servers 2 \
+ --max_servers 20 --log_file /openils/var/log/marc_net_importer.log &
+
+=head1 SEE ALSO
+
+L<Net::Server::PreFork>, L<marc_stream_importer.conf>
+
+=head1 AUTHORS
+
+ Bill Erickson <erickson@esilibrary.com>
+ Joe Atzberger <jatzberger@esilibrary.com>
+
+
+=cut