# $Header: provisionExecutor.pl 08-aug-2007.05:17:42 saurgarg Exp $
#
# $Header: provisionExecutor.pl 08-aug-2007.05:17:42 saurgarg Exp $
#
# provisionExecutor.pl
# Copyright (c) 2004, 2007, Oracle. All rights reserved.  
#
# Copyright (c) 2004, 2007, Oracle. All rights reserved.  
#
#    NAME
#      provisionExecutor.pl - <one-line expansion of the name>
#
#    DESCRIPTION
#      <short description of component this file declares/defines>
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#    saurgarg   08/08/07 - Further changes after testing
#    saurgarg   08/08/07 - Modifications to pick the correct and available perl
#                          executable
#    ssdas      09/11/06 - Backport gaurgupt_mybug from main
#    ssdas      08/25/06 - edited the chdir() function to allow directive step to CD to staging location 
#    rshetty    07/05/06 - handling the case of directive script file name or stage directory name
#                          containing spaces
#    rshetty    07/05/06 - handling the case of directive script file name or stage directory name
#                          containing spaces
#    ssdas      08/08/06 - Backport rshetty_bug-5191216 from main
#    rattipal   12/08/05 - Backport pshroff_stage_url from main 
#    pshroff    11/07/05 - adding newline before calling directive 
#    rshetty    12/02/05 - making code windows/linux independent 
#    rshetty    12/02/05 - making code windows/linux independent 
#    pshroff    09/25/05 - adding emdroot as cmdline param 
#    pshroff     08/22/05 - to support SUB_Exec Directive Type 
#    pshroff     07/05/05 - adding error handling code=> to exit with failure, 
#                           in case of errors 
#    pshroff     06/30/05 - pshroff_map_shiphome
#    pshroff     06/03/05 - 
#    pshroff     05/26/05 - adding switch to args 
#    pshroff     05/13/05 - removing hardcoded propertynames for cmdLine and dirType
#                             and added coded to set component filename in ENV
#    pshroff     05/12/05 - adding code to chdir to directive path 
#    pshroff     05/06/05 - defined "use strict"  and modifed all var declr to prefix with "my"
#    pshroff     04/26/05 - moving some common methods to provisionCommon.pl
#    pshroff     04/12/05 - modifying as per directive property changes and 
#                           new executor job enhancements   
#    pshroff     11/27/04 - Creation
# 

use Getopt::Long;
use strict;
use File::Basename;

my $ostype = "Linux";
 
if ($^O=~/win/i) {
	$ostype = "Windows";
	#set the path variable
	&mainWindows();
}
else
{
	$ENV{PATH} = "/bin:/usr/bin:/usr/local/bin:/usr/sbin";
	&mainLinux();
}

