# $Header: ecmCommon.pl 13-sep-2006.23:24:30 bkesavan Exp $
#
# Copyright (c) 2001, 2006, Oracle. All rights reserved.  
#
#    DESCRIPTION
#      Common routines for use by ECM scripts
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#     bkesavan   09/13/06 - Add getFileList
#     milshah    11/03/05 - used cwd for getting currentdir 
#     mgoodric   01/31/05 - update for using hostConfigClasspath
#     anusharm   06/18/04 - adding getPropertyValue, bug 3427734
#     xxu        06/25/02 - remove /usr/local/bin/perl
#     mgoodric   06/18/02 - Port perl patch scripts to NT
#     mgoodric   06/08/02 - Use jar for unpacking
#     mgoodric   06/06/02 - Fix PatchAgent job summary results
#     mgoodric   06/05/02 - Fix PatchAgent job
#     vkhizder   02/26/02 - adding STDERR to autoflush
#     jmansur    11/14/01 - Merged jmansur_ecm-011112
#     jmansur    11/13/01 - creation
#

# --- Set up necessary variables for proper running of this environment ---
use strict;
use Cwd;

use File::Find();
use File::Spec();
use File::Glob ':glob';

##*********************************************************************
##                   I N I T I A L I Z A T I O N
##*********************************************************************

BEGIN {

    #used for file and mask in wantName()
    use vars qw ( $S_WANTFILE $S_WANTMASK );
    ($S_WANTFILE, $S_WANTMASK) = ('', '');
}

##*********************************************************************
##                        F U N C T I O N S
##*********************************************************************

#======================================================================
# abort(<operation>,<errorCode>,<errorText>,<logfile>)
#
# Display an error message and exit with error status
#======================================================================
sub abort($$$;$) {
    my ($operation, $errorCode, $errorText, $logfile) = @_;

    if (isEmpty($operation)) {
        $operation = 'command';
    }
    if ($errorCode == 0) {
        $errorCode = 1;
    }

    main::err($errorCode, $errorText, $logfile);
    tee("\n$operation failed\n\n", $logfile);

    exit($errorCode);
}

#======================================================================
# err(<error_number>,<error_text>,<logfile>)
#
# Display a formatted error message
#======================================================================
sub err($$;$) {
    my ($errorCode, $errorText, $logfile) = @_;

    my $text =
          "\n---------- Error Message ----------\n"
        . sprintf("Error: %03d\n", $errorCode)
        . $errorText
        . "\n----------- End Message -----------";

    tee($text, $logfile);
}

#======================================================================
# warning(<warning_number>,<warning_text>,<logfile>)
#
# Display a formatted warning message
#======================================================================
sub warning($$;$) {
    my ($errorCode, $errorText, $logfile) = @_;

    my $text =
          "\n---------- Warning Message ----------\n"
        . sprintf("Warning: %03d\n", $errorCode)
        . $errorText
        . "\n----------- End Message -----------";
    tee($text, $logfile);
}

#======================================================================
# tee(<text>,<logfile>)
#
# Display the text and optionally log it
#======================================================================
sub tee($;$) {
    my ($text, $logfile) = @_;

    printf(STDOUT "%s\n", $text);

    if (!isEmpty($logfile)) {
        open(LOG, ">> $logfile") or return;
        printf(LOG "%s\n", $text);
        close(LOG);
    }
}

#======================================================================
# currentDir()
#
# Return absolute value of working directory
#======================================================================
sub currentDir {
    return cwd();
}

#======================================================================
# onWindows()
#
# Returns: true if running under MS Windows
#======================================================================
sub onWindows {
    return ($^O =~ m/MSWin32/);
}

#======================================================================
# getHostname()
#
# Returns: hostname of local host
#======================================================================
sub getHostname {
    my $hostname = '';
    if (onWindows()) {
        chomp($hostname = `hostname`);
    }
    else {
        chomp($hostname = `/bin/hostname`);
    }

    return $hostname;
}

#======================================================================
# printHeader(<scriptName>,<lastArgIndex>)
#
# Print a banner indicating system and time
#======================================================================
sub printHeader($$) {
    my ($scriptName, $lastArgIndex) = @_;

    my $hostname = getHostname();

    printf(STDOUT "\n");
    printf(STDOUT "Running: %s\n",        $scriptName);
    printf(STDOUT "Argument count: %s\n", $lastArgIndex + 1);
    printf(STDOUT "Perl version: $]\n");
    printf(STDOUT "Hostname: %s\n", $hostname);
    printf(STDOUT "Operating system: $^O\n");
    printf(STDOUT "Time: %s\n", scalar(localtime()));
    printf(STDOUT "\n");
}

