MsiTable.pm (c9b362f6) MsiTable.pm (9f91b7e3)
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

--- 30 unchanged lines hidden (view full) ---

39
40=cut
41sub new ($$$)
42{
43 my ($class, $filename, $table_name) = @_;
44
45 my $self = {
46 'name' => $table_name,
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

--- 30 unchanged lines hidden (view full) ---

39
40=cut
41sub new ($$$)
42{
43 my ($class, $filename, $table_name) = @_;
44
45 my $self = {
46 'name' => $table_name,
47 'is_valid' => 1
47 'filename' => $filename,
48 'columns' => undef,
49 'column_specs' => undef,
50 'codepage' => undef,
51 'is_valid' => 1,
52 'is_modified' => 0
48 };
49 bless($self, $class);
50
53 };
54 bless($self, $class);
55
51 if ( -f $filename)
56 if (defined $filename && -f $filename)
52 {
53 $self->ReadFile($filename);
54 }
55 return $self;
56}
57
58
59
60
57 {
58 $self->ReadFile($filename);
59 }
60 return $self;
61}
62
63
64
65
66sub SetColumnData ($@)
67{
68 my ($self, @data) = @_;
69
70 if (((scalar @data) % 2) != 0)
71 {
72 installer::logger::PrintError("column data has to have an even number of elements: (<column-name> <data-spec>)+)\n");
73 $self->{'is_valid'} = 0;
74 return;
75 }
76
77 $self->{'columns'} = [];
78 $self->{'column_specs'} = [];
79 while (scalar @data > 0)
80 {
81 my $name = shift @data;
82 my $spec = shift @data;
83 push @{$self->{'columns'}}, $name;
84 push @{$self->{'column_specs'}}, $spec;
85 }
86}
87
88
89
90
91sub SetIndexColumns ($@)
92{
93 my ($self, @index_columns) = @_;
94
95 $self->{'index_columns'} = [@index_columns];
96}
97
98
99
100
101sub SetCodepage ($$)
102{
103 my ($self, $codepage) = @_;
104
105 $self->{'codepage'} = $codepage;
106}
107
108
109
110
61sub IsValid ($)
62{
63 my ($self) = @_;
64 return $self->{'is_valid'};
65}
66
67
68

--- 32 unchanged lines hidden (view full) ---

101 $self->{'columns'} = [split(/\t/, $columns)];
102
103 my $column_specs = Trim(<$in>);
104 $self->{'column_specs'} = [split(/\t/, $column_specs)];
105
106 # Table name, index columns.
107 my $line = Trim(<$in>);
108 my @items = split(/\t/, $line);
111sub IsValid ($)
112{
113 my ($self) = @_;
114 return $self->{'is_valid'};
115}
116
117
118

--- 32 unchanged lines hidden (view full) ---

151 $self->{'columns'} = [split(/\t/, $columns)];
152
153 my $column_specs = Trim(<$in>);
154 $self->{'column_specs'} = [split(/\t/, $column_specs)];
155
156 # Table name, index columns.
157 my $line = Trim(<$in>);
158 my @items = split(/\t/, $line);
109 if (scalar @items == 3)
159 my $item_count = scalar @items;
160 if ($item_count>=1 && $items[0] eq $self->{'name'})
110 {
161 {
162 # No codepage.
163 }
164 elsif ($item_count>=2 && $items[1] eq $self->{'name'})
165 {
111 $self->{'codepage'} = shift @items;
112 }
166 $self->{'codepage'} = shift @items;
167 }
113 my $table_name = shift @items;
114 if ($table_name ne $self->{'name'})
168 else
115 {
169 {
116 printf STDERR ("reading wrong table data for table '%s' (got %s)\n", $self->{'name'}, $table_name);
170 printf STDERR ("reading wrong table data for table '%s' (got %s)\n", $self->{'name'}, $items[0]);
117 $self->{'is_valid'} = 0;
118 return;
119 }
171 $self->{'is_valid'} = 0;
172 return;
173 }
174 shift @items;
120 $self->{'index_columns'} = [@items];
121 $self->{'index_column_index'} = $self->GetColumnIndex($items[0]);
122
123 my $rows = [];
124 while (<$in>)
125 {
126 # Remove all trailing returns and newlines. Keep trailing spaces and tabs.
127 s/[\r\n]+$//g;
128
129 my @items = split(/\t/, $_);
130 push @$rows, new installer::patch::MsiRow($self, @items);
131 }
132 $self->{'rows'} = $rows;
133
134 return $self;
135}
136
137
138
175 $self->{'index_columns'} = [@items];
176 $self->{'index_column_index'} = $self->GetColumnIndex($items[0]);
177
178 my $rows = [];
179 while (<$in>)
180 {
181 # Remove all trailing returns and newlines. Keep trailing spaces and tabs.
182 s/[\r\n]+$//g;
183
184 my @items = split(/\t/, $_);
185 push @$rows, new installer::patch::MsiRow($self, @items);
186 }
187 $self->{'rows'} = $rows;
188
189 return $self;
190}
191
192
193
194
195=head WriteFile($self, $filename)
196
197 Write a text file containing the current table content.
198
199=cut
200sub WriteFile ($$)
201{
202 my ($self, $filename) = @_;
203
204 open my $out, ">".$self->{'filename'};
205
206 print $out join("\t", @{$self->{'columns'}})."\r\n";
207 print $out join("\t", @{$self->{'column_specs'}})."\r\n";
208 if (defined $self->{'codepage'})
209 {
210 print $out $self->{'codepage'} . "\t";
211 }
212 print $out $self->{'name'} . "\t";
213 print $out join("\t",@{$self->{'index_columns'}})."\r\n";
214
215 foreach my $row (@{$self->{'rows'}})
216 {
217 print $out $row->Format("\t")."\r\n";
218 }
219
220 close $out;
221}
222
223
224
225
226sub UpdateTimestamp ($)
227{
228 my $self = shift;
229
230 utime(undef,undef, $self->{'filename'});
231}
232
233
234
235
236sub GetName ($)
237{
238 my $self = shift;
239
240 return $self->{'name'};
241}
242
243
244
245
139=head2 GetColumnCount($self)
140
141 Return the number of columns in the table.
142
143=cut
144sub GetColumnCount ($)
145{
146 my ($self) = @_;

--- 41 unchanged lines hidden (view full) ---

188 }
189
190 printf STDERR ("did not find column %s in %s\n", $column_name, join(" and ", @{$self->{'columns'}}));
191 return -1;
192}
193
194
195
246=head2 GetColumnCount($self)
247
248 Return the number of columns in the table.
249
250=cut
251sub GetColumnCount ($)
252{
253 my ($self) = @_;

--- 41 unchanged lines hidden (view full) ---

295 }
296
297 printf STDERR ("did not find column %s in %s\n", $column_name, join(" and ", @{$self->{'columns'}}));
298 return -1;
299}
300
301
302
303=head2 GetRowIndex($self, $index_column_index, $index_column_value)
196
304
305 Return the index, starting at 0, of the (first) row that has value $index_column_value
306 in column with index $index_column_index.
307
308 Return -1 if now such row is found.
309
310=cut
311sub GetRowIndex ($$$)
312{
313 my ($self, $index_column_index, $index_column_value) = @_;
314
315 my $rows = $self->{'rows'};
316 for (my ($row_index,$row_count)=(0,scalar @$rows); $row_index<$row_count; ++$row_index)
317 {
318 my $row = $rows->[$row_index];
319 if ($row->GetValue($index_column_index) eq $index_column_value)
320 {
321 return $row_index;
322 }
323 }
324
325 return -1;
326}
327
328
329
330
197=head2 GetValue($self, $selector_column, $selector_column_value, $value_column)
198
199 Find the row in which the $selector_column has value
200 $selector_column_value and return its value in the $value_column.
201
202=cut
203
204sub GetValue ($$$$)

