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