#======================================================================
# setOutputAutoflush()
#
# Set STDOUT,STDERR to autoflush
#======================================================================
sub setOutputAutoflush {
    my $outHandle = select(STDOUT);
    $| = 1;    # set OUTPUT_AUTOFLUSH
    select(STDERR);
    $| = 1;                # flush std error as well
    select($outHandle);    #reset handle back to original
}

#======================================================================
# echodo(<cmd>)
#
# Display the command and execute it
#
# Returns: exit status
#======================================================================
sub echodo($) {
    my ($cmd) = @_;

    printf(STDOUT "\n%s\n", $cmd);

    $! = 0;

    return system($cmd);
}

#======================================================================
# getPERL5LIB()
#
# Returns: the equated value of $PERL5LIB
#======================================================================
sub getPERL5LIB {
    my $PERL5LIB = $ENV{'PERL5LIB'};
    if (isEmpty($PERL5LIB)) {
        $PERL5LIB = $ENV{'PERLLIB'};
        if (isEmpty($PERL5LIB)) {
            for (my $i = 0 ; $i < @INC ; $i++) {
                if ($i == 0) {
                    $PERL5LIB = $INC[$i];
                }
                else {
                    $PERL5LIB .= ':' . $INC[$i];
                }
            }
        }
    }

    return $PERL5LIB;
}

#======================================================================
# getPropertyValue(<file>,<property>)
#
# Returns: the value of the property from the specified file
#======================================================================
sub getPropertyValue($$) {
    my ($file, $property) = @_;

    open(FILE, "< $file") or return '';
    my @properties = <FILE>;
    close(FILE);

    my @found = grep(/^$property/, @properties);
    my ($name, $value) = split(/=/, $found[0]);
    chomp($value);

    return $value;
}

#======================================================================
# getAgentClasspath()
#
# Returns: the Java classpath for Agent Java commands
#======================================================================
sub getAgentClasspath() {
    my $ORACLE_HOME = $ENV{'ORACLE_HOME'};
    my $EMDROOT     = $ENV{'EMDROOT'};
    if (isEmpty($EMDROOT)) {
        $EMDROOT = File::Spec->catfile($ORACLE_HOME, 'emagent');
    }
    my $pathSep = onWindows() ? ';' : ':';
    my $classpath = File::Spec->catfile($ORACLE_HOME, 'oui', 'jlib', 'xmlparserv2.jar');

    $classpath .= $pathSep . File::Spec->catfile($ORACLE_HOME, 'oui', 'jlib', 'OraInstaller.jar');
    $classpath .= $pathSep . File::Spec->catfile($ORACLE_HOME, 'oui', 'jlib', 'srvm.jar');
    $classpath .= $pathSep . File::Spec->catfile($ORACLE_HOME, 'oui', 'jlib', 'share.jar');
    $classpath .= $pathSep . File::Spec->catfile($EMDROOT, 'sysman', 'jlib', 'emcoreAgent.jar');
    $classpath .= $pathSep . File::Spec->catfile($EMDROOT, 'sysman', 'jlib', 'emagentRT.jar');
    $classpath .= $pathSep . File::Spec->catfile($EMDROOT, 'sysman', 'jlib', 'emagentSDK.jar');
    $classpath .= $pathSep . File::Spec->catfile($EMDROOT, 'sysman', 'jlib', 'log4j-core.jar');

    return $classpath;
}

#======================================================================
# getJavaCommand(<classpath>,<class>)
#
# Returns: the Java command with a classpath and class
#======================================================================
sub getJavaCommand(;$$) {
    my ($classpath, $class) = @_;

    $classpath = getAgentClasspath() if (isEmpty($classpath));

    # construct Java command
    my $JAVA_HOME = $ENV{'JAVA_HOME'};
    if (isEmpty($JAVA_HOME)) {
        $JAVA_HOME = $ENV{'JRE_HOME'};
    }

    my @systemCommand = (File::Spec->catfile($JAVA_HOME, 'bin', 'java'));
    @systemCommand = (@systemCommand, '-Xmx512M', '-cp', $classpath);
    @systemCommand = (@systemCommand, $class) if (!isEmpty($class));

    return @systemCommand;
}

#======================================================================
# isEmpty(<test>)
#
# Returns: true if value is empty
#======================================================================
sub isEmpty($) {
    my ($test) = @_;    # string to check

    $test = '' if (!defined $test);

    # Windows requires a double-quoted string for passing null parameters

    return ($test eq "") || ($test eq "\"\"") || ($test eq '');
}

#======================================================================
# isEqual(<test>,<value>)
#
# Returns: true if value is identical to test
#======================================================================
sub isEqual($$) {
    my ($test, $value) = @_;

    my $result = 0;

    if ((defined $test) && (defined $value)) {
        $result = ($test eq $value);
    }

    return $result;
}