sub mainLinux()
{
    print "\nThis is Provisioning Executor Script (Linux)\n";
 
	my $FILE_SEP = "\/";
    my %cmdLine = ();

    GetOptions(\%cmdLine,
               "executorpropertyfilename=s",
                "assignmentpath=s",
               "componentpath=s",
               "directivepath=s",
               "directivescriptfilepath=s",
               "propertyfilepath=s",
               "component_binaryfilename=s",
               "cmdline_propertyname=s",
               "directivetype_propertyname=s",
               "standalonedirective=s",
               "perlhome=s", 
               "emdroot=s" );

    if(exists $cmdLine{"perlhome"})
    {
	my $perlhome_env = $cmdLine{"perlhome"};
    	#$ENV{PERL_HOME} = $cmdLine{"perlhome"};

	#first check if the perl exists at the location as specified in the commad line
	if( -e $perlhome_env.$FILE_SEP."perl")
	{
		$ENV{PERL_HOME} = $perlhome_env;
	}
	else
	{
		#check the current perl environment
		$perlhome_env = dirname $^X;
		if( -e $perlhome_env.$FILE_SEP."perl")
		{
			$ENV{PERL_HOME} = $perlhome_env;
		}
		else
		{
			#do nothing at the time being, we are not quite sure if perl is really needed
		}
	}
	
    }
    else
    {
        #check the current perl environment
        my $perlhome_env = dirname $^X;
        if( -e $perlhome_env.$FILE_SEP."perl")
        {
                $ENV{PERL_HOME} = $perlhome_env;
        }
        else
        {
                #do nothing at the time being, we are not quite sure if perl is really needed
        }
    }

    if(exists $cmdLine{"emdroot"})
    {
    $ENV{EMDROOT} = $cmdLine{"emdroot"};
    }

    require "$ENV{EMDROOT}/sysman/admin/scripts/provisioning/provisionCommon.pl";

    my $directiveTypeFile = "provision.properties"; 

    if(exists $cmdLine{"executorpropertyfilename"})
    {
        $directiveTypeFile = $cmdLine{"executorpropertyfilename"};
    }

    my ($assignmentPath, $componentPath, $directivePath, $directiveScriptFilePath);
    if(exists $cmdLine{"assignmentpath"})
    {
        $assignmentPath = $cmdLine{"assignmentpath"};
    }
    if(exists $cmdLine{"componentpath"})
    {
        $componentPath = $cmdLine{"componentpath"};
    }    
    if(exists $cmdLine{"directivepath"})
    {
        $directivePath = $cmdLine{"directivepath"};
    }
    if(exists $cmdLine{"directivescriptfilepath"})
    {
        $directiveScriptFilePath = $cmdLine{"directivescriptfilepath"};
    }

    my ($propertyFilePath, $componentFilename, $cmdLineProperty, $directiveTypeProperty);   

    if(exists $cmdLine{"propertyfilepath"})
    {
        $propertyFilePath = $cmdLine{"propertyfilepath"};
    } 
    if(exists $cmdLine{"component_binaryfilename"})
    {
        $componentFilename = $cmdLine{"component_binaryfilename"};
    }
    if(exists $cmdLine{"cmdline_propertyname"})
    {
        $cmdLineProperty = $cmdLine{"cmdline_propertyname"};
    }
    if(exists $cmdLine{"directivetype_propertyname"})
    {
        $directiveTypeProperty = $cmdLine{"directivetype_propertyname"};
    }

    my $standAloneDirectiveProperty = "no";
    if(exists $cmdLine{"standalonedirective"})
    {
        $standAloneDirectiveProperty = $cmdLine{"standalonedirective"};
    }
	 
    print "\nInput PropertyFilePath is $propertyFilePath\n";
    print "Input directiveScriptFilePath is $directiveScriptFilePath\n";
    print "Input directiveTypeProperty is $directiveTypeProperty\n";

    if ($standAloneDirectiveProperty eq "yes")
    {
           print "\nIts a StandAlone Directive\n";
           if (!$directiveTypeFile || !$directiveTypeProperty || 
                !$directiveScriptFilePath || !$propertyFilePath )
          {
                # return failure
                print "\nOne or more required param missing\n";
                exit 1;
            }
    }
    else
    { 
           print "Input componentPath is $componentPath\n";
           print "Input directivePath is $directivePath\n";
            if (!$directiveTypeFile || !$directiveTypeProperty || !$directiveScriptFilePath 
            || !$componentPath || !$directivePath || !$propertyFilePath )
            {
                # return failure
                print "\nOne or more required param missing\n";
                exit 1;
            }
    }
    print "Input componentFilename is $componentFilename\n"; 

    # SET ALL THE ENV VARIABLES TO BE USED BY THE DIRECTIVE SCTIPTS
    $ENV{COMPONENTPATH} = $componentPath;
    $ENV{DIRECTIVEPATH} = $directivePath;
    $ENV{PROPERTY_FILEPATH} = $propertyFilePath;
    $ENV{COMPONENT_FILENAME} = $componentFilename;
   
    my ($directiveType, $commandLine, $directiveCmdLine, $finalDirectiveCommandLine); 
 
    # get the type of the directive i.er. perl or bash or exec or something else
    $directiveType = get_oraDirectiveProperty($directiveTypeProperty);
    # get the the directive command line specified in the properties file
    $commandLine = get_oraDirectiveProperty($cmdLineProperty);
   
    print "\nDirective Type is $directiveType";

    $directiveCmdLine = "\"".$directiveScriptFilePath . "\""." " . $commandLine;
   
    if($directiveType eq "SUB_Exec")
    {
        system("chmod 555 $directiveScriptFilePath");
        $finalDirectiveCommandLine = $directiveCmdLine;
    } 
    else
    {
   
        # get the directive command line from the properties file
        # this will return the end command line inclduing directivetype also; and so for
        # a perl type; the command line look like "perl test.pl arg1 arg2.."
        
        $finalDirectiveCommandLine = getDirectiveCommandLine( $directiveType, $directiveTypeFile,
                                                                               $directiveCmdLine);
    	
	if($directiveType eq "SUB_Perl")	
	{
		if(! -e $ENV{PERL_HOME}.$FILE_SEP."perl")
    		{
        		#perl has not been set properly... assuming it is available on the path... the following replacement will only take place if the final command has PERL_HOME
        		$finalDirectiveCommandLine =~ s/\$PERL_HOME\/perl/perl/;
    		}
	}
        
    }
    
    # cd to the directory, where directiveScriptFile is placed - todo
    # if directiveScriptFilePath == /a/b/c/a.pl then 
    # we should 'cd' to /a/b/c before executing the directive
    changeDirToDirectiveLinux($directiveScriptFilePath);
   
    # execute the directive script by passing all the params
    print "\nFinal command line to execute is $finalDirectiveCommandLine";
    executeCommandLine($finalDirectiveCommandLine);
}

