# This package is responsible for maintaining a list of global parameter # variables, which are shared among all executing packages. Basically, # by default, this consists of maintaining a centralized hash, named # variables, and allowing users to add and delete from this hash at free. package INSTALL::parameter; use INSTALL::common; sub delete { map { delete $variables{$_} } @_; return(1); } sub append { my %hash = @_; my @keys = keys %hash; map { $variables{$_} = $hash{$_} } @keys; return(1); } sub setup { my $i = 0; foreach (@_) { if (/\s*([^\s=]*)\s*=\s*(.*)/) { my $key = $1; my $value = $2; if ($value =~ /\"([^\"]*|\\\"*)\"/) { $variables{$key} = $1; } else { $variables{$key} = $value; } } else { # Values without an equals, are assumed to have no value. $variables{$_} = undef; } } return(1); } #------------------------------------------------------------------------------ # Set up all of the parameters contained in ARGV, into the parameter's # variable listing. Also, detect if a help inquiry has been added and collate # all occurrences into --help=true. #------------------------------------------------------------------------------ BEGIN { setup(@main::ARGV); # Narrow help request to --help if (((exists $variables{"-?"}) || (exists $variables{"-help"}) || (exists $variables{"--help"}))) { delete $variables{"-?"}; delete $variables{"-help"}; $variables{"--help"} = 'true'; } } #------------------------------------------------------------------------------ # OPTIONAL = Specifies the parameter names for optional parameters, in a # non-interactive context. # REQUIRED = Specifies the parameter names for required parameters. If the # parameters are not passed in a non-interactive context, an error # will be generated. # VALUES = Specifies a list of parameter, value pairs, which specify which # values are allowed for a given parameter. If a parameter is not # listed, any value is allowed for that parameter (ie. it is assumed # that error conditions about the value are beyond the scope of # checking here). # # Note(0): A non-interactive context exists whenever an OPTIONAL or REQUIRED # parameter is specified on the command-line. # Note(1): If a non-interactive context exists, the additional parameter # non_interactive=true will be added to the parameter listing, iff # non_interative has not previously been set by the user. # Note(2): Names given in OPTIONAL and REQUIRED may be regular expressions. The # same is true for the keys and values of VALUES. # # Example(1): # my %PARAM_REQUIREMENTS # ( # OPTIONAL => ['jre_path', 'jre_enabled'], # REQUIRED => [], # No required params # VALUES => {} # Any value may be specified for each parameter. # ); # # specifies that the optional jre_path and jre_enabled are optional parameters # that require no specific value checking at this time. # # Example(2): # my %PARAM_REQUIREMENTS # ( # OPTIONAL => [],# No optional params # REQUIRED => ['function'] # VALUES => # { # function => [ # 'add[-_]server', # 'delete[-_]server', # 'change[-_]server', # 'configure[-_]java' # ] # } # ); # # specifies that the required parameter function must have a value which is # one of the values specifies in the VALUES section corresponding to # function. #------------------------------------------------------------------------------ sub verify { my %PARAM_REQUIREMENTS = @_; my ($pOptional,$pRequired,$pValues); if (exists $PARAM_REQUIREMENTS{OPTIONAL}) { $pOptional = $PARAM_REQUIREMENTS{OPTIONAL}; unless (ref($pOptional) == 'ARRAY') { die "Non-array-ref OPTIONAL parameter." } } else { $pOptional = []; } if (exists $PARAM_REQUIREMENTS{REQUIRED}) { $pRequired = $PARAM_REQUIREMENTS{REQUIRED}; unless (ref($pRequired) == 'ARRAY') { die "Non-array-ref REQUIRED parameter." } } else { $pRequired = []; } if (exists $PARAM_REQUIREMENTS{VALUES}) { $pValues = $PARAM_REQUIREMENTS{VALUES}; unless (ref($pValues) == 'HASH') { die "Non-hash-ref VALUES parameter." } } else { $pValues = {}; } # Generic check for non-interactive mode, if not specified by user. unless(exists $variables{non_interactive}) { foreach my $param (@$pOptional,@$pRequired) { if (grep { /^$param$/ } keys %variables) { $variables{non_interactive} = "true"; last; } } } # Assume everything might be a regex, but try exact matches # first for efficiency. if (INSTALL::common::boolean_value($variables{non_interactive})) { # Check whether all required parameters have been passed. foreach my $param (@$pRequired) { # Must use grep, because the param name might be a regex itself. unless ((exists $variables{$param}) || grep { /^$param$/ } keys %variables) { my @allowed_values = "It is marked to except any value."; my $actual_param; if (exists $pValues{$param}) { $actual_param = $param; } else { my @matches = grep { /@^$param$/ || ($param =~ m@^$_$@) } sort { length($a) <=> length($b) } keys %$pValues; if (@matches) { $actual_param = $matches[0]; } } if (defined $actual_param) { @allowed_values = ("It excepts the following values / patterns: ", " ".join(", ", @{$pValues->{$actual_param}})); } return(INSTALL::common::error ("Non-interactive mode requires that a parameter, matching the following,", "be specified:", " $param"), INSTALL::common::note(@allowed_values)); } } # Make sure that the required / optional parameters passed actually # meet the requirements as far as values passed. foreach my $actual_param (keys %variables) { my @matches = grep { $actual_param =~ /^$_$/ } keys %$pValues; if (@matches) { my $param = $matches[0]; my $valid_pattern = join('|',@{$pValues->{$param}}); unless ($variables{$actual_param} =~ /^$valid_pattern$/) { my @allowed_values = ("It excepts the following values / patterns: ", " ".join(", ",@{$pValues->{$param}})); return(INSTALL::common::error ("Non-interactive parameter '$actual_param' does not except ", "the value '$variables{$actual_param}'."), INSTALL::common::note(@allowed_values)); } } } } return (1); } 1;