xref: /AOO41X/main/solenv/bin/modules/installer/windows/component.pm (revision 24c56ab9f1bd1305754aa2f564704f38ff57627e)
1#**************************************************************
2#
3#  Licensed to the Apache Software Foundation (ASF) under one
4#  or more contributor license agreements.  See the NOTICE file
5#  distributed with this work for additional information
6#  regarding copyright ownership.  The ASF licenses this file
7#  to you under the Apache License, Version 2.0 (the
8#  "License"); you may not use this file except in compliance
9#  with the License.  You may obtain a copy of the License at
10#
11#    http://www.apache.org/licenses/LICENSE-2.0
12#
13#  Unless required by applicable law or agreed to in writing,
14#  software distributed under the License is distributed on an
15#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16#  KIND, either express or implied.  See the License for the
17#  specific language governing permissions and limitations
18#  under the License.
19#
20#**************************************************************
21
22
23
24package installer::windows::component;
25
26use installer::converter;
27use installer::existence;
28use installer::exiter;
29use installer::files;
30use installer::globals;
31use installer::windows::idtglobal;
32use installer::windows::language;
33
34##############################################################
35# Returning a globally unique ID (GUID) for a component
36# If the component is new, a unique guid has to be created.
37# If the component already exists, the guid has to be
38# taken from a list component <-> guid
39# Sample for a guid: {B68FD953-3CEF-4489-8269-8726848056E8}
40##############################################################
41
42sub get_component_guid
43{
44    my ( $componentname, $componentidhashref ) = @_;
45
46    # At this time only a template
47    my $returnvalue = "\{COMPONENTGUID\}";
48
49    # Returning a ComponentID, that is assigned in scp project
50    if ( exists($installer::globals::componentid{$componentname}) )
51    {
52        $returnvalue = "\{" . $installer::globals::componentid{$componentname} . "\}";
53    }
54
55    return $returnvalue;
56}
57
58##############################################################
59# Returning the directory for a file component.
60##############################################################
61
62sub get_file_component_directory
63{
64    my ($componentname, $filesref, $dirref) = @_;
65
66    my ($onefile, $component, $onedir, $hostname, $uniquedir);
67    my $found = 0;
68
69    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
70    {
71        $onefile =  ${$filesref}[$i];
72        $component = $onefile->{'componentname'};
73
74        if ( $component eq $componentname )
75        {
76            $found = 1;
77            last;
78        }
79    }
80
81    if (!($found))
82    {
83        # This component can be ignored, if it exists in a version with extension "_pff" (this was renamed in file::get_sequence_for_file() )
84        my $ignore_this_component = 0;
85        my $origcomponentname = $componentname;
86        my $componentname = $componentname . "_pff";
87
88        for ( my $j = 0; $j <= $#{$filesref}; $j++ )
89        {
90            $onefile =  ${$filesref}[$j];
91            $component = $onefile->{'componentname'};
92
93            if ( $component eq $componentname )
94            {
95                $ignore_this_component = 1;
96                last;
97            }
98        }
99
100        if ( $ignore_this_component ) { return "IGNORE_COMP"; }
101        else { installer::exiter::exit_program("ERROR: Did not find component \"$origcomponentname\" in file collection", "get_file_component_directory"); }
102    }
103
104    my $localstyles = "";
105
106    if ( $onefile->{'Styles'} ) { $localstyles = $onefile->{'Styles'}; }
107
108    if ( $localstyles =~ /\bFONT\b/ )   # special handling for font files
109    {
110        return $installer::globals::fontsfolder;
111    }
112
113    my $destdir = "";
114
115    if ( $onefile->{'Dir'} ) { $destdir = $onefile->{'Dir'}; }
116
117    if ( $destdir =~ /\bPREDEFINED_OSSHELLNEWDIR\b/ )   # special handling for shellnew files
118    {
119        return $installer::globals::templatefolder;
120    }
121
122    my $destination = $onefile->{'destination'};
123
124    installer::pathanalyzer::get_path_from_fullqualifiedname(\$destination);
125
126    $destination =~ s/\Q$installer::globals::separator\E\s*$//;
127
128    # This path has to be defined in the directory collection at "HostName"
129
130    if ($destination eq "")     # files in the installation root
131    {
132        $uniquedir = "INSTALLLOCATION";
133    }
134    else
135    {
136        $found = 0;
137
138        for ( my $i = 0; $i <= $#{$dirref}; $i++ )
139        {
140            $onedir =   ${$dirref}[$i];
141            $hostname = $onedir->{'HostName'};
142
143            if ( $hostname eq $destination )
144            {
145                $found = 1;
146                last;
147            }
148        }
149
150        if (!($found))
151        {
152            installer::exiter::exit_program("ERROR: Did not find destination $destination in directory collection", "get_file_component_directory");
153        }
154
155        $uniquedir = $onedir->{'uniquename'};
156
157        if ( $uniquedir eq $installer::globals::officeinstalldirectory )
158        {
159            $uniquedir = "INSTALLLOCATION";
160        }
161    }
162
163    $onefile->{'uniquedirname'} = $uniquedir;       # saving it in the file collection
164
165    return $uniquedir
166}
167
168##############################################################
169# Returning the directory for a registry component.
170# This cannot be a useful value
171##############################################################
172
173sub get_registry_component_directory
174{
175    my $componentdir = "INSTALLLOCATION";
176
177    return $componentdir;
178}
179
180##############################################################
181# Returning the attributes for a file component.
182# Always 8 in this first try?
183##############################################################
184
185sub get_file_component_attributes
186{
187    my ($componentname, $filesref, $allvariables) = @_;
188
189    my $attributes;
190
191    $attributes = 2;
192
193    # special handling for font files
194
195    my $onefile;
196    my $found = 0;
197
198    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
199    {
200        $onefile =  ${$filesref}[$i];
201        my $component = $onefile->{'componentname'};
202
203        if ( $component eq $componentname )
204        {
205            $found = 1;
206            last;
207        }
208    }
209
210    if (!($found))
211    {
212        installer::exiter::exit_program("ERROR: Did not find component in file collection", "get_file_component_attributes");
213    }
214
215    my $localstyles = "";
216
217    if ( $onefile->{'Styles'} ) { $localstyles = $onefile->{'Styles'}; }
218
219    if ( $localstyles =~ /\bFONT\b/ )
220    {
221        $attributes = 8;    # font files will be deinstalled if the ref count is 0
222    }
223
224    if ( $localstyles =~ /\bASSEMBLY\b/ )
225    {
226        $attributes = 0;    # Assembly files cannot run from source
227    }
228
229    if (( $onefile->{'Dir'} =~ /\bPREDEFINED_OSSHELLNEWDIR\b/ ) || ( $onefile->{'needs_user_registry_key'} ))
230    {
231        $attributes = 4;    # Files in shellnew dir and in non advertised startmenu entries must have user registry key as KeyPath
232    }
233
234    # Adding 256, if this is a 64 bit installation set.
235    if (( $allvariables->{'64BITPRODUCT'} ) && ( $allvariables->{'64BITPRODUCT'} == 1 )) { $attributes = $attributes + 256; }
236
237    return $attributes
238}
239
240##############################################################
241# Returning the attributes for a registry component.
242# Always 4, indicating, the keypath is a defined in
243# table registry
244##############################################################
245
246sub get_registry_component_attributes
247{
248    my ($componentname, $allvariables) = @_;
249
250    my $attributes;
251
252    $attributes = 4;
253
254    # Adding 256, if this is a 64 bit installation set.
255    if (( $allvariables->{'64BITPRODUCT'} ) && ( $allvariables->{'64BITPRODUCT'} == 1 )) { $attributes = $attributes + 256; }
256
257    if ( exists($installer::globals::dontdeletecomponents{$componentname}) ) { $attributes = $attributes + 16; }
258
259    return $attributes
260}
261
262##############################################################
263# Returning the conditions for a component.
264# This is important for language dependent components
265# in multilingual installation sets.
266##############################################################
267
268sub get_file_component_condition
269{
270    my ($componentname, $filesref) = @_;
271
272    my $condition = "";
273
274    if (exists($installer::globals::componentcondition{$componentname}))
275    {
276        $condition = $installer::globals::componentcondition{$componentname};
277    }
278
279    # there can be also tree conditions for multilayer products
280    if (exists($installer::globals::treeconditions{$componentname}))
281    {
282        if ( $condition eq "" )
283        {
284            $condition = $installer::globals::treeconditions{$componentname};
285        }
286        else
287        {
288            $condition = "($condition) And ($installer::globals::treeconditions{$componentname})";
289        }
290    }
291
292    return $condition
293}
294
295##############################################################
296# Returning the conditions for a registry component.
297##############################################################
298
299sub get_component_condition
300{
301    my ($componentname) = @_;
302
303    my $condition;
304
305    $condition = "";    # Always ?
306
307    if (exists($installer::globals::componentcondition{$componentname}))
308    {
309        $condition = $installer::globals::componentcondition{$componentname};
310    }
311
312    return $condition
313}
314
315####################################################################
316# Returning the keypath for a component.
317# This will be the name of the first file/registry, found in the
318# collection $itemsref
319# Attention: This has to be the unique (file)name, not the
320# real filename!
321####################################################################
322
323sub get_component_keypath
324{
325    my ($componentname, $itemsref, $componentidkeypathhashref) = @_;
326
327    my $oneitem;
328    my $found = 0;
329    my $infoline = "";
330
331    for ( my $i = 0; $i <= $#{$itemsref}; $i++ )
332    {
333        $oneitem =  ${$itemsref}[$i];
334        my $component = $oneitem->{'componentname'};
335
336        if ( $component eq $componentname )
337        {
338            $found = 1;
339            last;
340        }
341    }
342
343    if (!($found))
344    {
345        installer::exiter::exit_program("ERROR: Did not find component in file/registry collection, function get_component_keypath", "get_component_keypath");
346    }
347
348    my $keypath = $oneitem->{'uniquename'}; # "uniquename", not "Name"
349
350    # Special handling for updates from existing databases, because KeyPath must not change
351    if (( $installer::globals::updatedatabase ) && ( exists($componentidkeypathhashref->{$componentname}) ))
352    {
353        $keypath = $componentidkeypathhashref->{$componentname};
354        # -> check, if this is a valid key path?!
355        if ( $keypath ne $oneitem->{'uniquename'} )
356        {
357            # Warning: This keypath was changed because of info from old database
358            $infoline = "WARNING: The KeyPath for component \"$componentname\" was changed from \"$oneitem->{'uniquename'}\" to \"$keypath\" because of information from update database";
359            $installer::logger::Lang->print($infoline);
360        }
361    }
362
363    # Special handling for components in PREDEFINED_OSSHELLNEWDIR. These components
364    # need as KeyPath a RegistryItem in HKCU
365    if ( $oneitem->{'userregkeypath'} ) { $keypath = $oneitem->{'userregkeypath'}; }
366
367    # saving it in the file and registry collection
368    $oneitem->{'keypath'} = $keypath;
369
370    return $keypath
371}
372
373###################################################################
374# Creating the file Componen.idt dynamically
375# Content:
376# Component ComponentId Directory_ Attributes Condition KeyPath
377###################################################################
378
379sub create_component_table
380{
381    my ($filesref, $registryref, $dirref, $allfilecomponentsref, $allregistrycomponents, $basedir, $componentidhashref, $componentidkeypathhashref, $allvariables) = @_;
382
383    my @componenttable = ();
384
385    my ($oneline, $infoline);
386
387    installer::windows::idtglobal::write_idt_header(\@componenttable, "component");
388
389    # collect_layer_conditions();
390
391
392    # File components
393
394    for ( my $i = 0; $i <= $#{$allfilecomponentsref}; $i++ )
395    {
396        my %onecomponent = ();
397
398        $onecomponent{'name'} = ${$allfilecomponentsref}[$i];
399        $onecomponent{'guid'} = get_component_guid($onecomponent{'name'}, $componentidhashref);
400        $onecomponent{'directory'} = get_file_component_directory($onecomponent{'name'}, $filesref, $dirref);
401        if ( $onecomponent{'directory'} eq "IGNORE_COMP" ) { next; }
402        $onecomponent{'attributes'} = get_file_component_attributes($onecomponent{'name'}, $filesref, $allvariables);
403        $onecomponent{'condition'} = get_file_component_condition($onecomponent{'name'}, $filesref);
404        $onecomponent{'keypath'} = get_component_keypath($onecomponent{'name'}, $filesref, $componentidkeypathhashref);
405
406        $oneline = $onecomponent{'name'} . "\t" . $onecomponent{'guid'} . "\t" . $onecomponent{'directory'} . "\t"
407                . $onecomponent{'attributes'} . "\t" . $onecomponent{'condition'} . "\t" . $onecomponent{'keypath'} . "\n";
408
409        push(@componenttable, $oneline);
410    }
411
412    # Registry components
413
414    for ( my $i = 0; $i <= $#{$allregistrycomponents}; $i++ )
415    {
416        my %onecomponent = ();
417
418        $onecomponent{'name'} = ${$allregistrycomponents}[$i];
419        $onecomponent{'guid'} = get_component_guid($onecomponent{'name'}, $componentidhashref);
420        $onecomponent{'directory'} = get_registry_component_directory();
421        $onecomponent{'attributes'} = get_registry_component_attributes($onecomponent{'name'}, $allvariables);
422        $onecomponent{'condition'} = get_component_condition($onecomponent{'name'});
423        $onecomponent{'keypath'} = get_component_keypath($onecomponent{'name'}, $registryref, $componentidkeypathhashref);
424
425        $oneline = $onecomponent{'name'} . "\t" . $onecomponent{'guid'} . "\t" . $onecomponent{'directory'} . "\t"
426                . $onecomponent{'attributes'} . "\t" . $onecomponent{'condition'} . "\t" . $onecomponent{'keypath'} . "\n";
427
428        push(@componenttable, $oneline);
429    }
430
431    # Saving the file
432
433    my $componenttablename = $basedir . $installer::globals::separator . "Componen.idt";
434    installer::files::save_file($componenttablename ,\@componenttable);
435    $infoline = "Created idt file: $componenttablename\n";
436    $installer::logger::Lang->print($infoline);
437}
438
439####################################################################################
440# Returning a component for a scp module gid.
441# Pairs are saved in the files collector.
442####################################################################################
443
444sub get_component_name_from_modulegid
445{
446    my ($modulegid, $filesref) = @_;
447
448    my $componentname = "";
449
450    for ( my $i = 0; $i <= $#{$filesref}; $i++ )
451    {
452        my $onefile = ${$filesref}[$i];
453
454        if ( $onefile->{'modules'} )
455        {
456            my $filemodules = $onefile->{'modules'};
457            my $filemodulesarrayref = installer::converter::convert_stringlist_into_array_without_newline(\$filemodules, ",");
458
459            if (installer::existence::exists_in_array($modulegid, $filemodulesarrayref))
460            {
461                $componentname = $onefile->{'componentname'};
462                last;
463            }
464        }
465    }
466
467    return $componentname;
468}
469
470####################################################################################
471# Updating the file Environm.idt dynamically
472# Content:
473# Environment Name Value Component_
474####################################################################################
475
476sub set_component_in_environment_table
477{
478    my ($basedir, $filesref) = @_;
479
480    my $infoline = "";
481
482    my $environmentfilename = $basedir . $installer::globals::separator . "Environm.idt";
483
484    if ( -f $environmentfilename )  # only do something, if file exists
485    {
486        my $environmentfile = installer::files::read_file($environmentfilename);
487
488        for ( my $i = 3; $i <= $#{$environmentfile}; $i++ ) # starting in line 4 of Environm.idt
489        {
490            if ( ${$environmentfile}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ )
491            {
492                my $modulegid = $4; # in Environment table a scp module gid can be used as component replacement
493
494                my $componentname = get_component_name_from_modulegid($modulegid, $filesref);
495
496                if ( $componentname )   # only do something if a component could be found
497                {
498                    $infoline = "Updated Environment table:\n";
499                    $installer::logger::Lang->print($infoline);
500                    $infoline = "Old line: ${$environmentfile}[$i]\n";
501                    $installer::logger::Lang->print($infoline);
502
503                    ${$environmentfile}[$i] =~ s/$modulegid/$componentname/;
504
505                    $infoline = "New line: ${$environmentfile}[$i]\n";
506                    $installer::logger::Lang->print($infoline);
507
508                }
509            }
510        }
511
512        # Saving the file
513
514        installer::files::save_file($environmentfilename ,$environmentfile);
515        $infoline = "Updated idt file: $environmentfilename\n";
516        $installer::logger::Lang->print($infoline);
517
518    }
519}
520
5211;
522