sub changeDirToDirectiveLinux()
{
    my ($directiveScriptFilePath) = @_;

    my @data_array = split /\// , $directiveScriptFilePath;
    my $a;
    my @new_data;

    for($a=0;$a<=$#data_array-1;$a++)
    {
           my $each_entry=$data_array[$a];
           chomp $each_entry;
           push @new_data, $each_entry;
    }

    my $final_dir_to_cd=join "\/", @new_data;
    print "\nDir to CD is $final_dir_to_cd\n"; 

    chdir($final_dir_to_cd);
}


sub mainWindows()
{
    print "\nThis is Provisioning Executor Script(Windows)\n";
 
    my %cmdLine = ();
	my $FILE_SEP = "\\";

    GetOptions(\%cmdLine,
               "executorpropertyfilename=s",
                "assignmentpath=s",
               "componentpath=s",
               "directivepath=s",
               "directivescriptfilepath=s",
               "propertyfilepath=s",
               "component_binaryfilename=s",
               "cmdline_propertyname=s",
               "directivetype_propertyname=s",
               "standalonedirective=s",
               "perlhome=s", 
               "emdroot=s" );

    if(exists $cmdLine{"perlhome"})
    {
	$cmdLine{"perlhome"} =~ s/\//$FILE_SEP/g;
        my $perlhome_env = $cmdLine{"perlhome"};

        #first check if the perl exists at the location as specified in the commad line
        if( -e $perlhome_env.$FILE_SEP."perl" || -e $perlhome_env.$FILE_SEP."perl.exe")
        {
                $ENV{PERL_HOME} = $perlhome_env;
        }
        else
        {
                #check the current perl environment
                $perlhome_env = dirname $^X;
                if( -e $perlhome_env.$FILE_SEP."perl" || -e $perlhome_env.$FILE_SEP."perl.exe")
                {
                        $ENV{PERL_HOME} = $perlhome_env;
                }
                else
                {
                        #do nothing at the time being, we are not quite sure if perl is really needed
                }
        }
    }
    else
    {
	#check the current perl environment
        my $perlhome_env = dirname $^X;
        if( -e $perlhome_env.$FILE_SEP."perl" || -e $perlhome_env.$FILE_SEP."perl.exe")
        {
                $ENV{PERL_HOME} = $perlhome_env;
        }
        else
        {
                #do nothing at the time being, we are not quite sure if perl is really needed
	}
    }
    
#    if(exists $cmdLine{"perlhome"})
#    {
#		$cmdLine{"perlhome"} =~ s/\//$FILE_SEP/g;
#		$ENV{PERL_HOME} = $cmdLine{"perlhome"};
#    }

    if(exists $cmdLine{"emdroot"})
    {
		$cmdLine{"emdroot"} =~ s/\//$FILE_SEP/g;
		$ENV{EMDROOT} = $cmdLine{"emdroot"};
    }

    require "$ENV{EMDROOT}".$FILE_SEP."sysman".$FILE_SEP."admin".$FILE_SEP."scripts".$FILE_SEP."provisioning".$FILE_SEP."provisionCommon.pl";

    my $directiveTypeFile = "provision.properties"; 

    if(exists $cmdLine{"executorpropertyfilename"})
    {
	$cmdLine{"executorpropertyfilename"} =~ s/\//$FILE_SEP/g;
        $directiveTypeFile = $cmdLine{"executorpropertyfilename"};
    }

    my ($assignmentPath, $componentPath, $directivePath, $directiveScriptFilePath);
    if(exists $cmdLine{"assignmentpath"})
    {
        $assignmentPath = $cmdLine{"assignmentpath"};
    }
    if(exists $cmdLine{"componentpath"})
    {
        $componentPath = $cmdLine{"componentpath"};
    }    
    if(exists $cmdLine{"directivepath"})
    {
        $directivePath = $cmdLine{"directivepath"};
    }
    if(exists $cmdLine{"directivescriptfilepath"})
    {
        $cmdLine{"directivescriptfilepath"} =~ s/\//$FILE_SEP/g;
	$directiveScriptFilePath = $cmdLine{"directivescriptfilepath"};
    }

    my ($propertyFilePath, $componentFilename, $cmdLineProperty, $directiveTypeProperty);   

    if(exists $cmdLine{"propertyfilepath"})
    {
	$cmdLine{"propertyfilepath"} =~ s/\//$FILE_SEP/g;
        $propertyFilePath = $cmdLine{"propertyfilepath"};
    } 
    if(exists $cmdLine{"component_binaryfilename"})
    {
        $componentFilename = $cmdLine{"component_binaryfilename"};
    }
    if(exists $cmdLine{"cmdline_propertyname"})
    {
        $cmdLineProperty = $cmdLine{"cmdline_propertyname"};
    }
    if(exists $cmdLine{"directivetype_propertyname"})
    {
        $directiveTypeProperty = $cmdLine{"directivetype_propertyname"};
    }

    my $standAloneDirectiveProperty = "no";
    if(exists $cmdLine{"standalonedirective"})
    {
        $standAloneDirectiveProperty = $cmdLine{"standalonedirective"};
    }
 
    print "\nInput PropertyFilePath is $propertyFilePath\n";
    print "Input directiveScriptFilePath is $directiveScriptFilePath\n";
    print "Input directiveTypeProperty is $directiveTypeProperty\n";

    if ($standAloneDirectiveProperty eq "yes")
    {
           print "\nIts a StandAlone Directive\n";
           if (!$directiveTypeFile || !$directiveTypeProperty || 
                !$directiveScriptFilePath || !$propertyFilePath )
          {
                # return failure
                print "\nOne or more required param missing\n";
                exit 1;
            }
    }
    else
    { 
           print "Input componentPath is $componentPath\n";
           print "Input directivePath is $directivePath\n";
            if (!$directiveTypeFile || !$directiveTypeProperty || !$directiveScriptFilePath 
            || !$componentPath || !$directivePath || !$propertyFilePath )
            {
                # return failure
                print "\nOne or more required param missing\n";
                exit 1;
            }
    }
    print "Input componentFilename is $componentFilename\n"; 

    # SET ALL THE ENV VARIABLES TO BE USED BY THE DIRECTIVE SCTIPTS
    $ENV{COMPONENTPATH} = $componentPath;
    $ENV{DIRECTIVEPATH} = $directivePath;
    $ENV{PROPERTY_FILEPATH} = $propertyFilePath;
    $ENV{COMPONENT_FILENAME} = $componentFilename;
   
    my ($directiveType, $commandLine, $directiveCmdLine, $finalDirectiveCommandLine); 
 
    # get the type of the directive i.er. perl or bash or exec or something else
    $directiveType = get_oraDirectiveProperty($directiveTypeProperty);
    # get the the directive command line specified in the properties file
    $commandLine = get_oraDirectiveProperty($cmdLineProperty);
   
    print "\nDirective Type is $directiveType";

    $directiveCmdLine = "\"".$directiveScriptFilePath . "\""." " . $commandLine;
   
    if($directiveType eq "SUB_Exec")
    {
		# dont change the perms as of now for windows
        #system("chmod 555 $directiveScriptFilePath");
        $finalDirectiveCommandLine = $directiveCmdLine;
    } 
    else
    {
   
        # get the directive command line from the properties file
        # this will return the end command line inclduing directivetype also; and so for
        # a perl type; the command line look like "perl test.pl arg1 arg2.."
        
        $finalDirectiveCommandLine = getDirectiveCommandLine( $directiveType, $directiveTypeFile,
                                                                               $directiveCmdLine);

	#if it is a perl directive, check for the availability, and replace accordingly
    	if($directiveType eq "SUB_Perl") 
    	{
        	if(-e $ENV{PERL_HOME}.$FILE_SEP."perl" || -e $ENV{PERL_HOME}.$FILE_SEP."perl.exe")
        	{
			$finalDirectiveCommandLine =~ s/\$PERL_HOME\/perl/\%PERL_HOME\%\\perl/;
        	}   
        	else
        	{
			#perl has not been set properly... assuming it is available on the path... the following replacement will only take place if the final command has PERL_HOME
			$finalDirectiveCommandLine =~ s/\$PERL_HOME\/perl/perl/;
        	}
    	}
        
    }
    
    # cd to the directory, where directiveScriptFile is placed - todo
    # if directiveScriptFilePath == /a/b/c/a.pl then 
    # we should 'cd' to /a/b/c before executing the directive
    changeDirToDirectiveWindows($directiveScriptFilePath);
    
    # execute the directive script by passing all the params
    print "\nFinal command line to execute is $finalDirectiveCommandLine";
    executeCommandLine($finalDirectiveCommandLine);
}

sub changeDirToDirectiveWindows()
{
    my ($directiveScriptFilePath) = @_;

	
    my @data_array = split /\\/ , $directiveScriptFilePath;

    my $a;
    my @new_data;

    for($a=0;$a<=$#data_array-1;$a++)
    {
           my $each_entry=$data_array[$a];
           chomp $each_entry;
           push @new_data, $each_entry;
    }

    my $final_dir_to_cd=join "\\", @new_data;

    print "\nDir to CD is $final_dir_to_cd\n"; 

    chdir($final_dir_to_cd);
}

# for each directive type, format the actual 
# command to be excuted
sub getDirectiveCommandLine()
{
    my ($directiveType, $directiveTypeFile, $cmdLine) =  @_;
    my ($commndLine, $output);
    
    # getKeyValue defined in provisionCommon.pl 
    $output = getKeyValue($directiveType, $directiveTypeFile, "=");
    
    if (!$output)
    {
        print "\nInvalid or Unsupported Directive Type=> $directiveType\n";
        exit 1;
    }

    $cmdLine = "$output " . $cmdLine;
    
    return $cmdLine;
};

sub executeCommandLine()
{
    my ($commandLine) = @_;

    print "\n\nThe output of the directive is:\n"; 
    
    system($commandLine);
    exit $? >> 8;    
}



# Finds Property-Tab in the specified Property File
# and replaces Command Line value with the 
# value of that property from the property file
sub findAndReplaceProperties()
{
    my ($cmdLine, $propertyFile) = @_;
    my $output;
    
    my @allwords = split(" ", $cmdLine);
    
    my $word;
    my $letter;
    foreach $word(@allwords)
    {
    $letter = substr($word, 0, 1);
    
    if ($letter eq "#")
    {
        $output = getKeyValue($word, $propertyFile, "=");
        if (!$output)
        {
        print "Could not find the required property-key in the Property File\n";
        exit 1;
        }

        $cmdLine = findAndReplace($cmdLine, $word, $output);
    }
    }
    
    return $cmdLine ;
};


# generic function to find one substring and then replace
# it with the to be replaced substring into the string
# and then return the modifiedstring 

sub findAndReplace()
{
    my ($string, $find, $replace) = @_;

    $string =~ s/$find/$replace/ ;

    return $string;
};
    
