xref: /AOO41X/main/solenv/bin/modules/installer/patch/MsiTable.pm (revision c9b362f6b4b94fc79a706186f718dbfbc8ea72b0)
1*c9b362f6SAndre Fischer#**************************************************************
2*c9b362f6SAndre Fischer#
3*c9b362f6SAndre Fischer#  Licensed to the Apache Software Foundation (ASF) under one
4*c9b362f6SAndre Fischer#  or more contributor license agreements.  See the NOTICE file
5*c9b362f6SAndre Fischer#  distributed with this work for additional information
6*c9b362f6SAndre Fischer#  regarding copyright ownership.  The ASF licenses this file
7*c9b362f6SAndre Fischer#  to you under the Apache License, Version 2.0 (the
8*c9b362f6SAndre Fischer#  "License"); you may not use this file except in compliance
9*c9b362f6SAndre Fischer#  with the License.  You may obtain a copy of the License at
10*c9b362f6SAndre Fischer#
11*c9b362f6SAndre Fischer#    http://www.apache.org/licenses/LICENSE-2.0
12*c9b362f6SAndre Fischer#
13*c9b362f6SAndre Fischer#  Unless required by applicable law or agreed to in writing,
14*c9b362f6SAndre Fischer#  software distributed under the License is distributed on an
15*c9b362f6SAndre Fischer#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*c9b362f6SAndre Fischer#  KIND, either express or implied.  See the License for the
17*c9b362f6SAndre Fischer#  specific language governing permissions and limitations
18*c9b362f6SAndre Fischer#  under the License.
19*c9b362f6SAndre Fischer#
20*c9b362f6SAndre Fischer#**************************************************************
21*c9b362f6SAndre Fischer
22*c9b362f6SAndre Fischerpackage installer::patch::MsiTable;
23*c9b362f6SAndre Fischer
24*c9b362f6SAndre Fischer=head1 NAME
25*c9b362f6SAndre Fischer
26*c9b362f6SAndre Fischer    package installer::patch::MsiTable - Class that represents one table of an Msi file.
27*c9b362f6SAndre Fischer
28*c9b362f6SAndre Fischer=cut
29*c9b362f6SAndre Fischer
30*c9b362f6SAndre Fischeruse installer::patch::MsiRow;
31*c9b362f6SAndre Fischer
32*c9b362f6SAndre Fischeruse strict;
33*c9b362f6SAndre Fischer
34*c9b362f6SAndre Fischer=head new ($class, $filename, $table_name)
35*c9b362f6SAndre Fischer
36*c9b362f6SAndre Fischer    Create a new MsiTable object from the output of a previous
37*c9b362f6SAndre Fischer    msidb.exe run.  The table is named $table_name, its data is read
38*c9b362f6SAndre Fischer    from $filename.
39*c9b362f6SAndre Fischer
40*c9b362f6SAndre Fischer=cut
41*c9b362f6SAndre Fischersub new ($$$)
42*c9b362f6SAndre Fischer{
43*c9b362f6SAndre Fischer    my ($class, $filename, $table_name) = @_;
44*c9b362f6SAndre Fischer
45*c9b362f6SAndre Fischer    my $self = {
46*c9b362f6SAndre Fischer        'name' => $table_name,
47*c9b362f6SAndre Fischer        'is_valid' => 1
48*c9b362f6SAndre Fischer    };
49*c9b362f6SAndre Fischer    bless($self, $class);
50*c9b362f6SAndre Fischer
51*c9b362f6SAndre Fischer    if ( -f $filename)
52*c9b362f6SAndre Fischer    {
53*c9b362f6SAndre Fischer        $self->ReadFile($filename);
54*c9b362f6SAndre Fischer    }
55*c9b362f6SAndre Fischer    return $self;
56*c9b362f6SAndre Fischer}
57*c9b362f6SAndre Fischer
58*c9b362f6SAndre Fischer
59*c9b362f6SAndre Fischer
60*c9b362f6SAndre Fischer
61*c9b362f6SAndre Fischersub IsValid ($)
62*c9b362f6SAndre Fischer{
63*c9b362f6SAndre Fischer    my ($self) = @_;
64*c9b362f6SAndre Fischer    return $self->{'is_valid'};
65*c9b362f6SAndre Fischer}
66*c9b362f6SAndre Fischer
67*c9b362f6SAndre Fischer
68*c9b362f6SAndre Fischer
69*c9b362f6SAndre Fischer
70*c9b362f6SAndre Fischersub Trim ($)
71*c9b362f6SAndre Fischer{
72*c9b362f6SAndre Fischer    my $line = shift;
73*c9b362f6SAndre Fischer
74*c9b362f6SAndre Fischer    $line =~ s/(^\s+|\s+$)//g;
75*c9b362f6SAndre Fischer
76*c9b362f6SAndre Fischer    return $line;
77*c9b362f6SAndre Fischer}
78*c9b362f6SAndre Fischer
79*c9b362f6SAndre Fischer
80*c9b362f6SAndre Fischer
81*c9b362f6SAndre Fischer=head2 ReadFile($self, $filename)
82*c9b362f6SAndre Fischer
83*c9b362f6SAndre Fischer    Read the content of the table from the specified .idt file.
84*c9b362f6SAndre Fischer    For each row a MsiRow object is appended to $self->{'rows'}.
85*c9b362f6SAndre Fischer
86*c9b362f6SAndre Fischer=cut
87*c9b362f6SAndre Fischersub ReadFile ($$)
88*c9b362f6SAndre Fischer{
89*c9b362f6SAndre Fischer    my ($self, $filename) = @_;
90*c9b362f6SAndre Fischer
91*c9b362f6SAndre Fischer    if ( ! (-f $filename && -r $filename))
92*c9b362f6SAndre Fischer    {
93*c9b362f6SAndre Fischer        printf STDERR ("can not open idt file %s for reading\n", $filename);
94*c9b362f6SAndre Fischer        $self->{'is_valid'} = 0;
95*c9b362f6SAndre Fischer        return;
96*c9b362f6SAndre Fischer    }
97*c9b362f6SAndre Fischer
98*c9b362f6SAndre Fischer    open my $in, "<", $filename;
99*c9b362f6SAndre Fischer
100*c9b362f6SAndre Fischer    my $columns = Trim(<$in>);
101*c9b362f6SAndre Fischer    $self->{'columns'} = [split(/\t/, $columns)];
102*c9b362f6SAndre Fischer
103*c9b362f6SAndre Fischer    my $column_specs = Trim(<$in>);
104*c9b362f6SAndre Fischer    $self->{'column_specs'} = [split(/\t/, $column_specs)];
105*c9b362f6SAndre Fischer
106*c9b362f6SAndre Fischer    # Table name, index columns.
107*c9b362f6SAndre Fischer    my $line = Trim(<$in>);
108*c9b362f6SAndre Fischer    my @items = split(/\t/, $line);
109*c9b362f6SAndre Fischer    if (scalar @items == 3)
110*c9b362f6SAndre Fischer    {
111*c9b362f6SAndre Fischer        $self->{'codepage'} = shift @items;
112*c9b362f6SAndre Fischer    }
113*c9b362f6SAndre Fischer    my $table_name = shift @items;
114*c9b362f6SAndre Fischer    if ($table_name ne $self->{'name'})
115*c9b362f6SAndre Fischer    {
116*c9b362f6SAndre Fischer        printf STDERR ("reading wrong table data for table '%s' (got %s)\n", $self->{'name'}, $table_name);
117*c9b362f6SAndre Fischer        $self->{'is_valid'} = 0;
118*c9b362f6SAndre Fischer        return;
119*c9b362f6SAndre Fischer    }
120*c9b362f6SAndre Fischer    $self->{'index_columns'} = [@items];
121*c9b362f6SAndre Fischer    $self->{'index_column_index'} = $self->GetColumnIndex($items[0]);
122*c9b362f6SAndre Fischer
123*c9b362f6SAndre Fischer    my $rows = [];
124*c9b362f6SAndre Fischer    while (<$in>)
125*c9b362f6SAndre Fischer    {
126*c9b362f6SAndre Fischer        # Remove all trailing returns and newlines.  Keep trailing spaces and tabs.
127*c9b362f6SAndre Fischer        s/[\r\n]+$//g;
128*c9b362f6SAndre Fischer
129*c9b362f6SAndre Fischer        my @items = split(/\t/, $_);
130*c9b362f6SAndre Fischer        push @$rows, new installer::patch::MsiRow($self, @items);
131*c9b362f6SAndre Fischer    }
132*c9b362f6SAndre Fischer    $self->{'rows'} = $rows;
133*c9b362f6SAndre Fischer
134*c9b362f6SAndre Fischer    return $self;
135*c9b362f6SAndre Fischer}
136*c9b362f6SAndre Fischer
137*c9b362f6SAndre Fischer
138*c9b362f6SAndre Fischer
139*c9b362f6SAndre Fischer=head2 GetColumnCount($self)
140*c9b362f6SAndre Fischer
141*c9b362f6SAndre Fischer    Return the number of columns in the table.
142*c9b362f6SAndre Fischer
143*c9b362f6SAndre Fischer=cut
144*c9b362f6SAndre Fischersub GetColumnCount ($)
145*c9b362f6SAndre Fischer{
146*c9b362f6SAndre Fischer    my ($self) = @_;
147*c9b362f6SAndre Fischer
148*c9b362f6SAndre Fischer    return scalar @{$self->{'columns'}};
149*c9b362f6SAndre Fischer}
150*c9b362f6SAndre Fischer
151*c9b362f6SAndre Fischer
152*c9b362f6SAndre Fischer
153*c9b362f6SAndre Fischer
154*c9b362f6SAndre Fischer=head2 GetRowCount($self)
155*c9b362f6SAndre Fischer
156*c9b362f6SAndre Fischer    Return the number of rows in the table.
157*c9b362f6SAndre Fischer
158*c9b362f6SAndre Fischer=cut
159*c9b362f6SAndre Fischersub GetRowCount ($)
160*c9b362f6SAndre Fischer{
161*c9b362f6SAndre Fischer    my ($self) = @_;
162*c9b362f6SAndre Fischer
163*c9b362f6SAndre Fischer    return scalar @{$self->{'rows'}};
164*c9b362f6SAndre Fischer}
165*c9b362f6SAndre Fischer
166*c9b362f6SAndre Fischer
167*c9b362f6SAndre Fischer
168*c9b362f6SAndre Fischer
169*c9b362f6SAndre Fischer=head2 GetColumnIndx($self, $column_name)
170*c9b362f6SAndre Fischer
171*c9b362f6SAndre Fischer    Return the 0 based index of the column named $column_name.  Use
172*c9b362f6SAndre Fischer    this to speed up (slightly) access to column values when accessing
173*c9b362f6SAndre Fischer    many or all rows of a table.
174*c9b362f6SAndre Fischer
175*c9b362f6SAndre Fischer=cut
176*c9b362f6SAndre Fischersub GetColumnIndex ($$)
177*c9b362f6SAndre Fischer{
178*c9b362f6SAndre Fischer    my ($self, $column_name) = @_;
179*c9b362f6SAndre Fischer
180*c9b362f6SAndre Fischer    my $index = 0;
181*c9b362f6SAndre Fischer    foreach my $name (@{$self->{'columns'}})
182*c9b362f6SAndre Fischer    {
183*c9b362f6SAndre Fischer        if ($name eq $column_name)
184*c9b362f6SAndre Fischer        {
185*c9b362f6SAndre Fischer            return $index;
186*c9b362f6SAndre Fischer        }
187*c9b362f6SAndre Fischer        ++$index;
188*c9b362f6SAndre Fischer    }
189*c9b362f6SAndre Fischer
190*c9b362f6SAndre Fischer    printf STDERR ("did not find column %s in %s\n", $column_name, join(" and ", @{$self->{'columns'}}));
191*c9b362f6SAndre Fischer    return -1;
192*c9b362f6SAndre Fischer}
193*c9b362f6SAndre Fischer
194*c9b362f6SAndre Fischer
195*c9b362f6SAndre Fischer
196*c9b362f6SAndre Fischer
197*c9b362f6SAndre Fischer=head2 GetValue($self, $selector_column, $selector_column_value, $value_column)
198*c9b362f6SAndre Fischer
199*c9b362f6SAndre Fischer    Find the row in which the $selector_column has value
200*c9b362f6SAndre Fischer    $selector_column_value and return its value in the $value_column.
201*c9b362f6SAndre Fischer
202*c9b362f6SAndre Fischer=cut
203*c9b362f6SAndre Fischer
204*c9b362f6SAndre Fischersub GetValue ($$$$)
205*c9b362f6SAndre Fischer{
206*c9b362f6SAndre Fischer    my ($self, $selector_column, $selector_column_value, $value_column) = @_;
207*c9b362f6SAndre Fischer
208*c9b362f6SAndre Fischer    my $row = $self->GetRow($selector_column, $selector_column_value);
209*c9b362f6SAndre Fischer    if (defined $row)
210*c9b362f6SAndre Fischer    {
211*c9b362f6SAndre Fischer        return $row->GetValue($value_column);
212*c9b362f6SAndre Fischer    }
213*c9b362f6SAndre Fischer    else
214*c9b362f6SAndre Fischer    {
215*c9b362f6SAndre Fischer        return undef;
216*c9b362f6SAndre Fischer    }
217*c9b362f6SAndre Fischer}
218*c9b362f6SAndre Fischer
219*c9b362f6SAndre Fischer
220*c9b362f6SAndre Fischer
221*c9b362f6SAndre Fischer
222*c9b362f6SAndre Fischer=head2 GetRow($self, $column, $value)
223*c9b362f6SAndre Fischer
224*c9b362f6SAndre Fischer    Return the (first) row which has $value in $column.
225*c9b362f6SAndre Fischer
226*c9b362f6SAndre Fischer=cut
227*c9b362f6SAndre Fischersub GetRow ($$$)
228*c9b362f6SAndre Fischer{
229*c9b362f6SAndre Fischer    my ($self, $column, $value) = @_;
230*c9b362f6SAndre Fischer
231*c9b362f6SAndre Fischer    my $column_index = $self->GetColumnIndex($column);
232*c9b362f6SAndre Fischer    if ($column_index<0)
233*c9b362f6SAndre Fischer    {
234*c9b362f6SAndre Fischer        printf STDERR "ERROR: unknown column $column in table $self->{'name'}\n";
235*c9b362f6SAndre Fischer        return undef;
236*c9b362f6SAndre Fischer    }
237*c9b362f6SAndre Fischer
238*c9b362f6SAndre Fischer    foreach my $row (@{$self->{'rows'}})
239*c9b362f6SAndre Fischer    {
240*c9b362f6SAndre Fischer        if ($row->GetValue($column_index) eq $value)
241*c9b362f6SAndre Fischer        {
242*c9b362f6SAndre Fischer            return $row;
243*c9b362f6SAndre Fischer        }
244*c9b362f6SAndre Fischer    }
245*c9b362f6SAndre Fischer
246*c9b362f6SAndre Fischer    printf STDERR ("ERROR: did not find row for %s->%s in %s\n",
247*c9b362f6SAndre Fischer        $column,
248*c9b362f6SAndre Fischer        $value,
249*c9b362f6SAndre Fischer        table $self->{'name'});
250*c9b362f6SAndre Fischer
251*c9b362f6SAndre Fischer    return undef;
252*c9b362f6SAndre Fischer}
253*c9b362f6SAndre Fischer
254*c9b362f6SAndre Fischer
255*c9b362f6SAndre Fischer
256*c9b362f6SAndre Fischer
257*c9b362f6SAndre Fischer=head2 GetAllRows ($self)
258*c9b362f6SAndre Fischer
259*c9b362f6SAndre Fischer    Return the reference to an array that contains all rows of the table.
260*c9b362f6SAndre Fischer
261*c9b362f6SAndre Fischer=cut
262*c9b362f6SAndre Fischer
263*c9b362f6SAndre Fischersub GetAllRows ($)
264*c9b362f6SAndre Fischer{
265*c9b362f6SAndre Fischer    my $self = shift;
266*c9b362f6SAndre Fischer
267*c9b362f6SAndre Fischer    return $self->{'rows'};
268*c9b362f6SAndre Fischer}
269*c9b362f6SAndre Fischer
270*c9b362f6SAndre Fischer
271*c9b362f6SAndre Fischer
272*c9b362f6SAndre Fischer
273*c9b362f6SAndre Fischer
274*c9b362f6SAndre Fischer1;
275