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