xref: /AOO42X/main/solenv/bin/make_ext_update_info.pl (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir:
2*cdf0e10cSrcweireval 'exec perl -wS $0 ${1+"$@"}'
3*cdf0e10cSrcweir    if 0;
4*cdf0e10cSrcweir#*************************************************************************
5*cdf0e10cSrcweir#
6*cdf0e10cSrcweir# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7*cdf0e10cSrcweir#
8*cdf0e10cSrcweir# Copyright 2000, 2010 Oracle and/or its affiliates.
9*cdf0e10cSrcweir#
10*cdf0e10cSrcweir# OpenOffice.org - a multi-platform office productivity suite
11*cdf0e10cSrcweir#
12*cdf0e10cSrcweir# This file is part of OpenOffice.org.
13*cdf0e10cSrcweir#
14*cdf0e10cSrcweir# OpenOffice.org is free software: you can redistribute it and/or modify
15*cdf0e10cSrcweir# it under the terms of the GNU Lesser General Public License version 3
16*cdf0e10cSrcweir# only, as published by the Free Software Foundation.
17*cdf0e10cSrcweir#
18*cdf0e10cSrcweir# OpenOffice.org is distributed in the hope that it will be useful,
19*cdf0e10cSrcweir# but WITHOUT ANY WARRANTY; without even the implied warranty of
20*cdf0e10cSrcweir# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21*cdf0e10cSrcweir# GNU Lesser General Public License version 3 for more details
22*cdf0e10cSrcweir# (a copy is included in the LICENSE file that accompanied this code).
23*cdf0e10cSrcweir#
24*cdf0e10cSrcweir# You should have received a copy of the GNU Lesser General Public License
25*cdf0e10cSrcweir# version 3 along with OpenOffice.org.  If not, see
26*cdf0e10cSrcweir# <http://www.openoffice.org/license.html>
27*cdf0e10cSrcweir# for a copy of the LGPLv3 License.
28*cdf0e10cSrcweir#
29*cdf0e10cSrcweir#*************************************************************************
30*cdf0e10cSrcweir
31*cdf0e10cSrcweir#here the definition for d would be written into dependencies. The reason is that when the event handler
32*cdf0e10cSrcweir#for the element is called, we can only find out the namespace but not the prefix. So we cannot
33*cdf0e10cSrcweir#distinguish if the namespace is used because the element was prefixed or because it uses the default
34*cdf0e10cSrcweir#namespace.
35*cdf0e10cSrcweiruse warnings;
36*cdf0e10cSrcweiruse strict;
37*cdf0e10cSrcweir
38*cdf0e10cSrcweiruse XML::Parser;
39*cdf0e10cSrcweiruse Getopt::Long;
40*cdf0e10cSrcweiruse Carp;
41*cdf0e10cSrcweir
42*cdf0e10cSrcweirsub getUpdateInfoFileName($);
43*cdf0e10cSrcweirsub writeUpdateInformationData($);
44*cdf0e10cSrcweirsub findAttribute($$);
45*cdf0e10cSrcweirsub getNotDefPrefs($$$);
46*cdf0e10cSrcweirsub collectPrefixes($$$$);
47*cdf0e10cSrcweirsub determineNsDefinitions($$$);
48*cdf0e10cSrcweirsub determineNsDefinitionForItem($$$);
49*cdf0e10cSrcweir
50*cdf0e10cSrcweirmy $inDescription = 0;
51*cdf0e10cSrcweirmy $inDependencies = 0;
52*cdf0e10cSrcweirmy $inIdentifier = 0;
53*cdf0e10cSrcweirmy $inVersion = 0;
54*cdf0e10cSrcweirmy $descNS = "http://openoffice.org/extensions/description/2006";
55*cdf0e10cSrcweir                   my $indent;
56*cdf0e10cSrcweirmy $identifier;
57*cdf0e10cSrcweirmy $version;
58*cdf0e10cSrcweir
59*cdf0e10cSrcweir#contains prefixes and the corresponding namespaces which are used in the <dependencies>
60*cdf0e10cSrcweir#element and all children of the description.xml
61*cdf0e10cSrcweirmy @usedNsInDependencies;
62*cdf0e10cSrcweir
63*cdf0e10cSrcweir#Maps  prefix to namespaces which are valid in <dependencies>. That is, they are
64*cdf0e10cSrcweir#either defined in <dependencies> or in the hirarchy above <dependencies>
65*cdf0e10cSrcweirmy %validPrefsInDep;
66*cdf0e10cSrcweir#Contains the prefixes which are defined in <dependencies>
67*cdf0e10cSrcweirmy @newPrefsInDep;
68*cdf0e10cSrcweir#Contains the prefixes/namespaces which need to be defined in <dependencies> but which are currently
69*cdf0e10cSrcweir#not. For example a prefix is defined in the parent and is used in a child of <dependencies>
70*cdf0e10cSrcweirmy %notDefInDep;
71*cdf0e10cSrcweir
72*cdf0e10cSrcweir#prefix used in start and end element
73*cdf0e10cSrcweirmy $prefix;
74*cdf0e10cSrcweir
75*cdf0e10cSrcweir#The default namespace valid in <dependencies>
76*cdf0e10cSrcweirmy $defNsInDep;
77*cdf0e10cSrcweir#The prefix which we use for the default namespace used in <dependencies>
78*cdf0e10cSrcweirmy $generatedPrefix;
79*cdf0e10cSrcweir
80*cdf0e10cSrcweirmy $helptext =
81*cdf0e10cSrcweir"make_ext_update_info.pl produces an update information file for an extension. ".
82*cdf0e10cSrcweir"It will use a dummy URL as URL for the extension update unless a URL has been ".
83*cdf0e10cSrcweir"provided with the --update_url option. The name of the update ".
84*cdf0e10cSrcweir"information file, which must be provided with the --out switch, should be formed ".
85*cdf0e10cSrcweir"according to this scheme: \n\n".
86*cdf0e10cSrcweir"extension_identifier.update.xml\n\n".
87*cdf0e10cSrcweir"extension_identifier should correspond to the extension identifier. In some cases ".
88*cdf0e10cSrcweir"this may not be possible because the identifier may contain characters which are not ".
89*cdf0e10cSrcweir"allowd in file names.\n\n".
90*cdf0e10cSrcweir"usage:\n".
91*cdf0e10cSrcweir"perl make_ext_update_info.pl [--help][--update_url url] --out update_information_file description.xml \n\n".
92*cdf0e10cSrcweir"Options: \n".
93*cdf0e10cSrcweir"--help - prints the help message and exits \n".
94*cdf0e10cSrcweir"--out file - the update information file to be written including the path \n".
95*cdf0e10cSrcweir"--update-url url - inserts the url under the <update-download> element. It may be necessary to enclose the urls in quotes in case they contain characters such as \"?\". ".
96*cdf0e10cSrcweir"It can be used multiple times\n\n";
97*cdf0e10cSrcweir
98*cdf0e10cSrcweir#handling of arguments
99*cdf0e10cSrcweirmy $help = 0;
100*cdf0e10cSrcweirmy $out;
101*cdf0e10cSrcweirmy @update_urls;
102*cdf0e10cSrcweirif (!GetOptions('help|?' => \$help,
103*cdf0e10cSrcweir                'out=s' => \$out,
104*cdf0e10cSrcweir                'update-url=s'=> \@update_urls))
105*cdf0e10cSrcweir{
106*cdf0e10cSrcweir    print $helptext;
107*cdf0e10cSrcweir    exit -1;
108*cdf0e10cSrcweir}
109*cdf0e10cSrcweirmy $cArgs = scalar @ARGV;
110*cdf0e10cSrcweirdie "You need to provide a description.xml\n\n$helptext" if $cArgs ==0;
111*cdf0e10cSrcweirdie "You need to provide the name of the update information file ".
112*cdf0e10cSrcweir    "with the --out switch.\n" unless ($out);
113*cdf0e10cSrcweirdie "Too many arguments. \n\n$helptext" if $cArgs > 1;
114*cdf0e10cSrcweirprint $helptext if $help;
115*cdf0e10cSrcweir
116*cdf0e10cSrcweir
117*cdf0e10cSrcweir#open the update information file for writing
118*cdf0e10cSrcweirmy $FH;
119*cdf0e10cSrcweiropen $FH, "> $out" or die $!;
120*cdf0e10cSrcweir
121*cdf0e10cSrcweir#write the xml header and root element
122*cdf0e10cSrcweirprint $FH '<?xml version="1.0" encoding="UTF-8"?>', "\n";
123*cdf0e10cSrcweirprint $FH '<description xmlns="http://openoffice.org/extensions/update/2006"', "\n";
124*cdf0e10cSrcweirprint $FH '    xmlns:xlink="http://www.w3.org/1999/xlink">', "\n";
125*cdf0e10cSrcweir
126*cdf0e10cSrcweir#obtain from description.xml the data for the update information
127*cdf0e10cSrcweirwriteUpdateInformationData($ARGV[0]);
128*cdf0e10cSrcweir#We will die if there is no <version> or <identifier> in the description.xml
129*cdf0e10cSrcweirdie "Error: The description.xml does not contain a <identifier> element.\n" unless $identifier;
130*cdf0e10cSrcweirdie "Error: The description.xml does not contain a <version> element. \n" unless $version;
131*cdf0e10cSrcweir
132*cdf0e10cSrcweir#write the write the update-download element and the children.
133*cdf0e10cSrcweir#the indention of <update-download> corresponds to that of <version>
134*cdf0e10cSrcweirprint $FH ' 'x$indent, '<update-download>', "\n";
135*cdf0e10cSrcweir#check if update-urls have been provided through --update-url option
136*cdf0e10cSrcweirif (scalar @update_urls)
137*cdf0e10cSrcweir{
138*cdf0e10cSrcweir    my $urlIndent = $indent > 8 ? 8 : 2 * $indent;
139*cdf0e10cSrcweir    #use provided urls
140*cdf0e10cSrcweir    for (@update_urls)
141*cdf0e10cSrcweir    {
142*cdf0e10cSrcweir        print $FH ' 'x$urlIndent, '<src xlink:href="'.$_.'" />', "\n";
143*cdf0e10cSrcweir    }
144*cdf0e10cSrcweir}
145*cdf0e10cSrcweirelse
146*cdf0e10cSrcweir{
147*cdf0e10cSrcweir    #use dummy update url
148*cdf0e10cSrcweir    print $FH ' 'x8, '<src xlink:href="http://extensions.openoffice.org/testarea/dummy.oxt" />', "\n";
149*cdf0e10cSrcweir}
150*cdf0e10cSrcweirprint $FH ' 'x$indent, '</update-download>', "\n";
151*cdf0e10cSrcweir
152*cdf0e10cSrcweirprint $FH '</description>', "\n";
153*cdf0e10cSrcweirclose $FH;
154*cdf0e10cSrcweir
155*cdf0e10cSrcweirexit 0;
156*cdf0e10cSrcweir
157*cdf0e10cSrcweir
158*cdf0e10cSrcweir
159*cdf0e10cSrcweirsub start_handler
160*cdf0e10cSrcweir{
161*cdf0e10cSrcweir    my $parser = shift;
162*cdf0e10cSrcweir    my $name = shift;
163*cdf0e10cSrcweir
164*cdf0e10cSrcweir    if ($name eq "description"
165*cdf0e10cSrcweir        && $descNS eq $parser->namespace($name))
166*cdf0e10cSrcweir    {
167*cdf0e10cSrcweir        $inDescription = 1;
168*cdf0e10cSrcweir    }
169*cdf0e10cSrcweir    elsif ($inDescription
170*cdf0e10cSrcweir           && $name eq "version"
171*cdf0e10cSrcweir           && $descNS eq  $parser->namespace($name))
172*cdf0e10cSrcweir    {
173*cdf0e10cSrcweir        $inVersion = 1;
174*cdf0e10cSrcweir        $version = 1;
175*cdf0e10cSrcweir        $indent = $parser->current_column();
176*cdf0e10cSrcweir        print $FH " "x$indent, $parser->original_string();
177*cdf0e10cSrcweir    }
178*cdf0e10cSrcweir    elsif ($inDescription
179*cdf0e10cSrcweir           && $name eq "identifier"
180*cdf0e10cSrcweir           && $descNS eq  $parser->namespace($name))
181*cdf0e10cSrcweir    {
182*cdf0e10cSrcweir        $inIdentifier = 1;
183*cdf0e10cSrcweir        $identifier = 1;
184*cdf0e10cSrcweir        print $FH " "x$parser->current_column(), $parser->original_string();
185*cdf0e10cSrcweir    }
186*cdf0e10cSrcweir    elsif ($inDescription
187*cdf0e10cSrcweir           && $name eq "dependencies"
188*cdf0e10cSrcweir           && $descNS eq  $parser->namespace($name))
189*cdf0e10cSrcweir    {
190*cdf0e10cSrcweir        $inDependencies = 1;
191*cdf0e10cSrcweir        my $dep = $parser->original_string();
192*cdf0e10cSrcweir        #add the additional namespace definitions, which we have discovered during the first
193*cdf0e10cSrcweir        #parsing
194*cdf0e10cSrcweir        #cut of the closing > or /> from the start element, so we can append the namespace definitions
195*cdf0e10cSrcweir        $dep =~ /(\s*<.*) ((\s*\/>)|(\s*>))/x;
196*cdf0e10cSrcweir        my $dep1 = $1;
197*cdf0e10cSrcweir        $dep1.= " xmlns:".$_.'="'.$notDefInDep{$_}.'"' for (keys %notDefInDep);
198*cdf0e10cSrcweir        $dep1.= $2;
199*cdf0e10cSrcweir        print $FH " "x$parser->current_column(), $dep1;
200*cdf0e10cSrcweir    }
201*cdf0e10cSrcweir    elsif ($inDependencies)
202*cdf0e10cSrcweir    {
203*cdf0e10cSrcweir        #$prefix is global because we need to use it in the end element as well.
204*cdf0e10cSrcweir        $prefix = "";
205*cdf0e10cSrcweir        my $fullString;
206*cdf0e10cSrcweir        my $orig = $parser->original_string();
207*cdf0e10cSrcweir        #Split up the string so we can insert the prefix for the element.
208*cdf0e10cSrcweir        # <OpenOffice.org-minimal-version>
209*cdf0e10cSrcweir        # <d:OpenOffice.org-minimal-version>
210*cdf0e10cSrcweir        $orig=~/(\s*<)(.*?)\s/x;
211*cdf0e10cSrcweir        #in $2 is the element name, look for the prefix
212*cdf0e10cSrcweir        if ($2 !~/(.*?):/ && $parser->namespace($name)) {
213*cdf0e10cSrcweir            #no prefix, that is element uses default namespace.
214*cdf0e10cSrcweir            #Now check if the default namespace in <dependencies> is the same as the one in this
215*cdf0e10cSrcweir            #element. If not, then the default ns was defined "after" <dependencies>. Because all
216*cdf0e10cSrcweir            #children of <dependencies> are copied into the update information, so will this default
217*cdf0e10cSrcweir            #namespace definition. Hence this element will have the same default namespace in the
218*cdf0e10cSrcweir            #update information.
219*cdf0e10cSrcweir            my $defNsDep = $validPrefsInDep{"#default"};
220*cdf0e10cSrcweir            #we must have #default, see the if statement above
221*cdf0e10cSrcweir            my $defNsCur = $parser->expand_ns_prefix("#default");
222*cdf0e10cSrcweir
223*cdf0e10cSrcweir            if ($defNsDep eq $defNsCur) {
224*cdf0e10cSrcweir                #Determine if there is in <dependency> a prefix defined (only valid there and need not
225*cdf0e10cSrcweir                #directly defined in this element). If there is no prefix defined then we will
226*cdf0e10cSrcweir                #add a new definition to <dependencies>.
227*cdf0e10cSrcweir                for (keys %validPrefsInDep) {
228*cdf0e10cSrcweir                    if (($validPrefsInDep{$_} eq $defNsDep) && $_ ne "#default") {
229*cdf0e10cSrcweir                        $prefix = $_; last;
230*cdf0e10cSrcweir                    }
231*cdf0e10cSrcweir                }
232*cdf0e10cSrcweir                if (! $prefix) {
233*cdf0e10cSrcweir                    #If there was no prefix, we will add new prefix definition to <dependency>
234*cdf0e10cSrcweir                    #Which prefix this is has been determined during the first parsing.
235*cdf0e10cSrcweir                    for (keys %notDefInDep) {
236*cdf0e10cSrcweir                        if (($notDefInDep{$_} eq $defNsCur) && $_ ne "#default") {
237*cdf0e10cSrcweir                            $prefix = $_; last;
238*cdf0e10cSrcweir                        }
239*cdf0e10cSrcweir                    }
240*cdf0e10cSrcweir                }
241*cdf0e10cSrcweir                #die if we have no prefix
242*cdf0e10cSrcweir                confess "No prefix defined for default namespace " unless $prefix;
243*cdf0e10cSrcweir                #get the full part after <
244*cdf0e10cSrcweir                $orig=~/(\s*<)(.*)/x;
245*cdf0e10cSrcweir                $fullString= $1.$prefix.":".$2;
246*cdf0e10cSrcweir            }
247*cdf0e10cSrcweir
248*cdf0e10cSrcweir        }
249*cdf0e10cSrcweir        $fullString = $orig unless $fullString;
250*cdf0e10cSrcweir
251*cdf0e10cSrcweir        # We record anything within <dependencies> </dependencies>.
252*cdf0e10cSrcweir        print $FH $fullString;
253*cdf0e10cSrcweir    }
254*cdf0e10cSrcweir}
255*cdf0e10cSrcweir
256*cdf0e10cSrcweirsub end_handler
257*cdf0e10cSrcweir{
258*cdf0e10cSrcweir    my $parser = shift;
259*cdf0e10cSrcweir    my $name = shift;
260*cdf0e10cSrcweir
261*cdf0e10cSrcweir    if ($name eq "description"
262*cdf0e10cSrcweir        && $descNS eq  $parser->namespace($name))
263*cdf0e10cSrcweir    {
264*cdf0e10cSrcweir        $inDescription = 0;
265*cdf0e10cSrcweir    }
266*cdf0e10cSrcweir    elsif ($inDescription
267*cdf0e10cSrcweir           && $name eq "version"
268*cdf0e10cSrcweir           && $descNS eq  $parser->namespace($name))
269*cdf0e10cSrcweir    {
270*cdf0e10cSrcweir        $inVersion = 0;
271*cdf0e10cSrcweir        print $FH  $parser->original_string(), "\n";
272*cdf0e10cSrcweir    }
273*cdf0e10cSrcweir    elsif ($inDescription
274*cdf0e10cSrcweir           && $name eq "identifier"
275*cdf0e10cSrcweir           && $descNS eq  $parser->namespace($name))
276*cdf0e10cSrcweir    {
277*cdf0e10cSrcweir        $inIdentifier = 0;
278*cdf0e10cSrcweir        print $FH $parser->original_string(), "\n";
279*cdf0e10cSrcweir    }
280*cdf0e10cSrcweir    elsif($inDescription
281*cdf0e10cSrcweir          && $name eq "dependencies"
282*cdf0e10cSrcweir          && $descNS eq $parser->namespace($name))
283*cdf0e10cSrcweir    {
284*cdf0e10cSrcweir        $inDependencies = 0;
285*cdf0e10cSrcweir        print $FH $parser->original_string(), "\n";
286*cdf0e10cSrcweir    }
287*cdf0e10cSrcweir    elsif ($inDependencies)
288*cdf0e10cSrcweir    {
289*cdf0e10cSrcweir        my $orig = $parser->original_string();
290*cdf0e10cSrcweir        #$orig is empty if we have tags like this: <name />
291*cdf0e10cSrcweir        if ($orig && $prefix) {
292*cdf0e10cSrcweir            $orig=~/(\s*<\/)(.*)/x;
293*cdf0e10cSrcweir            $orig= $1.$prefix.":".$2;
294*cdf0e10cSrcweir        }
295*cdf0e10cSrcweir        print $FH $orig;
296*cdf0e10cSrcweir    }
297*cdf0e10cSrcweir}
298*cdf0e10cSrcweir
299*cdf0e10cSrcweir#We write the complete content between start and end tags of
300*cdf0e10cSrcweir# <identifier>, <version>, <dependencies>
301*cdf0e10cSrcweirsub default_handler
302*cdf0e10cSrcweir{
303*cdf0e10cSrcweir    my $parser = shift;
304*cdf0e10cSrcweir    my $name = shift;
305*cdf0e10cSrcweir    if ($inIdentifier || $inVersion) {
306*cdf0e10cSrcweir        print $FH $parser->original_string();
307*cdf0e10cSrcweir    } elsif ($inDependencies) {
308*cdf0e10cSrcweir        print $FH  $parser->original_string();
309*cdf0e10cSrcweir    }
310*cdf0e10cSrcweir
311*cdf0e10cSrcweir}  # End of default_handler
312*cdf0e10cSrcweir
313*cdf0e10cSrcweir#sax handler used for the first parsing to recognize the used prefixes in <dependencies > and its
314*cdf0e10cSrcweir#children and to find out if we need to define a new prefix for the current default namespace.
315*cdf0e10cSrcweirsub start_handler_infos
316*cdf0e10cSrcweir{
317*cdf0e10cSrcweir    my $parser = shift;
318*cdf0e10cSrcweir    my $name = shift;
319*cdf0e10cSrcweir    if ($name eq "description"
320*cdf0e10cSrcweir        && $descNS eq $parser->namespace($name)) {
321*cdf0e10cSrcweir        $inDescription = 1;
322*cdf0e10cSrcweir    }
323*cdf0e10cSrcweir    elsif ($inDescription
324*cdf0e10cSrcweir           && $name eq "dependencies"
325*cdf0e10cSrcweir           && $descNS eq  $parser->namespace($name)) {
326*cdf0e10cSrcweir        $inDependencies = 1;
327*cdf0e10cSrcweir        #build the map of prefix/namespace which are valid in <dependencies>
328*cdf0e10cSrcweir        my @cur = $parser->current_ns_prefixes();
329*cdf0e10cSrcweir        for (@cur) {
330*cdf0e10cSrcweir            $validPrefsInDep{$_} = $parser->expand_ns_prefix($_);
331*cdf0e10cSrcweir        }
332*cdf0e10cSrcweir        #remember the prefixes defined in <dependencies>
333*cdf0e10cSrcweir        @newPrefsInDep = $parser->new_ns_prefixes();
334*cdf0e10cSrcweir
335*cdf0e10cSrcweir        collectPrefixes($parser, $name, \@_, \@usedNsInDependencies);
336*cdf0e10cSrcweir        return if  $generatedPrefix;
337*cdf0e10cSrcweir
338*cdf0e10cSrcweir        #determine if need to create a new prefix for the current element if it uses a default ns.
339*cdf0e10cSrcweir        #Split up the string so we can see if there is a prefix used
340*cdf0e10cSrcweir        # <OpenOffice.org-minimal-version>
341*cdf0e10cSrcweir        # <d:OpenOffice.org-minimal-version>
342*cdf0e10cSrcweir        my $orig = $parser->original_string();
343*cdf0e10cSrcweir        $orig=~/(\s*<)(.*?)\s/x;
344*cdf0e10cSrcweir        #in $2 is the element name, look for the prefix
345*cdf0e10cSrcweir        if ($2 !~/(.*?):/ && $parser->namespace($name)) {
346*cdf0e10cSrcweir            #no prefix, that is element uses default namespace.
347*cdf0e10cSrcweir            #Now check if the default namespace in <dependencies> is the same as the one in this
348*cdf0e10cSrcweir            #element. If not, then the default ns was defined "after" <dependencies>. Because all
349*cdf0e10cSrcweir            #children of <dependencies> are copied into the update information, so will this default
350*cdf0e10cSrcweir            #namespace definition. Hence this element will have the same default namespace in the
351*cdf0e10cSrcweir            #update information.
352*cdf0e10cSrcweir            my $defNsDep = $validPrefsInDep{"#default"};
353*cdf0e10cSrcweir            #we must have #default, see the if statement above
354*cdf0e10cSrcweir            my $defNsCur = $parser->expand_ns_prefix("#default");
355*cdf0e10cSrcweir
356*cdf0e10cSrcweir            if ($defNsDep eq $defNsCur) {
357*cdf0e10cSrcweir                #Determine if there is in <dependency> a prefix defined (only valid there and need not
358*cdf0e10cSrcweir                #directly defined in this element). If there is no prefix defined then we will
359*cdf0e10cSrcweir                #add a new definition to <dependencies>.
360*cdf0e10cSrcweir                for (keys %validPrefsInDep) {
361*cdf0e10cSrcweir                    if (($validPrefsInDep{$_} eq $defNsDep) && $_ ne "#default") {
362*cdf0e10cSrcweir                        $prefix = $_; last;
363*cdf0e10cSrcweir                    }
364*cdf0e10cSrcweir                }
365*cdf0e10cSrcweir
366*cdf0e10cSrcweir                if (! $prefix) {
367*cdf0e10cSrcweir
368*cdf0e10cSrcweir                    #define a new prefix
369*cdf0e10cSrcweir                    #actually there can be only onle prefix, which is the case when the element
370*cdf0e10cSrcweir                    #uses the same default namespace as <dependencies> otherwise, the default
371*cdf0e10cSrcweir                    #namespace was redefined by the children of <dependencies>. These are completely
372*cdf0e10cSrcweir                    #copied and still valid in the update information file
373*cdf0e10cSrcweir                    $generatedPrefix = "a";
374*cdf0e10cSrcweir                    $defNsInDep = $defNsDep;
375*cdf0e10cSrcweir                }
376*cdf0e10cSrcweir            }
377*cdf0e10cSrcweir        }
378*cdf0e10cSrcweir
379*cdf0e10cSrcweir    }
380*cdf0e10cSrcweir    elsif ($inDependencies) {
381*cdf0e10cSrcweir        determineNsDefinitions($parser, $name, \@_);
382*cdf0e10cSrcweir        collectPrefixes($parser, $name, \@_, \@usedNsInDependencies);
383*cdf0e10cSrcweir    }
384*cdf0e10cSrcweir}
385*cdf0e10cSrcweir#sax handler used for the first parsing to recognize the used prefixes in <dependencies > and its
386*cdf0e10cSrcweir#children
387*cdf0e10cSrcweirsub end_handler_infos
388*cdf0e10cSrcweir{
389*cdf0e10cSrcweir    my $parser = shift;
390*cdf0e10cSrcweir    my $name = shift;
391*cdf0e10cSrcweir
392*cdf0e10cSrcweir    if ($name eq "description"
393*cdf0e10cSrcweir        && $descNS eq  $parser->namespace($name)) {
394*cdf0e10cSrcweir        $inDescription = 0;
395*cdf0e10cSrcweir    }
396*cdf0e10cSrcweir    elsif($inDescription
397*cdf0e10cSrcweir          && $name eq "dependencies"
398*cdf0e10cSrcweir          && $descNS eq $parser->namespace($name)) {
399*cdf0e10cSrcweir        $inDependencies = 0;
400*cdf0e10cSrcweir    }
401*cdf0e10cSrcweir}
402*cdf0e10cSrcweir
403*cdf0e10cSrcweirsub writeUpdateInformationData($)
404*cdf0e10cSrcweir{
405*cdf0e10cSrcweir    my $desc = shift;
406*cdf0e10cSrcweir    {
407*cdf0e10cSrcweir        #parse description xml to collect information about all used
408*cdf0e10cSrcweir        #prefixes and names within <dependencies>
409*cdf0e10cSrcweir
410*cdf0e10cSrcweir        my $parser = new XML::Parser(ErrorContext => 2,
411*cdf0e10cSrcweir                                     Namespaces => 1);
412*cdf0e10cSrcweir        $parser->setHandlers(Start => \&start_handler_infos,
413*cdf0e10cSrcweir                             End => \&end_handler_infos);
414*cdf0e10cSrcweir
415*cdf0e10cSrcweir        $parser->parsefile($desc);
416*cdf0e10cSrcweir
417*cdf0e10cSrcweir
418*cdf0e10cSrcweir    }
419*cdf0e10cSrcweir    #remove duplicates in the array containing the prefixes
420*cdf0e10cSrcweir    if ($generatedPrefix) {
421*cdf0e10cSrcweir        my %hashtmp;
422*cdf0e10cSrcweir        @usedNsInDependencies = grep(!$hashtmp{$_}++, @usedNsInDependencies);
423*cdf0e10cSrcweir
424*cdf0e10cSrcweir        #check that the prefix for the default namespace in <dependencies> does not clash
425*cdf0e10cSrcweir        #with any other prefixes
426*cdf0e10cSrcweir        my $clash;
427*cdf0e10cSrcweir        do {
428*cdf0e10cSrcweir            $clash = 0;
429*cdf0e10cSrcweir            for (@usedNsInDependencies) {
430*cdf0e10cSrcweir                if ($_ eq $generatedPrefix) {
431*cdf0e10cSrcweir                    $generatedPrefix++;
432*cdf0e10cSrcweir                    $clash = 1; last;
433*cdf0e10cSrcweir                }
434*cdf0e10cSrcweir            }
435*cdf0e10cSrcweir        } while ($clash);
436*cdf0e10cSrcweir        $notDefInDep{$generatedPrefix} = $defNsInDep;
437*cdf0e10cSrcweir    }
438*cdf0e10cSrcweir    #if $notDefInDep contains the prefix #default then we need to add the generated prefix as well
439*cdf0e10cSrcweir
440*cdf0e10cSrcweir    #add the special prefix for the default namespace into the map of prefixes that will be
441*cdf0e10cSrcweir    #added to the <dependencies> element in the update information file
442*cdf0e10cSrcweir
443*cdf0e10cSrcweir
444*cdf0e10cSrcweir    ($inDependencies, $inDescription) = (0,0);
445*cdf0e10cSrcweir    {
446*cdf0e10cSrcweir        my $parser = new XML::Parser(ErrorContext => 2,
447*cdf0e10cSrcweir                                     Namespaces => 1);
448*cdf0e10cSrcweir        $parser->setHandlers(
449*cdf0e10cSrcweir                             Start => \&start_handler,
450*cdf0e10cSrcweir                             End => \&end_handler,
451*cdf0e10cSrcweir                             Default => \&default_handler);
452*cdf0e10cSrcweir        $parser->parsefile($desc);
453*cdf0e10cSrcweir    }
454*cdf0e10cSrcweir}
455*cdf0e10cSrcweir
456*cdf0e10cSrcweir# param 1: name of the attribute we look for
457*cdf0e10cSrcweir# param 2: array of name value pairs, the first subscript is the attribute and the second
458*cdf0e10cSrcweir# is the value.
459*cdf0e10cSrcweirsub findAttribute($$)
460*cdf0e10cSrcweir{
461*cdf0e10cSrcweir    my ($name, $args_r) = @_;
462*cdf0e10cSrcweir    my @args = @{$args_r};
463*cdf0e10cSrcweir    my $value;
464*cdf0e10cSrcweir    while (my $attr = shift(@args))
465*cdf0e10cSrcweir    {
466*cdf0e10cSrcweir        if ($attr eq $name) {
467*cdf0e10cSrcweir            $value = shift(@args);
468*cdf0e10cSrcweir            die "href attribut has no valid URL" unless $value;
469*cdf0e10cSrcweir            last;
470*cdf0e10cSrcweir        } else { # shift away the following value for the attribute
471*cdf0e10cSrcweir            shift(@args);
472*cdf0e10cSrcweir        }
473*cdf0e10cSrcweir    }
474*cdf0e10cSrcweir    return $value;
475*cdf0e10cSrcweir}
476*cdf0e10cSrcweir
477*cdf0e10cSrcweir#collect the prefixes used in an xml element
478*cdf0e10cSrcweir#param 1: parser,
479*cdf0e10cSrcweir#param 2: element name,
480*cdf0e10cSrcweir#param 3: array of name and values of attributes
481*cdf0e10cSrcweir#param 4: out parameter, the array containing the prefixes
482*cdf0e10cSrcweirsub collectPrefixes($$$$)
483*cdf0e10cSrcweir{
484*cdf0e10cSrcweir    my $parser = shift;
485*cdf0e10cSrcweir    my $name = shift;
486*cdf0e10cSrcweir    my $attr_r = shift;
487*cdf0e10cSrcweir    my $out_r = shift;
488*cdf0e10cSrcweir    #get the prefixes which are currently valid
489*cdf0e10cSrcweir    my @cur = $parser->current_ns_prefixes();
490*cdf0e10cSrcweir    my %map_ns;
491*cdf0e10cSrcweir    #get the namespaces for the prefixes
492*cdf0e10cSrcweir    for (@cur) {
493*cdf0e10cSrcweir        if ($_ eq '#default') {
494*cdf0e10cSrcweir            next;
495*cdf0e10cSrcweir        }
496*cdf0e10cSrcweir        my $ns = $parser->expand_ns_prefix($_);
497*cdf0e10cSrcweir        $map_ns{$ns} = $_;
498*cdf0e10cSrcweir    }
499*cdf0e10cSrcweir    #investigat ns of element
500*cdf0e10cSrcweir    my $pref = $map_ns{$parser->namespace($name)};
501*cdf0e10cSrcweir    push(@{$out_r}, $pref) if $pref;
502*cdf0e10cSrcweir    #now go over the attributes
503*cdf0e10cSrcweir
504*cdf0e10cSrcweir    while (my $attr = shift(@{$attr_r})) {
505*cdf0e10cSrcweir        my $ns = $parser->namespace($attr);
506*cdf0e10cSrcweir        if (! $ns) {
507*cdf0e10cSrcweir            shift(@{$attr_r});
508*cdf0e10cSrcweir            next;
509*cdf0e10cSrcweir        }
510*cdf0e10cSrcweir        $pref = $map_ns{$ns};
511*cdf0e10cSrcweir        push( @{$out_r}, $pref) if $pref;
512*cdf0e10cSrcweir        shift(@{$attr_r});
513*cdf0e10cSrcweir    }
514*cdf0e10cSrcweir    #also add newly defined prefixes
515*cdf0e10cSrcweir    my @newNs = $parser->new_ns_prefixes();
516*cdf0e10cSrcweir    for (@newNs) {
517*cdf0e10cSrcweir        if ($_ eq '#default') {
518*cdf0e10cSrcweir            next;
519*cdf0e10cSrcweir        }
520*cdf0e10cSrcweir        push (@{$out_r}, $_);
521*cdf0e10cSrcweir    }
522*cdf0e10cSrcweir}
523*cdf0e10cSrcweir
524*cdf0e10cSrcweir#The function is called for each child element of dependencies. It finds out the prefixes
525*cdf0e10cSrcweir#which are used by the children and which are defined by the parents of <dependencies>. These
526*cdf0e10cSrcweir#would be lost when copying the children of <dependencies> into the update information file.
527*cdf0e10cSrcweir#Therefore these definitions are collected so that they then can be written in the <dependencies>
528*cdf0e10cSrcweir#element of the update information file.
529*cdf0e10cSrcweir#param 1: parser
530*cdf0e10cSrcweir#param 2: namsepace
531*cdf0e10cSrcweir#param 3: the @_ received in the start handler
532*cdf0e10cSrcweirsub determineNsDefinitions($$$)
533*cdf0e10cSrcweir{
534*cdf0e10cSrcweir    my ($parser, $name, $attr_r) = @_;
535*cdf0e10cSrcweir    my @attr = @{$attr_r};
536*cdf0e10cSrcweir
537*cdf0e10cSrcweir    determineNsDefinitionForItem($parser, $name, 1);
538*cdf0e10cSrcweir
539*cdf0e10cSrcweir    while (my $attr = shift(@attr)) {
540*cdf0e10cSrcweir        determineNsDefinitionForItem($parser, $attr, 0);
541*cdf0e10cSrcweir        shift @attr;
542*cdf0e10cSrcweir    }
543*cdf0e10cSrcweir}
544*cdf0e10cSrcweir
545*cdf0e10cSrcweir#do not call this function for the element that does not use a prefix
546*cdf0e10cSrcweir#param 1: parser
547*cdf0e10cSrcweir#param 2: name of the element or attribute
548*cdf0e10cSrcweir#param 3: 1 if called for an elment name and 0 when called for attribue
549*cdf0e10cSrcweirsub determineNsDefinitionForItem($$$)
550*cdf0e10cSrcweir{
551*cdf0e10cSrcweir    my ($parser, $name) = @_;
552*cdf0e10cSrcweir    my $ns = $parser->namespace($name);
553*cdf0e10cSrcweir    if (! $ns) {
554*cdf0e10cSrcweir        return;
555*cdf0e10cSrcweir    }
556*cdf0e10cSrcweir    #If the namespace was not kwown in <dependencies> then it was defined in one of its children
557*cdf0e10cSrcweir    #or in this element. Then we are done since this namespace definition is copied into the
558*cdf0e10cSrcweir    #update information.
559*cdf0e10cSrcweir    my $bNsKnownInDep;
560*cdf0e10cSrcweir    for ( keys %validPrefsInDep) {
561*cdf0e10cSrcweir        if ( $validPrefsInDep{$_} eq $ns) {
562*cdf0e10cSrcweir            $bNsKnownInDep = 1;
563*cdf0e10cSrcweir            last;
564*cdf0e10cSrcweir        }
565*cdf0e10cSrcweir    }
566*cdf0e10cSrcweir    #If the namespace of the current element is known in <dependencies> then check if the same
567*cdf0e10cSrcweir    #prefix is used. If not, then the prefix was defined in one of the children of <dependencies>
568*cdf0e10cSrcweir    #and was assigned the same namespace. Because we copy of children into the update information,
569*cdf0e10cSrcweir    #this definition is also copied.
570*cdf0e10cSrcweir    if ($bNsKnownInDep) {
571*cdf0e10cSrcweir        #create a map of currently valid prefix/namespace
572*cdf0e10cSrcweir        my %curPrefToNs;
573*cdf0e10cSrcweir        my @curNs = $parser->current_ns_prefixes();
574*cdf0e10cSrcweir        for (@curNs) {
575*cdf0e10cSrcweir            $curPrefToNs{$_} = $parser->expand_ns_prefix($_);
576*cdf0e10cSrcweir        }
577*cdf0e10cSrcweir        #find the prefix used in <dependencies> to define the namespace of the current element
578*cdf0e10cSrcweir        my $validDepPref;
579*cdf0e10cSrcweir        for (keys %validPrefsInDep) {
580*cdf0e10cSrcweir            if ($validPrefsInDep{$_} eq $ns) {
581*cdf0e10cSrcweir                #ignore #default
582*cdf0e10cSrcweir                next if $_ eq "#default";
583*cdf0e10cSrcweir                $validDepPref = $_;
584*cdf0e10cSrcweir                last;
585*cdf0e10cSrcweir            }
586*cdf0e10cSrcweir        }
587*cdf0e10cSrcweir        #find the prefix defined in the current element used for the namespace of the element
588*cdf0e10cSrcweir        my $curPref;
589*cdf0e10cSrcweir        for (keys %curPrefToNs) {
590*cdf0e10cSrcweir            if ($curPrefToNs{$_} eq $ns) {
591*cdf0e10cSrcweir                #ignore #default
592*cdf0e10cSrcweir                next if $_ eq "#default";
593*cdf0e10cSrcweir                $curPref = $_;
594*cdf0e10cSrcweir                last;
595*cdf0e10cSrcweir            }
596*cdf0e10cSrcweir        }
597*cdf0e10cSrcweir        if ($curPref && $validDepPref && ($curPref eq $validDepPref)) {
598*cdf0e10cSrcweir            #If the prefixes and ns are the same, then the prefix definition of <dependencies> or its
599*cdf0e10cSrcweir            #parent can be used. However, we need to find out which prefixed are NOT defined in
600*cdf0e10cSrcweir            #<dependencies> so we can add them to it when we write the update information.
601*cdf0e10cSrcweir            my $bDefined = 0;
602*cdf0e10cSrcweir            for (@newPrefsInDep) {
603*cdf0e10cSrcweir                if ($curPref eq $_) {
604*cdf0e10cSrcweir                    $bDefined = 1;
605*cdf0e10cSrcweir                    last;
606*cdf0e10cSrcweir                }
607*cdf0e10cSrcweir            }
608*cdf0e10cSrcweir            if (! $bDefined) {
609*cdf0e10cSrcweir                $notDefInDep{$curPref} = $ns;
610*cdf0e10cSrcweir            }
611*cdf0e10cSrcweir        }
612*cdf0e10cSrcweir    }
613*cdf0e10cSrcweir}
614