--- 60 unchanged lines hidden (view full) ---

265 my $self = shift;
266
267 return $self->{'rows'};
268}
269
270
271
272
331=head2 GetValue($self, $selector_column, $selector_column_value, $value_column)
332
333 Find the row in which the $selector_column has value
334 $selector_column_value and return its value in the $value_column.
335
336=cut
337
338sub GetValue ($$$$)

--- 60 unchanged lines hidden (view full) ---

399 my $self = shift;
400
401 return $self->{'rows'};
402}
403
404
405
406
407=head2 SetRow($self, {$key, $value}*)
273
408
409 Replace an existing row. If no matching row is found then add the row.
410
411 The row is defined by a set of key/value pairs. Their order is defined by the keys (column names)
412 and their indices as defined in $self->{'columns'}.
413
414 Rows are compared by their values of the index column. By default this is the first element of
415 $self->{'index_columns'} but is overruled by the last key that starts with a '*'.
416
417=cut
418sub SetRow ($@)
419{
420 my $self = shift;
421 my @data = @_;
422
423 my @items = ();
424 my $index_column = $self->{'index_columns'}->[0];
425
426 # Key/Value has to have an even number of entries.
427 MsiTools::Die("invalid arguments given to MsiTable::SetRow()\n") if (scalar @data%2) != 0;
428
429 # Find column indices for column names.
430 while (scalar @data > 0)
431 {
432 my $column_name = shift @data;
433 if ($column_name =~ /^\*(.*)$/)
434 {
435 # Column name starts with a '*'. Use it as index column.
436 $column_name = $1;
437 $index_column = $1;
438 }
439 my $value = shift @data;
440 my $column_index = $self->GetColumnIndex($column_name);
441 $items[$column_index] = $value;
442 }
443
444 my $index_column_index = $self->GetColumnIndex($index_column);
445 my $row_index = $self->GetRowIndex($index_column_index, $items[$index_column_index]);
446
447 if ($row_index < 0)
448 {
449 # Row does not yet exist. Add it.
450 push @{$self->{'rows'}}, installer::patch::MsiRow->new($self, @items);
451 }
452 else
453 {
454 # Row does already exist. Replace it.
455 $self->{'rows'}->[$row_index] = installer::patch::MsiRow->new($self, @items);
456 }
457
458 $self->MarkAsModified();
459}
460
461
462
463
464sub MarkAsModified ($)
465{
466 my $self = shift;
467
468 $self->{'is_modified'} = 1;
469}
470
471
472
473
474sub MarkAsUnmodified ($)
475{
476 my $self = shift;
477
478 $self->{'is_modified'} = 0;
479}
480
481
482
483
484sub IsModified ($)
485{
486 my $self = shift;
487
488 return $self->{'is_modified'};
489}
490
491
2741;
4921;