#======================================================================
# isMatch(<test>,<value>,<count>)
#
# Returns: true if value matches test for at least count characters
#======================================================================
sub isMatch($$;$) {
    my ($test, $value, $count) = @_;

    my $result = 0;

    if ((defined $test) && (defined $value)) {
        $count = length($value) if (isEmpty($count));
        $result = isEqual($test, $value) | isEqual(substr($test, 0, $count), $value);
    }

    return $result;
}

#======================================================================
# isNumeric(<value>)
#
# Returns: true if value is numeric
#======================================================================
sub isNumeric($) {
    my ($value) = @_;

    my $result = 0;

    if (!isEmpty($value)) {
        $result = ($value =~ m/^[0-9]+$/);
    }

    return $result;
}

#======================================================================
# equalsIgnoreCase(<s1>,<s2>)
#
# Returns: result of nocase compare
#======================================================================
sub equalsIgnoreCase($$) {
    my ($s1, $s2) = @_;

    return (lc($s1) eq lc($s2));
}

#======================================================================
# trim(<value>)
#
# Returns: value without leading|trailing space(s)|tab(s)
# NOTE: Do not use prototypes so arrays can be passed.
#======================================================================
sub trim {
    my (@value) = @_;

    for (@value) {
        s/^\s+//;
        s/\s+$//;
    }

    return wantarray ? @value : $value[0];
}

#======================================================================
# fnQuote(<value>)
#
# Returns: a quoted value if spaces are present
#======================================================================
sub fnQuote($) {
    my ($value) = @_;

    if ((defined $value) && ($value =~ m/\s/)) {
        if (onWindows()) {
            $value = '"' . $value . '"';
        }
        else {
            $value = "'" . $value . "'";
        }
    }

    return $value;
}

#======================================================================
# mask()
#
# Helper routine to quote literal (.) in filespecs
#======================================================================
sub mask($) {
    my ($value) = @_;

    if (!isEmpty($value)) {
        $value =~ s/\./\\./g;
    }

    return $value;
}

#======================================================================
# wantName()
#
# Helper routine called by findFile to find matching file
#======================================================================
sub wantName {
    if (isEmpty($S_WANTFILE)) {
        if ($_ =~ m/^${S_WANTMASK}$/) {
            if (onWindows()) {
                $S_WANTFILE = $File::Find::name;
            }
            else {
                $S_WANTFILE = $File::Find::fullname;
            }
        }
    }
}

#======================================================================
# findFile(<path>,<mask>)
#
# Returns: the absolute name of file matching a pattern mask
#======================================================================
sub findFile($$) {
    my ($path, $mask) = @_;

    if (onWindows()) {
        $path =~ s~\\~/~g;    #convert to forward slash (/)
    }

    $S_WANTMASK = $mask;
    $S_WANTFILE = '';

    if (-d $path) {
        if (onWindows()) {
            File::Find::find(\&wantName, $path);
        }
        else {
            File::Find::find(
                {
                    wanted      => \&wantName,
                    follow_fast => 1,
                    follow_skip => 2
                },
                $path
            );
        }
    }

    return $S_WANTFILE;
}

#======================================================================
# getFileList(<pattern>,<flags>)
#
# Returns: all files matching pattern
#======================================================================
sub getFileList($;$) {
    my ($pattern, $flags) = @_;

    if (!defined $flags) {
        $flags = GLOB_CSH;
        $flags |= GLOB_NOCASE if (onWindows());
    }

    my @files = ();

    # glob in Perl 5.8.3 on HP-UX doesn't work ($] == 5.008003)
    if (($^O =~ m/hpux/i) && ($] > 5.008)) {
        chomp(@files = `/usr/bin/ls -1 $pattern 2>/dev/null`);
    }
    else {
        if (onWindows()) {
            $pattern =~ s~/~\\~g    # convert from forward slash (/)
        }
        @files = bsd_glob($pattern, $flags);
    }

    return @files;
}

#======================================================================
# convertToDos(<value>)
#
# Convert forward slashes (/) to back slashes (\)
#======================================================================
sub convertToDos($) {
    my ($value) = @_;

    if (!isEmpty($value) && onWindows()) {
        $value =~ s~/~\\~g;    # convert from forward slash (/)
    }

    return $value;
}

#======================================================================
# convertToUnix(<value>)
#
# Convert back slashes (\) to forward slashes (/)
#======================================================================
sub convertToUnix($) {
    my ($value) = @_;

    if (!isEmpty($value) && onWindows()) {
        $value =~ s~\\~/~g;    # convert to forward slash (/)
    }

    return $value;
}

#======================================================================
# currentDate()
#
# Returns: current date in YYYY-MM-DD HH24:MM:SS SQL format
#======================================================================
sub currentDate {
    my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time());
    my $date = sprintf(
        "%4d-%02d-%02d %02d:%02d:%02d",
        ($year + 1900),
        ($mon + 1),
        $mday, $hour, $min, $sec
    );

    return $date;
}

1;
