1*b1cdbd2cSJim Jagielski#************************************************************** 2*b1cdbd2cSJim Jagielski# 3*b1cdbd2cSJim Jagielski# Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski# or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski# distributed with this work for additional information 6*b1cdbd2cSJim Jagielski# regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski# to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski# "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski# with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski# 11*b1cdbd2cSJim Jagielski# http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski# 13*b1cdbd2cSJim Jagielski# Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski# software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski# KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski# specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski# under the License. 19*b1cdbd2cSJim Jagielski# 20*b1cdbd2cSJim Jagielski#************************************************************** 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski 23*b1cdbd2cSJim Jagielski 24*b1cdbd2cSJim Jagielskipackage installer::windows::feature; 25*b1cdbd2cSJim Jagielski 26*b1cdbd2cSJim Jagielskiuse installer::existence; 27*b1cdbd2cSJim Jagielskiuse installer::exiter; 28*b1cdbd2cSJim Jagielskiuse installer::files; 29*b1cdbd2cSJim Jagielskiuse installer::globals; 30*b1cdbd2cSJim Jagielskiuse installer::sorter; 31*b1cdbd2cSJim Jagielskiuse installer::worker; 32*b1cdbd2cSJim Jagielskiuse installer::windows::idtglobal; 33*b1cdbd2cSJim Jagielskiuse installer::windows::language; 34*b1cdbd2cSJim Jagielski 35*b1cdbd2cSJim Jagielski############################################################## 36*b1cdbd2cSJim Jagielski# Returning the gid for a feature. 37*b1cdbd2cSJim Jagielski# Attention: Maximum length 38*b1cdbd2cSJim Jagielski############################################################## 39*b1cdbd2cSJim Jagielski 40*b1cdbd2cSJim Jagielskisub get_feature_gid 41*b1cdbd2cSJim Jagielski{ 42*b1cdbd2cSJim Jagielski my ($onefeature) = @_; 43*b1cdbd2cSJim Jagielski 44*b1cdbd2cSJim Jagielski my $gid = ""; 45*b1cdbd2cSJim Jagielski 46*b1cdbd2cSJim Jagielski if ( $onefeature->{'gid'} ) { $gid = $onefeature->{'gid'}; } 47*b1cdbd2cSJim Jagielski 48*b1cdbd2cSJim Jagielski # Attention: Maximum feature length is 38! 49*b1cdbd2cSJim Jagielski installer::windows::idtglobal::shorten_feature_gid(\$gid); 50*b1cdbd2cSJim Jagielski 51*b1cdbd2cSJim Jagielski return $gid 52*b1cdbd2cSJim Jagielski} 53*b1cdbd2cSJim Jagielski 54*b1cdbd2cSJim Jagielski############################################################## 55*b1cdbd2cSJim Jagielski# Returning the gid of the parent. 56*b1cdbd2cSJim Jagielski# Attention: Maximum length 57*b1cdbd2cSJim Jagielski############################################################## 58*b1cdbd2cSJim Jagielski 59*b1cdbd2cSJim Jagielskisub get_feature_parent 60*b1cdbd2cSJim Jagielski{ 61*b1cdbd2cSJim Jagielski my ($onefeature) = @_; 62*b1cdbd2cSJim Jagielski 63*b1cdbd2cSJim Jagielski my $parentgid = ""; 64*b1cdbd2cSJim Jagielski 65*b1cdbd2cSJim Jagielski if ( $onefeature->{'ParentID'} ) { $parentgid = $onefeature->{'ParentID'}; } 66*b1cdbd2cSJim Jagielski 67*b1cdbd2cSJim Jagielski # The modules, hanging directly below the root, have to be root modules. 68*b1cdbd2cSJim Jagielski # Only then it is possible to make the "real" root module invisible by 69*b1cdbd2cSJim Jagielski # setting the display to "0". 70*b1cdbd2cSJim Jagielski 71*b1cdbd2cSJim Jagielski if ( $parentgid eq $installer::globals::rootmodulegid ) { $parentgid = ""; } 72*b1cdbd2cSJim Jagielski 73*b1cdbd2cSJim Jagielski # Attention: Maximum feature length is 38! 74*b1cdbd2cSJim Jagielski installer::windows::idtglobal::shorten_feature_gid(\$parentgid); 75*b1cdbd2cSJim Jagielski 76*b1cdbd2cSJim Jagielski return $parentgid 77*b1cdbd2cSJim Jagielski} 78*b1cdbd2cSJim Jagielski 79*b1cdbd2cSJim Jagielski############################################################## 80*b1cdbd2cSJim Jagielski# Returning the display for a feature. 81*b1cdbd2cSJim Jagielski# 0: Feature is not shown 82*b1cdbd2cSJim Jagielski# odd: subfeatures are shown 83*b1cdbd2cSJim Jagielski# even: subfeatures are not shown 84*b1cdbd2cSJim Jagielski############################################################## 85*b1cdbd2cSJim Jagielski 86*b1cdbd2cSJim Jagielskisub get_feature_display 87*b1cdbd2cSJim Jagielski{ 88*b1cdbd2cSJim Jagielski my ($onefeature) = @_; 89*b1cdbd2cSJim Jagielski 90*b1cdbd2cSJim Jagielski my $display; 91*b1cdbd2cSJim Jagielski my $parentid = ""; 92*b1cdbd2cSJim Jagielski 93*b1cdbd2cSJim Jagielski if ( $onefeature->{'ParentID'} ) { $parentid = $onefeature->{'ParentID'}; } 94*b1cdbd2cSJim Jagielski 95*b1cdbd2cSJim Jagielski if ( $parentid eq "" ) 96*b1cdbd2cSJim Jagielski { 97*b1cdbd2cSJim Jagielski $display = "0"; # root module is not visible 98*b1cdbd2cSJim Jagielski } 99*b1cdbd2cSJim Jagielski elsif ( $onefeature->{'gid'} eq "gid_Module_Prg") # program module shows subfeatures 100*b1cdbd2cSJim Jagielski { 101*b1cdbd2cSJim Jagielski $display = "1"; # root module shows subfeatures 102*b1cdbd2cSJim Jagielski } 103*b1cdbd2cSJim Jagielski else 104*b1cdbd2cSJim Jagielski { 105*b1cdbd2cSJim Jagielski $display = "2"; # all other modules do not show subfeatures 106*b1cdbd2cSJim Jagielski } 107*b1cdbd2cSJim Jagielski 108*b1cdbd2cSJim Jagielski # special case: Feature has flag "HIDDEN_ROOT" -> $display is 0 109*b1cdbd2cSJim Jagielski my $styles = ""; 110*b1cdbd2cSJim Jagielski if ( $onefeature->{'Styles'} ) { $styles = $onefeature->{'Styles'}; } 111*b1cdbd2cSJim Jagielski if ( $styles =~ /\bHIDDEN_ROOT\b/ ) { $display = "0"; } 112*b1cdbd2cSJim Jagielski 113*b1cdbd2cSJim Jagielski # Special handling for language modules. Only visible in multilingual installation set 114*b1cdbd2cSJim Jagielski if (( $styles =~ /\bSHOW_MULTILINGUAL_ONLY\b/ ) && ( ! $installer::globals::ismultilingual )) { $display = "0"; } 115*b1cdbd2cSJim Jagielski 116*b1cdbd2cSJim Jagielski # Special handling for c05office. No program module visible. 117*b1cdbd2cSJim Jagielski if (( $onefeature->{'gid'} eq "gid_Module_Prg" ) && ( $installer::globals::product =~ /c05office/i )) { $display = "0"; } 118*b1cdbd2cSJim Jagielski 119*b1cdbd2cSJim Jagielski # making all feature invisible in Language packs! 120*b1cdbd2cSJim Jagielski if ( $installer::globals::languagepack ) { $display = "0"; } 121*b1cdbd2cSJim Jagielski 122*b1cdbd2cSJim Jagielski return $display 123*b1cdbd2cSJim Jagielski} 124*b1cdbd2cSJim Jagielski 125*b1cdbd2cSJim Jagielski############################################################## 126*b1cdbd2cSJim Jagielski# Returning the level for a feature. 127*b1cdbd2cSJim Jagielski############################################################## 128*b1cdbd2cSJim Jagielski 129*b1cdbd2cSJim Jagielskisub get_feature_level 130*b1cdbd2cSJim Jagielski{ 131*b1cdbd2cSJim Jagielski my ($onefeature) = @_; 132*b1cdbd2cSJim Jagielski 133*b1cdbd2cSJim Jagielski my $level = "20"; # the default 134*b1cdbd2cSJim Jagielski 135*b1cdbd2cSJim Jagielski my $localdefault = ""; 136*b1cdbd2cSJim Jagielski 137*b1cdbd2cSJim Jagielski if ( $onefeature->{'Default'} ) { $localdefault = $onefeature->{'Default'}; } 138*b1cdbd2cSJim Jagielski 139*b1cdbd2cSJim Jagielski if ( $localdefault eq "NO" ) # explicitely set Default = "NO" 140*b1cdbd2cSJim Jagielski { 141*b1cdbd2cSJim Jagielski $level = "200"; # deselected in default installation, base is 100 142*b1cdbd2cSJim Jagielski if ( $installer::globals::patch ) { $level = "20"; } 143*b1cdbd2cSJim Jagielski } 144*b1cdbd2cSJim Jagielski 145*b1cdbd2cSJim Jagielski # special handling for Java and Ada 146*b1cdbd2cSJim Jagielski if ( $onefeature->{'Name'} ) 147*b1cdbd2cSJim Jagielski { 148*b1cdbd2cSJim Jagielski if ( $onefeature->{'Name'} =~ /java/i ) { $level = $level + 40; } 149*b1cdbd2cSJim Jagielski } 150*b1cdbd2cSJim Jagielski 151*b1cdbd2cSJim Jagielski # if FeatureLevel is defined in scp, this will be used 152*b1cdbd2cSJim Jagielski 153*b1cdbd2cSJim Jagielski if ( $onefeature->{'FeatureLevel'} ) { $level = $onefeature->{'FeatureLevel'}; } 154*b1cdbd2cSJim Jagielski 155*b1cdbd2cSJim Jagielski return $level 156*b1cdbd2cSJim Jagielski} 157*b1cdbd2cSJim Jagielski 158*b1cdbd2cSJim Jagielski############################################################## 159*b1cdbd2cSJim Jagielski# Returning the directory for a feature. 160*b1cdbd2cSJim Jagielski############################################################## 161*b1cdbd2cSJim Jagielski 162*b1cdbd2cSJim Jagielskisub get_feature_directory 163*b1cdbd2cSJim Jagielski{ 164*b1cdbd2cSJim Jagielski my ($onefeature) = @_; 165*b1cdbd2cSJim Jagielski 166*b1cdbd2cSJim Jagielski my $directory; 167*b1cdbd2cSJim Jagielski 168*b1cdbd2cSJim Jagielski $directory = "INSTALLLOCATION"; 169*b1cdbd2cSJim Jagielski 170*b1cdbd2cSJim Jagielski return $directory 171*b1cdbd2cSJim Jagielski} 172*b1cdbd2cSJim Jagielski 173*b1cdbd2cSJim Jagielski############################################################## 174*b1cdbd2cSJim Jagielski# Returning the directory for a feature. 175*b1cdbd2cSJim Jagielski############################################################## 176*b1cdbd2cSJim Jagielski 177*b1cdbd2cSJim Jagielskisub get_feature_attributes 178*b1cdbd2cSJim Jagielski{ 179*b1cdbd2cSJim Jagielski my ($onefeature) = @_; 180*b1cdbd2cSJim Jagielski 181*b1cdbd2cSJim Jagielski my $attributes; 182*b1cdbd2cSJim Jagielski 183*b1cdbd2cSJim Jagielski # No advertising of features and no leaving on network. 184*b1cdbd2cSJim Jagielski # Feature without parent must not have the "2" 185*b1cdbd2cSJim Jagielski 186*b1cdbd2cSJim Jagielski my $parentgid = ""; 187*b1cdbd2cSJim Jagielski if ( $onefeature->{'ParentID'} ) { $parentgid = $onefeature->{'ParentID'}; } 188*b1cdbd2cSJim Jagielski 189*b1cdbd2cSJim Jagielski if (( $parentgid eq "" ) || ( $parentgid eq $installer::globals::rootmodulegid )) { $attributes = "8"; } 190*b1cdbd2cSJim Jagielski else { $attributes = "10"; } 191*b1cdbd2cSJim Jagielski 192*b1cdbd2cSJim Jagielski return $attributes 193*b1cdbd2cSJim Jagielski} 194*b1cdbd2cSJim Jagielski 195*b1cdbd2cSJim Jagielski################################################################################# 196*b1cdbd2cSJim Jagielski# Replacing one variable in one files 197*b1cdbd2cSJim Jagielski################################################################################# 198*b1cdbd2cSJim Jagielski 199*b1cdbd2cSJim Jagielskisub replace_one_variable 200*b1cdbd2cSJim Jagielski{ 201*b1cdbd2cSJim Jagielski my ($translationfile, $variable, $searchstring) = @_; 202*b1cdbd2cSJim Jagielski 203*b1cdbd2cSJim Jagielski for ( my $i = 0; $i <= $#{$translationfile}; $i++ ) 204*b1cdbd2cSJim Jagielski { 205*b1cdbd2cSJim Jagielski ${$translationfile}[$i] =~ s/\%$searchstring/$variable/g; 206*b1cdbd2cSJim Jagielski } 207*b1cdbd2cSJim Jagielski} 208*b1cdbd2cSJim Jagielski 209*b1cdbd2cSJim Jagielski################################################################################# 210*b1cdbd2cSJim Jagielski# Replacing the variables in the feature names and descriptions 211*b1cdbd2cSJim Jagielski################################################################################# 212*b1cdbd2cSJim Jagielski 213*b1cdbd2cSJim Jagielskisub replace_variables 214*b1cdbd2cSJim Jagielski{ 215*b1cdbd2cSJim Jagielski my ($translationfile, $variableshashref) = @_; 216*b1cdbd2cSJim Jagielski 217*b1cdbd2cSJim Jagielski foreach $key (keys %{$variableshashref}) 218*b1cdbd2cSJim Jagielski { 219*b1cdbd2cSJim Jagielski my $value = $variableshashref->{$key}; 220*b1cdbd2cSJim Jagielski replace_one_variable($translationfile, $value, $key); 221*b1cdbd2cSJim Jagielski } 222*b1cdbd2cSJim Jagielski} 223*b1cdbd2cSJim Jagielski 224*b1cdbd2cSJim Jagielski################################################################################# 225*b1cdbd2cSJim Jagielski# Collecting the feature recursively. 226*b1cdbd2cSJim Jagielski################################################################################# 227*b1cdbd2cSJim Jagielski 228*b1cdbd2cSJim Jagielskisub collect_modules_recursive 229*b1cdbd2cSJim Jagielski{ 230*b1cdbd2cSJim Jagielski my ($modulesref, $parentid, $feature, $directaccess, $directgid, $directparent, $directsortkey, $sorted) = @_; 231*b1cdbd2cSJim Jagielski 232*b1cdbd2cSJim Jagielski my @allchildren = (); 233*b1cdbd2cSJim Jagielski my $childrenexist = 0; 234*b1cdbd2cSJim Jagielski 235*b1cdbd2cSJim Jagielski # Collecting children from Module $parentid 236*b1cdbd2cSJim Jagielski 237*b1cdbd2cSJim Jagielski my $modulegid; 238*b1cdbd2cSJim Jagielski foreach $modulegid ( keys %{$directparent}) 239*b1cdbd2cSJim Jagielski { 240*b1cdbd2cSJim Jagielski if ( $directparent->{$modulegid} eq $parentid ) 241*b1cdbd2cSJim Jagielski { 242*b1cdbd2cSJim Jagielski my %childhash = ( "gid" => "$modulegid", "Sortkey" => "$directsortkey->{$modulegid}"); 243*b1cdbd2cSJim Jagielski push(@allchildren, \%childhash); 244*b1cdbd2cSJim Jagielski $childrenexist = 1; 245*b1cdbd2cSJim Jagielski } 246*b1cdbd2cSJim Jagielski } 247*b1cdbd2cSJim Jagielski 248*b1cdbd2cSJim Jagielski # Sorting children 249*b1cdbd2cSJim Jagielski 250*b1cdbd2cSJim Jagielski if ( $childrenexist ) 251*b1cdbd2cSJim Jagielski { 252*b1cdbd2cSJim Jagielski # Sort children 253*b1cdbd2cSJim Jagielski installer::sorter::sort_array_of_hashes_numerically(\@allchildren, "Sortkey"); 254*b1cdbd2cSJim Jagielski 255*b1cdbd2cSJim Jagielski # Adding children to new array 256*b1cdbd2cSJim Jagielski my $childhashref; 257*b1cdbd2cSJim Jagielski foreach $childhashref ( @allchildren ) 258*b1cdbd2cSJim Jagielski { 259*b1cdbd2cSJim Jagielski my $gid = $childhashref->{'gid'}; 260*b1cdbd2cSJim Jagielski 261*b1cdbd2cSJim Jagielski # Saving all lines, that have this 'gid' 262*b1cdbd2cSJim Jagielski 263*b1cdbd2cSJim Jagielski my $unique; 264*b1cdbd2cSJim Jagielski foreach $unique ( keys %{$directgid} ) 265*b1cdbd2cSJim Jagielski { 266*b1cdbd2cSJim Jagielski if ( $directgid->{$unique} eq $gid ) 267*b1cdbd2cSJim Jagielski { 268*b1cdbd2cSJim Jagielski push(@{$feature}, ${$modulesref}[$directaccess->{$unique}]); 269*b1cdbd2cSJim Jagielski if ( $sorted->{$unique} == 1 ) { installer::exiter::exit_program("ERROR: Sorting feature failed! \"$unique\" already sorted.", "sort_feature"); } 270*b1cdbd2cSJim Jagielski $sorted->{$unique} = 1; 271*b1cdbd2cSJim Jagielski } 272*b1cdbd2cSJim Jagielski } 273*b1cdbd2cSJim Jagielski 274*b1cdbd2cSJim Jagielski collect_modules_recursive($modulesref, $gid, $feature, $directaccess, $directgid, $directparent, $directsortkey, $sorted); 275*b1cdbd2cSJim Jagielski } 276*b1cdbd2cSJim Jagielski } 277*b1cdbd2cSJim Jagielski} 278*b1cdbd2cSJim Jagielski 279*b1cdbd2cSJim Jagielski################################################################################# 280*b1cdbd2cSJim Jagielski# Sorting the feature in specified order. Evaluated is the key "Sortkey", that 281*b1cdbd2cSJim Jagielski# is set in scp2 projects. 282*b1cdbd2cSJim Jagielski# The display order of modules in Windows Installer is dependent from the order 283*b1cdbd2cSJim Jagielski# in the idt file. Therefore the order of the modules array has to be adapted 284*b1cdbd2cSJim Jagielski# to the Sortkey order, before the idt file is created. 285*b1cdbd2cSJim Jagielski################################################################################# 286*b1cdbd2cSJim Jagielski 287*b1cdbd2cSJim Jagielskisub sort_feature 288*b1cdbd2cSJim Jagielski{ 289*b1cdbd2cSJim Jagielski my ($modulesref) = @_; 290*b1cdbd2cSJim Jagielski 291*b1cdbd2cSJim Jagielski my @feature = (); 292*b1cdbd2cSJim Jagielski 293*b1cdbd2cSJim Jagielski my %directaccess = (); 294*b1cdbd2cSJim Jagielski my %directparent = (); 295*b1cdbd2cSJim Jagielski my %directgid = (); 296*b1cdbd2cSJim Jagielski my %directsortkey = (); 297*b1cdbd2cSJim Jagielski my %sorted = (); 298*b1cdbd2cSJim Jagielski 299*b1cdbd2cSJim Jagielski for ( my $i = 0; $i <= $#{$modulesref}; $i++ ) 300*b1cdbd2cSJim Jagielski { 301*b1cdbd2cSJim Jagielski my $onefeature = ${$modulesref}[$i]; 302*b1cdbd2cSJim Jagielski 303*b1cdbd2cSJim Jagielski my $uniquekey = $onefeature->{'uniquekey'}; 304*b1cdbd2cSJim Jagielski my $modulegid = $onefeature->{'gid'}; 305*b1cdbd2cSJim Jagielski 306*b1cdbd2cSJim Jagielski $directaccess{$uniquekey} = $i; 307*b1cdbd2cSJim Jagielski 308*b1cdbd2cSJim Jagielski $directgid{$uniquekey} = $onefeature->{'gid'}; 309*b1cdbd2cSJim Jagielski 310*b1cdbd2cSJim Jagielski # ParentID and Sortkey are not saved for the 'uniquekey', but only for the 'gid' 311*b1cdbd2cSJim Jagielski 312*b1cdbd2cSJim Jagielski if ( $onefeature->{'ParentID'} ) { $directparent{$modulegid} = $onefeature->{'ParentID'}; } 313*b1cdbd2cSJim Jagielski else { $directparent{$modulegid} = ""; } 314*b1cdbd2cSJim Jagielski 315*b1cdbd2cSJim Jagielski if ( $onefeature->{'Sortkey'} ) { $directsortkey{$modulegid} = $onefeature->{'Sortkey'}; } 316*b1cdbd2cSJim Jagielski else { $directsortkey{$modulegid} = "9999"; } 317*b1cdbd2cSJim Jagielski 318*b1cdbd2cSJim Jagielski # Bookkeeping: 319*b1cdbd2cSJim Jagielski $sorted{$uniquekey} = 0; 320*b1cdbd2cSJim Jagielski } 321*b1cdbd2cSJim Jagielski 322*b1cdbd2cSJim Jagielski # Searching all feature recursively, beginning with ParentID = "" 323*b1cdbd2cSJim Jagielski my $parentid = ""; 324*b1cdbd2cSJim Jagielski collect_modules_recursive($modulesref, $parentid, \@feature, \%directaccess, \%directgid, \%directparent, \%directsortkey, \%sorted); 325*b1cdbd2cSJim Jagielski 326*b1cdbd2cSJim Jagielski # Bookkeeping 327*b1cdbd2cSJim Jagielski my $modulekey; 328*b1cdbd2cSJim Jagielski foreach $modulekey ( keys %sorted ) 329*b1cdbd2cSJim Jagielski { 330*b1cdbd2cSJim Jagielski if ( $sorted{$modulekey} == 0 ) 331*b1cdbd2cSJim Jagielski { 332*b1cdbd2cSJim Jagielski $installer::logger::Lang->printf( 333*b1cdbd2cSJim Jagielski "Warning: Module \"%s\" could not be sorted. Added to the end of the module array.\n", 334*b1cdbd2cSJim Jagielski $modulekey); 335*b1cdbd2cSJim Jagielski push(@feature, ${$modulesref}[$directaccess{$modulekey}]); 336*b1cdbd2cSJim Jagielski } 337*b1cdbd2cSJim Jagielski } 338*b1cdbd2cSJim Jagielski 339*b1cdbd2cSJim Jagielski return \@feature; 340*b1cdbd2cSJim Jagielski} 341*b1cdbd2cSJim Jagielski 342*b1cdbd2cSJim Jagielski################################################################################# 343*b1cdbd2cSJim Jagielski# Adding a unique key to the modules array. The gid is not unique for 344*b1cdbd2cSJim Jagielski# multilingual modules. Only the combination from gid and specific language 345*b1cdbd2cSJim Jagielski# is unique. Uniqueness is required for sorting mechanism. 346*b1cdbd2cSJim Jagielski################################################################################# 347*b1cdbd2cSJim Jagielski 348*b1cdbd2cSJim Jagielskisub add_uniquekey 349*b1cdbd2cSJim Jagielski{ 350*b1cdbd2cSJim Jagielski my ( $modulesref ) = @_; 351*b1cdbd2cSJim Jagielski 352*b1cdbd2cSJim Jagielski for ( my $i = 0; $i <= $#{$modulesref}; $i++ ) 353*b1cdbd2cSJim Jagielski { 354*b1cdbd2cSJim Jagielski my $uniquekey = ${$modulesref}[$i]->{'gid'}; 355*b1cdbd2cSJim Jagielski if ( ${$modulesref}[$i]->{'specificlanguage'} ) { $uniquekey = $uniquekey . "_" . ${$modulesref}[$i]->{'specificlanguage'}; } 356*b1cdbd2cSJim Jagielski ${$modulesref}[$i]->{'uniquekey'} = $uniquekey; 357*b1cdbd2cSJim Jagielski } 358*b1cdbd2cSJim Jagielski} 359*b1cdbd2cSJim Jagielski 360*b1cdbd2cSJim Jagielski################################################################################# 361*b1cdbd2cSJim Jagielski# Creating the file Feature.idt dynamically 362*b1cdbd2cSJim Jagielski# Content: 363*b1cdbd2cSJim Jagielski# Feature Feature_Parent Title Description Display Level Directory_ Attributes 364*b1cdbd2cSJim Jagielski################################################################################# 365*b1cdbd2cSJim Jagielski 366*b1cdbd2cSJim Jagielskisub prepare_feature_table ($$$) 367*b1cdbd2cSJim Jagielski{ 368*b1cdbd2cSJim Jagielski my ($modules, $language, $variables) = @_; 369*b1cdbd2cSJim Jagielski 370*b1cdbd2cSJim Jagielski my $features = []; 371*b1cdbd2cSJim Jagielski 372*b1cdbd2cSJim Jagielski foreach my $onefeature (@$modules) 373*b1cdbd2cSJim Jagielski { 374*b1cdbd2cSJim Jagielski # Java and Ada only, if the correct settings are set 375*b1cdbd2cSJim Jagielski my $styles = $onefeature->{'Styles'}; 376*b1cdbd2cSJim Jagielski $styles = "" unless defined $styles; 377*b1cdbd2cSJim Jagielski if (( $styles =~ /\bJAVAMODULE\b/ ) && ( ! ($variables->{'JAVAPRODUCT'} ))) { next; } 378*b1cdbd2cSJim Jagielski 379*b1cdbd2cSJim Jagielski # Controlling the language! 380*b1cdbd2cSJim Jagielski # Only language independent feature or feature with the correct language will be included into the table 381*b1cdbd2cSJim Jagielski 382*b1cdbd2cSJim Jagielski next if $onefeature->{'ismultilingual'} && ($onefeature->{'specificlanguage'} ne $language); 383*b1cdbd2cSJim Jagielski 384*b1cdbd2cSJim Jagielski my $feature_gid =get_feature_gid($onefeature); 385*b1cdbd2cSJim Jagielski 386*b1cdbd2cSJim Jagielski my $feature = { 387*b1cdbd2cSJim Jagielski 'Feature' => $feature_gid, 388*b1cdbd2cSJim Jagielski 'Feature_Parent' => get_feature_parent($onefeature), 389*b1cdbd2cSJim Jagielski 'Title' => $onefeature->{'Name'}, 390*b1cdbd2cSJim Jagielski 'Description' => $onefeature->{'Description'}, 391*b1cdbd2cSJim Jagielski 'Display' => get_feature_display($onefeature), 392*b1cdbd2cSJim Jagielski 'Level' => get_feature_level($onefeature), 393*b1cdbd2cSJim Jagielski 'Directory_' => get_feature_directory($onefeature), 394*b1cdbd2cSJim Jagielski 'Attributes' => get_feature_attributes($onefeature) 395*b1cdbd2cSJim Jagielski }; 396*b1cdbd2cSJim Jagielski push @$features, $feature; 397*b1cdbd2cSJim Jagielski 398*b1cdbd2cSJim Jagielski # collecting all feature in global feature collector (so that properties can be set in property table) 399*b1cdbd2cSJim Jagielski $installer::globals::featurecollector{$feature_gid} = 1; 400*b1cdbd2cSJim Jagielski 401*b1cdbd2cSJim Jagielski # collecting all language feature in feature collector for check of language selection 402*b1cdbd2cSJim Jagielski if (( $styles =~ /\bSHOW_MULTILINGUAL_ONLY\b/ ) && $onefeature->{'ParentID'} ne $installer::globals::rootmodulegid) 403*b1cdbd2cSJim Jagielski { 404*b1cdbd2cSJim Jagielski $installer::globals::multilingual_only_modules{$feature_gid} = 1; 405*b1cdbd2cSJim Jagielski } 406*b1cdbd2cSJim Jagielski 407*b1cdbd2cSJim Jagielski # collecting all application feature in global feature collector for check of application selection 408*b1cdbd2cSJim Jagielski if ( $styles =~ /\bAPPLICATIONMODULE\b/ ) 409*b1cdbd2cSJim Jagielski { 410*b1cdbd2cSJim Jagielski $installer::globals::application_modules{$feature_gid} = 1; 411*b1cdbd2cSJim Jagielski } 412*b1cdbd2cSJim Jagielski } 413*b1cdbd2cSJim Jagielski 414*b1cdbd2cSJim Jagielski return $features; 415*b1cdbd2cSJim Jagielski} 416*b1cdbd2cSJim Jagielski 417*b1cdbd2cSJim Jagielski 418*b1cdbd2cSJim Jagielski 419*b1cdbd2cSJim Jagielski 420*b1cdbd2cSJim Jagielski=head add_missing_features($features) 421*b1cdbd2cSJim Jagielski 422*b1cdbd2cSJim Jagielski When we are building a release, then there may be features missing 423*b1cdbd2cSJim Jagielski that where present in the source release. As missing features 424*b1cdbd2cSJim Jagielski would prevent patches from being created, we add the missing 425*b1cdbd2cSJim Jagielski features. 426*b1cdbd2cSJim Jagielski 427*b1cdbd2cSJim Jagielski The returned feature hash is either identical to the given 428*b1cdbd2cSJim Jagielski $features or is a copy with the missing features added. 429*b1cdbd2cSJim Jagielski 430*b1cdbd2cSJim Jagielski=cut 431*b1cdbd2cSJim Jagielski 432*b1cdbd2cSJim Jagielskisub add_missing_features ($) 433*b1cdbd2cSJim Jagielski{ 434*b1cdbd2cSJim Jagielski my ($features) = @_; 435*b1cdbd2cSJim Jagielski 436*b1cdbd2cSJim Jagielski return $features if ! $installer::globals::is_release; 437*b1cdbd2cSJim Jagielski 438*b1cdbd2cSJim Jagielski # Aquire the feature list of the source release. 439*b1cdbd2cSJim Jagielski my $source_feature_table = $installer::globals::source_msi->GetTable("Feature"); 440*b1cdbd2cSJim Jagielski my $feature_column_index = $source_feature_table->GetColumnIndex("Feature"); 441*b1cdbd2cSJim Jagielski 442*b1cdbd2cSJim Jagielski # Prepare fast lookup of the target features. 443*b1cdbd2cSJim Jagielski my %target_feature_map = map {$_->{'Feature'} => $_} @$features; 444*b1cdbd2cSJim Jagielski 445*b1cdbd2cSJim Jagielski # Find missing features. 446*b1cdbd2cSJim Jagielski my @missing_features = (); 447*b1cdbd2cSJim Jagielski foreach my $source_feature_row (@{$source_feature_table->GetAllRows()}) 448*b1cdbd2cSJim Jagielski { 449*b1cdbd2cSJim Jagielski my $feature_gid = $source_feature_row->GetValue($feature_column_index); 450*b1cdbd2cSJim Jagielski if ( ! defined $target_feature_map{$feature_gid}) 451*b1cdbd2cSJim Jagielski { 452*b1cdbd2cSJim Jagielski push @missing_features, $source_feature_row; 453*b1cdbd2cSJim Jagielski } 454*b1cdbd2cSJim Jagielski } 455*b1cdbd2cSJim Jagielski 456*b1cdbd2cSJim Jagielski # Return when there are no missing features. 457*b1cdbd2cSJim Jagielski return $features if scalar @missing_features==0; 458*b1cdbd2cSJim Jagielski 459*b1cdbd2cSJim Jagielski # Process the missing features. 460*b1cdbd2cSJim Jagielski my $extended_features = [@$features]; 461*b1cdbd2cSJim Jagielski foreach my $missing_feature_row (@missing_features) 462*b1cdbd2cSJim Jagielski { 463*b1cdbd2cSJim Jagielski my %feature = map 464*b1cdbd2cSJim Jagielski {$_ => $missing_feature_row->GetValue($_)} 465*b1cdbd2cSJim Jagielski ('Feature', 'Feature_Parent', 'Title', 'Description', 'Display', 'Level', 'Directory_', 'Attributes'); 466*b1cdbd2cSJim Jagielski push @$extended_features, \%feature; 467*b1cdbd2cSJim Jagielski 468*b1cdbd2cSJim Jagielski $installer::logger::Lang->printf("added missing feature %s\n", $feature->{'Feature'}); 469*b1cdbd2cSJim Jagielski } 470*b1cdbd2cSJim Jagielski return $extended_features; 471*b1cdbd2cSJim Jagielski} 472*b1cdbd2cSJim Jagielski 473*b1cdbd2cSJim Jagielski 474*b1cdbd2cSJim Jagielski 475*b1cdbd2cSJim Jagielski 476*b1cdbd2cSJim Jagielskisub create_feature_table ($$$) 477*b1cdbd2cSJim Jagielski{ 478*b1cdbd2cSJim Jagielski my ($basedir, $language, $features) = @_; 479*b1cdbd2cSJim Jagielski 480*b1cdbd2cSJim Jagielski my @feature_table = (); 481*b1cdbd2cSJim Jagielski installer::windows::idtglobal::write_idt_header(\@feature_table, "feature"); 482*b1cdbd2cSJim Jagielski 483*b1cdbd2cSJim Jagielski foreach my $feature (@$features) 484*b1cdbd2cSJim Jagielski { 485*b1cdbd2cSJim Jagielski my $line = join("\t", 486*b1cdbd2cSJim Jagielski $feature->{'Feature'}, 487*b1cdbd2cSJim Jagielski $feature->{'Feature_Parent'}, 488*b1cdbd2cSJim Jagielski $feature->{'Title'}, 489*b1cdbd2cSJim Jagielski $feature->{'Description'}, 490*b1cdbd2cSJim Jagielski $feature->{'Display'}, 491*b1cdbd2cSJim Jagielski $feature->{'Level'}, 492*b1cdbd2cSJim Jagielski $feature->{'Directory_'}, 493*b1cdbd2cSJim Jagielski $feature->{'Attributes'}) . "\n"; 494*b1cdbd2cSJim Jagielski 495*b1cdbd2cSJim Jagielski push(@feature_table, $line); 496*b1cdbd2cSJim Jagielski } 497*b1cdbd2cSJim Jagielski 498*b1cdbd2cSJim Jagielski my $filename = $basedir . $installer::globals::separator . "Feature.idt" . "." . $language; 499*b1cdbd2cSJim Jagielski installer::files::save_file($filename ,\@feature_table); 500*b1cdbd2cSJim Jagielski $installer::logger::Lang->printf("Created idt file: %s\n", $filename); 501*b1cdbd2cSJim Jagielski} 502*b1cdbd2cSJim Jagielski 503*b1cdbd2cSJim Jagielski1; 504