diff scripts/installer/install @ 10:a50cf11e5178

Rewrite LGDataverse completely upgrading to dataverse4.0
author Zoe Hong <zhong@mpiwg-berlin.mpg.de>
date Tue, 08 Sep 2015 17:00:21 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/installer/install	Tue Sep 08 17:00:21 2015 +0200
@@ -0,0 +1,1159 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Getopt::Long;
+use Socket;
+use File::Copy;
+
+my $verbose;
+my $pg_only;
+my $hostname;
+my $gfdir;
+my $mailserver;
+my $yes;
+my $force;
+my $nogfpasswd;
+my ($rez) = GetOptions(
+    #"length=i" => \$length,    # numeric
+    #"file=s"   => \$data,      # string
+    "verbose"      => \$verbose,
+    "pg_only"      => \$pg_only,
+    "hostname=s"   => \$hostname,
+    "gfdir=s"      => \$gfdir,
+    "mailserver=s" => \$mailserver,
+    "y|yes"        => \$yes,
+    "f|force"      => \$force,
+    "nogfpasswd"   => \$nogfpasswd,
+);
+
+my $postgresonly = 0;
+
+my @CONFIG_VARIABLES = (
+    'HOST_DNS_ADDRESS',
+    'GLASSFISH_DIRECTORY',
+    'MAIL_SERVER',
+
+    'POSTGRES_SERVER',
+    'POSTGRES_PORT',
+    'POSTGRES_DATABASE',
+    'POSTGRES_USER',
+    'POSTGRES_PASSWORD',
+
+    'RSERVE_HOST',
+    'RSERVE_PORT',
+    'RSERVE_USER',
+    'RSERVE_PASSWORD'
+
+);
+
+if ($pg_only) {
+#    exit;
+    @CONFIG_VARIABLES =
+      ( 'POSTGRES_SERVER', 'POSTGRES_PORT', 'POSTGRES_DATABASE', 'POSTGRES_USER', 'POSTGRES_PASSWORD' );
+
+    $postgresonly = 1;
+}
+
+# TODO:
+# supply pre-set, default values in a text file;
+# this way we can provide different sets of default
+# values, for the installers intended for different
+# groups of users - local developers vs. "real"
+# dataverse users.
+
+my %CONFIG_DEFAULTS = (
+    'HOST_DNS_ADDRESS',    'localhost',
+    'GLASSFISH_DIRECTORY', '/usr/local/glassfish4',
+    'MAIL_SERVER',         'mail.hmdc.harvard.edu',
+
+    'POSTGRES_SERVER',   'localhost',
+    'POSTGRES_PORT',     5432,
+    'POSTGRES_DATABASE', 'dvndb',
+    'POSTGRES_USER',     'dvnapp',
+    'POSTGRES_PASSWORD', 'secret',
+
+    'RSERVE_HOST',     'localhost',
+    'RSERVE_PORT',     6311,
+    'RSERVE_USER',     'rserve',
+    'RSERVE_PASSWORD', 'rserve'
+
+);
+
+my %CONFIG_PROMPTS = (
+    'HOST_DNS_ADDRESS',    'Internet Address of your host',
+    'GLASSFISH_DIRECTORY', 'Glassfish Directory',
+    'MAIL_SERVER',         'SMTP (mail) server to relay notification messages',
+
+    'POSTGRES_SERVER',   'Postgres Server',
+    'POSTGRES_PORT',     'Postgres Server Port',
+    'POSTGRES_DATABASE', 'Name of the Postgres Database',
+    'POSTGRES_USER',     'Name of the Postgres User',
+    'POSTGRES_PASSWORD', 'Postgres user password',
+
+    'RSERVE_HOST',     'Rserve Server',
+    'RSERVE_PORT',     'Rserve Server Port',
+    'RSERVE_USER',     'Rserve User Name',
+    'RSERVE_PASSWORD', 'Rserve User Password'
+
+);
+
+# Supported Posstgres JDBC drivers:
+# (have to be configured explicitely, so that Perl "taint" (security) mode
+# doesn't get paranoid)
+
+my %POSTGRES_DRIVERS = (
+    #    "8_4", "postgresql-8.3-603.jdbc4.jar",
+    "8_4", "postgresql-8.4-703.jdbc4.jar",
+    "9_0", "postgresql-9.0-802.jdbc4.jar",
+    "9_1", "postgresql-9.1-902.jdbc4.jar",
+    "9_2", "postgresql-9.1-902.jdbc4.jar",
+    "9_3", "postgresql-9.1-902.jdbc4.jar"
+);
+
+# A few preliminary checks:
+
+# user -- must be root:
+
+my $user_real = `who am i`;
+chop $user_real;
+$user_real =~ s/ .*$//;
+
+if ( $< != 0 ) {
+    print STDERR "\nERROR: You must be logged in as root to run the installer.\n\n";
+    exit 1;
+}
+
+# OS:
+
+my $uname_out = `uname -a`;
+
+# hostname:
+
+my $hostname_from_cmdline = `hostname`;
+chop $hostname_from_cmdline;
+
+if ($hostname) {
+    $CONFIG_DEFAULTS{'HOST_DNS_ADDRESS'} = $hostname;
+}
+else {
+    $CONFIG_DEFAULTS{'HOST_DNS_ADDRESS'} = $hostname_from_cmdline;
+}
+
+if ($mailserver) {
+    $CONFIG_DEFAULTS{'MAIL_SERVER'} = $mailserver;
+}
+
+if ($gfdir) {
+    $CONFIG_DEFAULTS{'GLASSFISH_DIRECTORY'} = $gfdir;
+}
+
+print "\nWelcome to the Dataverse installer.\n";
+unless ($postgresonly) {
+    print "You will be guided through the process of setting up a NEW\n";
+    print "instance of the dataverse application\n";
+}
+else {
+    print "You will be guided through the process of configuring the\n";
+    print "LOCAL instance of PostgreSQL database for use by the DVN\n";
+    print "application.\n";
+}
+
+my @uname_tokens = split( " ", $uname_out );
+
+my $WORKING_OS;
+if ( $uname_tokens[0] eq "Darwin" ) {
+    print "\nThis appears to be a MacOS X system; good.\n";
+    # TODO: check the OS version
+
+    $WORKING_OS = "MacOSX";
+}
+elsif ( $uname_tokens[0] eq "Linux" ) {
+    if ( -f "/etc/redhat-release" ) {
+        print "\nThis appears to be a RedHat system; good.\n";
+        $WORKING_OS = "RedHat";
+        # TODO: check the distro version
+    }
+    else {
+        print "\nThis appears to be a non-RedHat Linux system;\n";
+        print "this installation *may* succeed; but we're not making any promises!\n";
+        $WORKING_OS = "Linux";
+    }
+}
+else {
+    print "\nWARNING: This appears to be neither a Linux or MacOS X system!\n";
+    print "This installer script will most likely fail. Please refer to the\n";
+    print "DVN Installers Guide for more information.\n\n";
+
+    $WORKING_OS = "Unknown";
+
+    print "Do you wish to continue?\n [y/n] ";
+
+    my $yesnocont;
+
+    if ($yes) {
+        $yesnocont = "y";
+    }
+    else {
+        print "here";
+        exit;
+        $yesnocont = <>;
+        chop $yesnocont;
+    }
+
+    while ( $yesnocont ne "y" && $yesnocont ne "n" ) {
+        print "Please enter 'y' or 'n'!\n";
+        print "(or ctrl-C to exit the installer)\n";
+        $yesnocont = <>;
+        chop $yesnocont;
+    }
+
+    if ( $yesnocont eq "n" ) {
+        exit 0;
+    }
+
+}
+
+ENTERCONFIG:
+
+print "\n";
+print "Please enter the following configuration values:\n";
+print "(hit [RETURN] to accept the default value)\n";
+print "\n";
+
+for my $ENTRY (@CONFIG_VARIABLES) {
+    print $CONFIG_PROMPTS{$ENTRY} . ": ";
+    print "[" . $CONFIG_DEFAULTS{$ENTRY} . "] ";
+
+    my $user_entry;
+    unless ($yes) {
+        $user_entry = <>;
+        chop $user_entry;
+    }
+
+    if ( $user_entry ne "" ) {
+        $CONFIG_DEFAULTS{$ENTRY} = $user_entry;
+    }
+
+    print "\n";
+}
+
+# CONFIRM VALUES ENTERED:
+
+print "\nOK, please confirm what you've entered:\n\n";
+
+for my $ENTRY (@CONFIG_VARIABLES) {
+    print $CONFIG_PROMPTS{$ENTRY} . ": " . $CONFIG_DEFAULTS{$ENTRY} . "\n";
+}
+
+my $yesno;
+if ($yes) {
+    $yesno = "y";
+}
+else {
+    print "\nIs this correct? [y/n] ";
+    $yesno = <>;
+    chop $yesno;
+}
+
+while ( $yesno ne "y" && $yesno ne "n" ) {
+    print "Please enter 'y' or 'n'!\n";
+    print "(or ctrl-C to exit the installer)\n";
+    $yesno = <>;
+    chop $yesno;
+}
+
+if ( $yesno eq "n" ) {
+    goto ENTERCONFIG;
+}
+
+# VALIDATION/VERIFICATION OF THE CONFIGURATION VALUES:
+# 1. VERIFY MAIL SERVER THEY CONFIGURED:
+
+unless ($postgresonly) {
+
+    my ( $mail_server_iaddr, $mail_server__paddr, $mail_server_proto, $mail_server_status );
+
+    $mail_server_status = 1;
+
+    unless ( $mail_server_iaddr = inet_aton( $CONFIG_DEFAULTS{'MAIL_SERVER'} ) ) {
+        print STDERR "Could not look up $CONFIG_DEFAULTS{'MAIL_SERVER'},\n";
+        print STDERR "the host you specified as your mail server\n";
+        $mail_server_status = 0;
+    }
+
+    if ($mail_server_status) {
+        my $mail_server_paddr = sockaddr_in( 25, $mail_server_iaddr );
+        $mail_server_proto = getprotobyname('tcp');
+
+        unless ( socket( SOCK, PF_INET, SOCK_STREAM, $mail_server_proto )
+            && connect( SOCK, $mail_server_paddr ) )
+        {
+            print STDERR "Could not establish connection to $CONFIG_DEFAULTS{'MAIL_SERVER'},\n";
+            print STDERR "the address you provided for your Mail server.\n";
+            print STDERR "Please select a valid mail server, and try again.\n\n";
+
+            $mail_server_status = 0;
+        }
+
+    }
+
+    close(SOCK);
+
+    unless ($mail_server_status) {
+        goto ENTERCONFIG;
+    }
+}
+
+# 2. CHECK IF THE WAR FILE IS AVAILABLE:
+
+my $WARFILE_LOCATION = "../../target/dataverse-4.0.war";
+
+unless ( -f $WARFILE_LOCATION ) {
+    $WARFILE_LOCATION = "dataverse-4.0.war";
+}
+
+unless ( -f $WARFILE_LOCATION ) {
+    print "\nWARNING: Can't find the project .war file!\n";
+    print "\tAre you running the installer in the right directory?\n";
+    print "\tHave you built the war file?\n";
+    print "\t(if not, build the project and run the installer again)\n";
+
+    exit 0;
+}
+
+# check the working (installer) dir:
+my $cwd;
+chomp( $cwd = `pwd` );
+
+# 2b. CHECK IF THE SQL TEMPLATE IS IN PLACE AND CREATE THE SQL FILE
+
+my $SQL_REFERENCE_DATA     = "reference_data_filtered.sql";
+my $SQL_REFERENCE_TEMPLATE = "../database/reference_data.sql";
+
+unless ( -f $SQL_REFERENCE_TEMPLATE ) {
+    $SQL_REFERENCE_TEMPLATE = "reference_data.sql";
+}
+
+unless ( -f $SQL_REFERENCE_TEMPLATE ) {
+    print "\nWARNING: Can't find .sql data template!\n";
+    print "(are you running the installer in the right directory?)\n";
+
+    exit 0;
+}
+
+open DATATEMPLATEIN, $SQL_REFERENCE_TEMPLATE   || die $@;
+open SQLDATAOUT,     '>' . $SQL_REFERENCE_DATA || die $@;
+
+while (<DATATEMPLATEIN>) {
+    s/dvnapp/$CONFIG_DEFAULTS{'POSTGRES_USER'}/g;
+    print SQLDATAOUT $_;
+}
+
+close DATATEMPLATEIN;
+close SQLDATAOUT;
+
+# 3. CHECK POSTGRES AND JQ AVAILABILITY:
+
+my $pg_local_connection = 0;
+my $psql_exec;
+my $jq_exec = "";
+my $pg_major_version = 0;
+my $pg_minor_version = 0;
+
+my $POSTGRES_SYS_UID;
+if ( $CONFIG_DEFAULTS{'POSTGRES_SERVER'} eq 'localhost' ) {
+    $pg_local_connection = 1;
+
+    # 3a. CHECK FOR USER postgres:
+
+    print "\nChecking system user \"postgres\"... ";
+
+    my $POSTGRES_SYS_NAME = "postgres";
+    $POSTGRES_SYS_UID = ( getpwnam("postgres") )[2];
+
+    unless ($POSTGRES_SYS_UID) {
+        print STDERR "\nERROR: I haven't been able to find user \"postgres\" on the system! Is PostgreSQL installed?\n";
+        print STDERR "(TODO: prompt the user instead to supply an alternative username, if\n";
+        print STDERR "available)\n";
+
+        exit 1;
+    }
+
+    print "OK.\n";
+
+    # 3b. LOCATE THE EXECUTABLE:
+
+    my $sys_path = $ENV{'PATH'};
+    my @sys_path_dirs = split( ":", $sys_path );
+
+    $psql_exec = "";
+
+    for my $sys_path_dir (@sys_path_dirs) {
+        if ( -x $sys_path_dir . "/psql" ) {
+            $psql_exec = $sys_path_dir;
+            last;
+        }
+    }
+
+    for my $sys_path_dir (@sys_path_dirs) {
+        if ( -x $sys_path_dir . "/jq" ) {
+            $jq_exec = $sys_path_dir;
+            last;
+        }
+    }
+    if ( $jq_exec eq "" ) {
+        print STDERR "\nERROR: I haven't been able to find the jq command in your PATH! Please install it from http://stedolan.github.io/jq/\n";
+        exit 1;
+
+    }
+
+    my $psql_major_version = 0;
+    my $psql_minor_version = 0;
+
+    # 3c. IF PSQL WAS FOUND IN THE PATH, CHECK ITS VERSION:
+
+    unless ( $psql_exec eq "" ) {
+        open( PSQLOUT, $psql_exec . "/psql --version|" );
+
+        my $psql_version_line = <PSQLOUT>;
+        chop $psql_version_line;
+        close PSQLOUT;
+
+        my ( $postgresName, $postgresNameLong, $postgresVersion ) = split( " ", $psql_version_line );
+
+        unless ( $postgresName eq "psql" && $postgresVersion =~ /^[0-9][0-9\.]*$/ ) {
+            print STDERR "\nWARNING: Unexpected output from psql command!\n";
+        }
+        else {
+            my (@psql_version_tokens) = split( '\.', $postgresVersion );
+
+            print "\n\nFound Postgres psql command, version $postgresVersion.\n\n";
+
+            $psql_major_version = $psql_version_tokens[0];
+            $psql_minor_version = $psql_version_tokens[1];
+
+            $pg_major_version = $psql_major_version;
+            $pg_minor_version = $psql_minor_version;
+
+        }
+    }
+
+    # a frequent problem with MacOSX is that the copy of psql found in the PATH
+    # belongs to the older version of PostgresQL supplied with the OS, which happens
+    # to be incompatible with the newer builds from the Postgres project; which are
+    # recommended to be used with dataverse. So if this is a MacOSX box, we'll
+    # check what other versions of PG are available, and select the highest version
+    # we can find:
+
+    if ( $WORKING_OS eq "MacOSX" ) {
+        my $macos_pg_major_version = 0;
+        my $macos_pg_minor_version = 0;
+
+        for $macos_pg_minor_version ( "3", "2", "1", "0" ) {
+            if ( -x "/Library/PostgreSQL/9." . $macos_pg_minor_version . "/bin/psql" ) {
+                $macos_pg_major_version = 9;
+                if (   ( $macos_pg_major_version > $psql_major_version )
+                    || ( $macos_pg_minor_version >= $psql_minor_version ) )
+                {
+                    $psql_exec        = "/Library/PostgreSQL/9." . $macos_pg_minor_version . "/bin";
+                    $pg_major_version = $macos_pg_major_version;
+                    $pg_minor_version = $macos_pg_minor_version;
+                }
+                last;
+            }
+        }
+
+        # And if we haven't found an 9.* version of postgresql installed, we'll also check
+        # for version 8.* available:
+
+        if ( $macos_pg_major_version < 9 ) {
+            for $macos_pg_minor_version ( "4", "3" )
+              # TODO:
+              # Do we even want to support postgres 8.3?
+            {
+                if ( -x "/Library/PostgreSQL/8." . $macos_pg_minor_version . "/bin/psql" ) {
+                    $macos_pg_major_version = 8;
+                    if (   $macos_pg_major_version > $psql_major_version
+                        || $macos_pg_minor_version > $psql_minor_version )
+                    {
+                        $psql_exec        = "/Library/PostgreSQL/8." . $macos_pg_minor_version . "/bin";
+                        $pg_major_version = $macos_pg_major_version;
+                        $pg_minor_version = $macos_pg_minor_version;
+                    }
+                    last;
+                }
+            }
+        }
+    }
+
+    if ( $psql_exec eq "" ) {
+        print STDERR "\nERROR: I haven't been able to find the psql command in your PATH!\n";
+        print STDERR "Please make sure PostgresQL is properly installed; if necessary, add\n";
+        print STDERR "the location of psql to the PATH, then try again.\n\n";
+
+        exit 1;
+    }
+
+    if ( $pg_major_version == 0 ) {
+    }
+
+    # 4. CONFIGURE POSTGRES:
+
+    print "\nConfiguring Postgres Database:\n";
+    print "(Using psql version " . $pg_major_version . "." . $pg_minor_version . ")\n";
+
+    $< = $POSTGRES_SYS_UID;
+    $> = $POSTGRES_SYS_UID;
+
+    # 4a. CHECK IF POSTGRES IS RUNNING:
+    print "Checking if a local instance of Postgres is running and accessible...\n";
+
+    # (change to /tmp before executing the command below -
+    # we are trying to do it as user postgres, and it may not have
+    # access to the current, installer directory; the command would still
+    # work, but there would be an error message from the shell init on screen
+    # - potentially confusing)
+
+    chdir("/tmp");
+
+    if ( !system( $psql_exec . "/psql -c 'SELECT * FROM pg_roles' > /dev/null 2>&1" ) ) {
+        print "Yes, it is.\n";
+    }
+    else {
+        print "Nope, I haven't been able to connect to the local instance of PostgresQL.\n";
+        print "daemon. Is postgresql running? \n";
+        print "On a RedHat-like system, you can check the status of the daemon with\n\n";
+        print "   service postgresql status\n\n";
+        print "and, if it's not running, start the daemon with\n\n";
+        print "   service postgresql start\n\n";
+        print "On MacOSX, use Applications -> PostgresQL -> Start Server.\n";
+        print "(or, if there's no \"Start Server\" item in your PostgresQL folder, \n";
+        print "simply restart your MacOSX system!)\n";
+        print "Also, please make sure that the daemon is listening to network connections,\n";
+        print "at least on the localhost interface. (See \"Installing Postgres\" section\n";
+        print "of the installation manual).\n";
+        print "Finally, please make sure that the postgres user can make localhost \n";
+        print "connections without supplying a password. (That's controlled by the \n";
+        print "\"localhost ... ident\" line in pg_hba.conf; again, please consult the \n";
+        print "installation manual).\n";
+
+        exit 1;
+    }
+
+    # 4c. CHECK IF THIS DB ALREADY EXISTS:
+
+    my $psql_command_dbcheck =
+      $psql_exec . "/psql -c \"\" -d " . $CONFIG_DEFAULTS{'POSTGRES_DATABASE'} . ">/dev/null 2>&1";
+    if ($force) {
+        print "WARNING! Database "
+          . $CONFIG_DEFAULTS{'POSTGRES_DATABASE'}
+          . " already exists but --force given... continuing.\n";
+    }
+    elsif ( ( my $exitcode = system($psql_command_dbcheck) ) == 0 ) {
+        $> = 0;
+        $< = 0;
+
+        chdir($cwd);
+
+        print "WARNING! Database " . $CONFIG_DEFAULTS{'POSTGRES_DATABASE'} . " already exists!\n";
+        print "\nPlease note that you can only use this installer to create a blank, \n";
+        print "new and shiny DVN database. I.e., you cannot install on top of an \n";
+        print "existing database. Please enter a different name for the DVN database.\n";
+        print "\nPress any key to continue, or ctrl-C to exit the installer...\n\n";
+
+        system "stty cbreak </dev/tty >/dev/tty 2>&1";
+        my $key = getc(STDIN);
+        system "stty -cbreak </dev/tty >/dev/tty 2>&1";
+        print "\n";
+
+        goto ENTERCONFIG;
+
+    }
+
+    # 4d. CHECK IF THIS USER ALREADY EXISTS:
+
+    my $psql_command_rolecheck =
+      $psql_exec . "/psql -c \"\" -d postgres " . $CONFIG_DEFAULTS{'POSTGRES_USER'} . " >/dev/null 2>&1";
+    if ( ( my $exitcode = system($psql_command_rolecheck) ) == 0 ) {
+        print "User (role) " . $CONFIG_DEFAULTS{'POSTGRES_USER'} . " already exists;\n";
+        print "Proceeding.";
+    }
+    else {
+        # 4e. CREATE DVN DB USER:
+
+        print "\nCreating Postgres user (role) for the DVN:\n";
+
+        open TMPCMD, ">/tmp/pgcmd.$$.tmp";
+
+        # with md5-encrypted password:
+        my $pg_password_md5 =
+          &create_pg_hash( $CONFIG_DEFAULTS{'POSTGRES_USER'}, $CONFIG_DEFAULTS{'POSTGRES_PASSWORD'} );
+        my $sql_command =
+            "CREATE ROLE \""
+          . $CONFIG_DEFAULTS{'POSTGRES_USER'}
+          . "\" PASSWORD 'md5"
+          . $pg_password_md5
+          . "' NOSUPERUSER CREATEDB CREATEROLE INHERIT LOGIN";
+
+        print TMPCMD $sql_command;
+        close TMPCMD;
+
+        my $psql_commandline = $psql_exec . "/psql -f /tmp/pgcmd.$$.tmp >/dev/null 2>&1";
+
+        my $out      = qx($psql_commandline 2>&1);
+        my $exitcode = $?;
+        unless ( $exitcode == 0 ) {
+            print STDERR "Could not create the DVN Postgres user role!\n";
+            print STDERR "(SQL: " . $sql_command . ")\n";
+            print STDERR "(psql exit code: " . $exitcode . ")\n";
+            print STDERR "(STDERR and STDOUT was: " . $out . ")\n";
+            exit 1;
+        }
+
+        unlink "/tmp/pgcmd.$$.tmp";
+        print "done.\n";
+    }
+
+    # 4f. CREATE DVN DB:
+
+    print "\nCreating Postgres database:\n";
+
+    my $psql_command =
+        $psql_exec
+      . "/createdb "
+      . $CONFIG_DEFAULTS{'POSTGRES_DATABASE'}
+      . " --owner="
+      . $CONFIG_DEFAULTS{'POSTGRES_USER'};
+
+    my $out      = qx($psql_command 2>&1);
+    my $exitcode = $?;
+    unless ( $exitcode == 0 ) {
+        print STDERR "Could not create Postgres database for the DVN app!\n";
+        print STDERR "(command: " . $psql_command . ")\n";
+        print STDERR "(psql exit code: " . $exitcode . ")\n";
+        print STDERR "(STDOUT and STDERR: " . $out . ")\n";
+        if ($force) {
+            print STDERR "\n--force called, continuing\n";
+        }
+        else {
+            print STDERR "\naborting the installation (sorry!)\n\n";
+            exit 1;
+        }
+    }
+
+    # Changing back to root UID:
+
+    $> = 0;
+    $< = 0;
+
+    chdir($cwd);
+
+}
+else {
+    if (0) {    # THE LINES BELOW WERE PART OF THE 3.* "DEV." INSTALLER:
+                # DO WE STILL WANT TO MAINTAIN THIS FUNCTIONALITY IN 4.0?
+        print "\nIt is strongly recommended that you use a local PostgresQL server,\n";
+        print "running on localhost, in your development environment!\n\n";
+
+        print "Do you wish to continue?\n [y/n] ";
+
+        my $yesnocont = <>;
+        chop $yesnocont;
+
+        while ( $yesnocont ne "y" && $yesnocont ne "n" ) {
+            print "Please enter 'y' or 'n'!\n";
+            print "(or ctrl-C to exit the installer)\n";
+            $yesnocont = <>;
+            chop $yesnocont;
+        }
+
+        if ( $yesnocont eq "n" ) {
+            print "(aborting the installation)\n" . exit 0;
+        }
+    }
+
+    if ($pg_only) {
+        print "The script must be run in the --pg_only mode ONLY locally,\n";
+        print "i.e., on the server where PostgresQL is running.\n";
+
+        exit 1;
+    }
+
+    print "In order to use a PostgresQL database running on a remote server,\n";
+    print "Please run this installer on that host with the \"--pg_only\" option:\n\n";
+    print "./install --pg_only\n\n";
+
+    print "Press any key to continue the installation process once that has been\n";
+    print "done. Or press ctrl-C to exit the installer.\n\n";
+
+    chdir("/tmp");
+    system "stty cbreak </dev/tty >/dev/tty 2>&1";
+    my $key = getc(STDIN);
+    system "stty -cbreak </dev/tty >/dev/tty 2>&1";
+    print "\n";
+    chdir($cwd);
+
+    # Check if the role and database have been created on the remote server:
+    # -- TODO;
+
+    # Find out what Postgres version is running remotely:
+
+    $pg_major_version = 9;
+    $pg_minor_version = 1;
+
+    print "What version of PostgresQL is installed on the remote server?\n ["
+      . $pg_major_version . "."
+      . $pg_minor_version . "] ";
+
+    my $postgresVersion = <>;
+    chop $postgresVersion;
+
+    while ( $postgresVersion ne "" && !( $postgresVersion =~ /^[0-9]+\.[0-9]+$/ ) ) {
+        print "Please enter valid Postgres version!\n";
+        print "(or ctrl-C to exit the installer)\n";
+        $postgresVersion = <>;
+        chop $postgresVersion;
+    }
+
+    unless ( $postgresVersion eq "" ) {
+        my (@postgres_version_tokens) = split( '\.', $postgresVersion );
+
+        unless ( ( $postgres_version_tokens[0] == 8 && $postgres_version_tokens[1] >= 4 )
+            || ( $postgres_version_tokens[0] >= 9 ) )
+        {
+            print STDERR "\nERROR: PostgresQL version 8.4, or newer, is required!\n";
+            print STDERR "Please make sure the right version of PostgresQL is properly installed\n";
+            print STDERR "on the remote server, then try again.\n";
+
+            exit 1;
+        }
+
+        $pg_major_version = $postgres_version_tokens[0];
+        $pg_minor_version = $postgres_version_tokens[1];
+    }
+
+}
+
+if ($postgresonly) {
+    print "\nOK, done.\n";
+    print "You can now resume the installation on the main DVN host.\n\n";
+
+    exit 0;
+}
+
+# 5. CONFIGURE GLASSFISH
+
+print "\nProceeding with the Glassfish setup.\n";
+print "\nChecking your Glassfish installation...";
+
+my $glassfish_dir = $CONFIG_DEFAULTS{'GLASSFISH_DIRECTORY'};
+
+# 5a. CHECK IF GLASSFISH DIR LOOKS OK:
+
+unless ( -d $glassfish_dir . "/glassfish/domains/domain1" ) {
+    # TODO: need better check than this
+
+    while ( !( -d $glassfish_dir . "/glassfish/domains/domain1" ) ) {
+        print "\nInvalid Glassfish directory " . $glassfish_dir . "!\n";
+        print "Enter the root directory of your Glassfish installation:\n";
+        print "(Or ctrl-C to exit the installer): ";
+
+        $glassfish_dir = <>;
+        chop $glassfish_dir;
+    }
+}
+
+print "OK!\n";
+
+# 5b. DETERMINE HOW MUCH MEMORY TO GIVE TO GLASSFISH AS HEAP:
+
+my $gf_heap_default = "2048m";
+my $sys_mem_total   = 0;
+
+if ( -e "/proc/meminfo" && open MEMINFO, "/proc/meminfo" ) {
+    # Linux
+
+    while ( my $mline = <MEMINFO> ) {
+        if ( $mline =~ /MemTotal:[ \t]*([0-9]*) kB/ ) {
+            $sys_mem_total = $1;
+        }
+    }
+
+    close MEMINFO;
+
+}
+elsif ( -x "/usr/sbin/sysctl" ) {
+    # MacOS X, probably...
+
+    $sys_mem_total = `/usr/sbin/sysctl -n hw.memsize`;
+    chop $sys_mem_total;
+    if ( $sys_mem_total > 0 ) {
+        $sys_mem_total = int( $sys_mem_total / 1024 );
+        # size in kb
+    }
+}
+
+if ( $sys_mem_total > 0 ) {
+    # setting the default heap size limit to 3/8 of the available
+    # amount of memory:
+    $gf_heap_default = ( int( $sys_mem_total / ( 8 / 3 * 1024 ) ) );
+
+    print "\nSetting the heap limit for Glassfish to " . $gf_heap_default . "MB. \n";
+    print "You may need to adjust this setting to better suit \n";
+    print "your system.\n\n";
+
+    #$gf_heap_default .= "m";
+
+}
+else {
+    print "\nCould not determine the amount of memory on your system.\n";
+    print "Setting the heap limit for Glassfish to 2GB. You may need \n";
+    print "to  adjust the value to better suit your system.\n\n";
+}
+
+push @CONFIG_VARIABLES, "DEF_MEM_SIZE";
+$CONFIG_DEFAULTS{"DEF_MEM_SIZE"} = $gf_heap_default;
+
+# TODO:
+# if the system has more than 4GB of memory (I believe), glassfish must
+# be run with the 64 bit flag set explicitly (at least that was the case
+# with the MacOS glassfish build...). Verify, and if still the case,
+# add a check.
+
+print "\nInstalling the Glassfish PostgresQL driver... ";
+
+my $install_driver_jar = "";
+
+$install_driver_jar = $POSTGRES_DRIVERS{ $pg_major_version . "_" . $pg_minor_version };
+
+unless ( $install_driver_jar && -e "pgdriver/" . $install_driver_jar ) {
+    die "Installer could not find POSTGRES JDBC driver for your version of PostgresQL!\n("
+      . $pg_major_version . "."
+      . $pg_minor_version . ")";
+
+}
+
+system( "/bin/cp", "pgdriver/" . $install_driver_jar, $glassfish_dir . "/glassfish/lib" );
+# more diagnostics needed?
+
+print "done!\n";
+
+print "\n*********************\n";
+print "PLEASE NOTE, SOME OF THE ASADMIN COMMANDS ARE GOING TO FAIL,\n";
+print "FOR EXAMPLE, IF A CONFIGURATION SETTING THAT WE ARE TRYING\n";
+print "TO CREATE ALREADY EXISTS; OR IF A JVM OPTION THAT WE ARE\n";
+print "DELETING DOESN'T. THESE \"FAILURES\" ARE NORMAL!\n";
+print "*********************\n\n";
+print "When/if asadmin asks you to \"Enter admin user name\",\n";
+print "it should be safe to hit return and accept the default\n";
+print "(which is \"admin\").\n";
+
+print "\nPress any key to continue...\n\n";
+
+system "stty cbreak </dev/tty >/dev/tty 2>&1";
+unless ($yes) {
+    my $key = getc(STDIN);
+}
+system "stty -cbreak </dev/tty >/dev/tty 2>&1";
+print "\n";
+
+# start domain, if not running:
+
+my $javacheck = `java -version`;
+my $exitcode  = $?;
+unless ( $exitcode == 0 ) {
+    print STDERR "$javacheck\n" if $javacheck;
+    print STDERR "Do you have java installed?\n";
+    exit 1;
+}
+my $DOMAIN = "domain1";
+my $DOMAIN_DOWN =
+  `$CONFIG_DEFAULTS{'GLASSFISH_DIRECTORY'}/bin/asadmin list-domains | grep "$DOMAIN " | grep "not running"`;
+print STDERR $DOMAIN_DOWN . "\n";
+if ($DOMAIN_DOWN) {
+    print "Trying to start domain up...\n";
+    system( $CONFIG_DEFAULTS{'GLASSFISH_DIRECTORY'} . "/bin/asadmin start-domain domain1" );
+}
+else {
+    print "domain appears to be up...\n";
+}
+
+# create asadmin login, so that the user doesn't have to enter
+# the username and password for every asadmin command, if
+# access to :4848 is password-protected:
+
+system( $glassfish_dir. "/bin/asadmin login" );
+
+# NEW: configure glassfish using ASADMIN commands:
+
+my $success = &setup_glassfish();
+
+# CHECK EXIT STATUS, BARF IF SETUP SCRIPT FAILED:
+
+unless ($success) {
+    print "\nERROR! Failed to configure Glassfish domain!\n";
+    print "(see the error messages above - if any)\n";
+    print "Aborting...\n";
+
+    exit 1;
+}
+
+# Additional config files:
+
+my $JHOVE_CONFIG = "../../conf/jhove/jhove.conf";
+
+unless ( -f $JHOVE_CONFIG ) {
+    $JHOVE_CONFIG = "jhove.conf";
+}
+
+unless ( -f $JHOVE_CONFIG ) {
+    print "\nERROR! Configuration files not found in config dir!\n";
+    print "(are you running the installer in the right directory?\n";
+    print "Aborting...\n";
+    exit 1;
+}
+
+print "\nCopying additional configuration files... ";
+
+system( "/bin/cp -Rf " . $JHOVE_CONFIG . " " . $glassfish_dir . "/glassfish/domains/domain1/config" );
+#diagnostics needed!
+
+# install the DVN guides (HTML) into the application docroot:
+# (if the built docs exist?)
+# TODO: add documentation build/installation to the installer.
+#system ( "/bin/cp -Rf doc/guides/* ".$glassfish_dir."/glassfish/domains/domain1/docroot/guides");
+
+print "done!\n";
+
+# check if glassfish is running:
+# TODO.
+
+# 6. DEPLOY APPLICATION:
+
+# 6b. TRY TO (AUTO-)DEPLOY:
+
+unless (
+    (
+        my $exit_code =
+        system( "cp -f " . $WARFILE_LOCATION . " " . $glassfish_dir . "/glassfish/domains/domain1/autodeploy" )
+    ) == 0
+  )
+{
+    print STDERR "Could copy the application into the auto-deploy directory!\n";
+    print STDERR "(exit code: " . $exit_code . ")\n";
+    exit 1;
+}
+
+print "Waiting for the dataverse application to start...\n";
+sleep 60;
+
+# 7. POPULATE DATABASE:
+
+if ($pg_local_connection) {
+    # 7a. POPULATE LOCALLY:
+    print "\nPopulating the database (local PostgresQL instance):\n\n";
+
+    # Copy the SQL file to /tmp, where user postgres will definitely
+    # have read access to it:
+
+    copy( $SQL_REFERENCE_DATA, "/tmp" ) or die "Could not copy $SQL_REFERENCE_DATA to /tmp: $!";
+    unlink( $SQL_REFERENCE_DATA );
+
+    chdir("/tmp");
+    $< = $POSTGRES_SYS_UID;
+    $> = $POSTGRES_SYS_UID;
+    my $psql_command = $psql_exec . "/psql -d $CONFIG_DEFAULTS{'POSTGRES_DATABASE'} -f $SQL_REFERENCE_DATA";
+
+    unless ( ( my $exitcode = system("$psql_command") ) == 0 ) {
+        print STDERR "Could not populate Postgres database for the DVN app!\n";
+        print STDERR "(command: " . $psql_command . ")\n";
+        print STDERR "(psql exit code: " . $exitcode . ")\n";
+        print STDERR "\nYou must populate the database before you can use your new\n";
+        print STDERR "DVN instance. Please consult the installation manual and/or\n";
+        print STDERR "seek support from the DVN team.\n\n";
+        exit 1;
+
+    }
+
+}
+else {
+    # 7b. INSTRUCT THE USER TO POPULATE THE DB ON THE REMOTE SERVER:
+    # NOT SUPPORTED YET -- TODO
+    print "Please copy the file $SQL_REFERENCE_DATA (found in this directory)\n";
+    print "onto the remote server and populate the database manually,\n";
+    print "as user postgres, with the following command:\n\n";
+    print "   psql -d $CONFIG_DEFAULTS{'POSTGRES_DATABASE'} -f $SQL_REFERENCE_DATA\n";
+    print "then start glassfish again on this server with \n\n";
+    print "   " . $glassfish_dir . "/bin/asadmin start-domain domain1\n\n";
+
+#    exit 0;
+
+}
+
+# back to root:
+
+$> = 0;
+$< = 0;
+chdir($cwd);
+print "\nOK, done!\n";
+
+# FIXME: don't just sleep... figure out if the app is up yet.
+print "\n--Sleeping for 3 minutes--\n";
+sleep 180;
+
+# Populate the metadata block field values, create users
+# and dataverses:
+
+unless ( -d "data" && -f "setup-datasetfields.sh" && -f "setup-users.sh" && -f "setup-dvs.sh" && -f "setup-all.sh" ) {
+    chdir("../api");
+}
+
+unless ( -d "data" && -f "setup-datasetfields.sh" && -f "setup-users.sh" && -f "setup-dvs.sh" && -f "setup-builtin-roles.sh" && -f "setup-all.sh" ) {
+    print "\nERROR: Can't find the metadata and user/dataverse setup scripts!\n";
+    print "\tAre you running the installer in the right directory?\n";
+    exit 1;
+}
+
+for my $script ( "setup-all.sh" ) {
+    print "Executing script " . $script . "...\n";
+
+    my $my_hostname = $CONFIG_DEFAULTS{'HOST_DNS_ADDRESS'};
+
+    my $run_script;
+    #if ( $my_hostname ne "localhost" ) {
+    #    system( "sed 's/localhost:8080/$my_hostname/g' < " . $script . " > tmpscript.sh; chmod +x tmpscript.sh" );
+    #    $run_script = "tmpscript.sh";
+    #}
+    #else {
+        $run_script = $script;
+    #}
+
+    unless ( my $exit_code = system( "./" . $run_script ) == 0 ) {
+        print "\nERROR executing script " . $script . "!\n";
+        exit 1;
+    }
+    print "ok!\n";
+}
+
+chdir($cwd);
+
+print "\n\nYou should now have a running DVN instance at\n";
+print "  http://" . $CONFIG_DEFAULTS{'HOST_DNS_ADDRESS'} . "[:YOURPORT]\n";
+
+# (going to skip the Rserve check, for now)
+
+exit 0;
+
+# 9. FINALLY, CHECK IF RSERVE IS RUNNING:
+print "\n\nFinally, checking if Rserve is running and accessible...\n";
+
+unless ( $CONFIG_DEFAULTS{'RSERVE_PORT'} =~ /^[0-9][0-9]*$/ ) {
+    print $CONFIG_DEFAULTS{'RSERVE_HOST'} . " does not look like a valid port number,\n";
+    print "defaulting to 6311.\n\n";
+
+    $CONFIG_DEFAULTS{'RSERVE_PORT'} = 6311;
+}
+
+my ( $rserve_iaddr, $rserve_paddr, $rserve_proto );
+
+unless ( $rserve_iaddr = inet_aton( $CONFIG_DEFAULTS{'RSERVE_HOST'} ) ) {
+    print STDERR "Could not look up $CONFIG_DEFAULTS{'RSERVE_HOST'},\n";
+    print STDERR "the host you specified as your R server.\n";
+    print STDERR "\nDVN can function without a working R server, but\n";
+    print STDERR "much of the functionality concerning running statistics\n";
+    print STDERR "and analysis on quantitative data will not be available.\n";
+    print STDERR "Please consult the Installers guide for more info.\n";
+
+    exit 0;
+}
+
+$rserve_paddr = sockaddr_in( $CONFIG_DEFAULTS{'RSERVE_PORT'}, $rserve_iaddr );
+$rserve_proto = getprotobyname('tcp');
+
+unless ( socket( SOCK, PF_INET, SOCK_STREAM, $rserve_proto )
+    && connect( SOCK, $rserve_paddr ) )
+{
+    print STDERR "Could not establish connection to $CONFIG_DEFAULTS{'RSERVE_HOST'}\n";
+    print STDERR "on port $CONFIG_DEFAULTS{'RSERVE_PORT'}, the address you provided\n";
+    print STDERR "for your R server.\n";
+    print STDERR "DVN can function without a working R server, but\n";
+    print STDERR "much of the functionality concerning running statistics\n";
+    print STDERR "and analysis on quantitative data will not be available.\n";
+    print STDERR "Please consult the \"Installing R\" section in the Installers guide\n";
+    print STDERR "for more info.\n";
+
+    exit 0;
+
+}
+
+close(SOCK);
+print "\nOK!\n";
+
+sub setup_glassfish {
+    my $success = 1;
+    my $failure = 0;
+
+    # We are going to run a standalone shell script with a bunch of asadmin
+    # commands to set up all the glassfish components for the application.
+    # All the parameters must be passed to that script as environmental
+    # variables:
+
+    $ENV{'GLASSFISH_ROOT'}   = $CONFIG_DEFAULTS{'GLASSFISH_DIRECTORY'};
+    $ENV{'GLASSFISH_DOMAIN'} = "domain1";
+    $ENV{'ASADMIN_OPTS'}     = "";
+    $ENV{'MEM_HEAP_SIZE'}    = $CONFIG_DEFAULTS{'DEF_MEM_SIZE'};
+
+    $ENV{'DB_PORT'} = $CONFIG_DEFAULTS{'POSTGRES_PORT'};
+    $ENV{'DB_HOST'} = $CONFIG_DEFAULTS{'POSTGRES_SERVER'};
+    $ENV{'DB_NAME'} = $CONFIG_DEFAULTS{'POSTGRES_DATABASE'};
+    $ENV{'DB_USER'} = $CONFIG_DEFAULTS{'POSTGRES_USER'};
+    $ENV{'DB_PASS'} = $CONFIG_DEFAULTS{'POSTGRES_PASSWORD'};
+
+    $ENV{'RSERVE_HOST'} = $CONFIG_DEFAULTS{'RSERVE_HOST'};
+    $ENV{'RSERVE_PORT'} = $CONFIG_DEFAULTS{'RSERVE_PORT'};
+    $ENV{'RSERVE_USER'} = $CONFIG_DEFAULTS{'RSERVE_USER'};
+    $ENV{'RSERVE_PASS'} = $CONFIG_DEFAULTS{'RSERVE_PASSWORD'};
+
+    $ENV{'HOST_ADDRESS'} = $CONFIG_DEFAULTS{'HOST_DNS_ADDRESS'};
+    $ENV{'SMTP_SERVER'}  = $CONFIG_DEFAULTS{'MAIL_SERVER'};
+    $ENV{'FILES_DIR'} =
+      $CONFIG_DEFAULTS{'GLASSFISH_DIRECTORY'} . "/glassfish/domains/" . $ENV{'GLASSFISH_DOMAIN'} . "/files";
+
+    system("./glassfish-setup.sh");
+
+    if ($?) {
+        return $failure;
+    }
+    return $success;
+}
+
+sub create_pg_hash {
+    my $pg_username = shift @_;
+    my $pg_password = shift @_;
+
+    my $encode_line = $pg_password . $pg_username;
+
+    # for Redhat:
+
+    ##print STDERR "executing /bin/echo -n $encode_line | md5sum\n";
+
+    my $hash;
+    if ( $WORKING_OS eq "MacOSX" ) {
+        $hash = `/bin/echo -n $encode_line | md5`;
+    }
+    else {
+        $hash = `/bin/echo -n $encode_line | md5sum`;
+    }
+
+    chop $hash;
+
+    $hash =~ s/  \-$//;
+
+    if ( ( length($hash) != 32 ) || ( $hash !~ /^[0-9a-f]*$/ ) ) {
+        print STDERR "Failed to generate a MD5-encrypted password hash for the Postgres database.\n";
+        exit 1;
+    }
+
+    return $hash;
+}