### Local Variables: *** ### mode:perl *** ### comment-column:0 *** ### comment-start: "### " *** ### comment-end: "***" *** ### End: *** # # ****************DO NOT MOVE OR CHANGE LINES ABOVE THIS********************* # # The first set of lines runs perl from any shell. The second set of lines # identifies the rest of the file as PERL for EMACS autoformatting. # See end of copyright for more information. # # # ------------------------------------------------------------------- # X-BONE # # http://www.isi.edu/xbone # USC Information Sciences Institute (USC/ISI) # Marina del Rey, California 90292, USA # Copyright (c) 1998-2005 # # ------------------------------------------------------------------- # # Copyright (c) 1998-2005 by the University of Southern California. # All rights reserved. # # Permission to use, copy, modify, and distribute this software and # its documentation in source and binary forms for non-commercial # purposes and without fee is hereby granted, provided that the above # copyright notice appear in all copies and that both the copyright # notice and this permission notice appear in supporting # documentation, and that any documentation, advertising materials, # and other materials related to such distribution and use acknowledge # that the software was developed by the University of Southern # California, Information Sciences Institute. The name of the # University may not be used to endorse or promote products derived # from this software without specific prior written permission. # # THE UNIVERSITY OF SOUTHERN CALIFORNIA MAKES NO REPRESENTATIONS ABOUT # THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. THIS SOFTWARE IS # PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, # INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # Other copyrights might apply to parts of this software and are so # noted when applicable. # # ------------------------------------------------------------------- # # Effort partly sponsored by the Defense Advanced Research Projects # Agency (DARPA) and Air Force Research Laboratory, Air Force Materiel # Command, USAF, under agreement numbers F30602-98-1-0200 (X-Bone) and # F30602-01-2-0529 (DynaBone). The views and conclusions contained # herein are those of the authors and should not be interpreted as # necessarily representing the official policies or endorsements, # either expressed or implied, of the Defense Advanced Research # Projects Agency (DARPA), the Air Force Research Laboratory, or the # U.S. Government. # # This work was partly supported by the NSF STI-XTEND (ANI-0230789) # and NETFS (ANI-0129689) projects. Any opinions, findings, and # conclusions or recommendations expressed in this material are those # of the authors and do not necessarily reflect the views of the # National Science Foundation. # # ------------------------------------------------------------------- ################################################## # # # XBone XML scanning utilities used by GUI and OM # # Principal author: Gregory G. Finn # # # These routines presume that the GNOME package libxml2, which is a C language # based XML parser library has been installed on the running system. The # Perl package XML::LibXML requires libxml2. # # The Perl packages XML::LibXML and XML::Simple must be installed # on the running system. XML::LibXML also requires installation of: # # XML::LibXML::Common # XML::NamespaceSupport # XML::NodeFilter # and perhaps XML::SAX # # in order to ensure the XML::LibXML passes its installation test suite. # ################################################## package XB_XML_scan; require Exporter; @ISA = qw(Exporter); @EXPORT = qw(); @EXPORT_OK = qw(); use strict; use Data::Dumper; use XML::LibXML; use XML::Simple; use FindBin qw($Bin); use LWP::Simple; ############################################################################## # # sub XB_XML_parse ( xmlref ) # # Parses the XML string referenced by xmlref. The XML string should include # a reference to the DTD file SYSTEM "api.dtd", which is located in the same # directory as XB_XML.pm. # # Returns an empty string "" if the parse succeeds. Otherwise, the error # string is returned. ############################################################################## ################################################### # Next four functions are callbacks from the parse. ################################################### ################################################### # the parser is asking us if the URI is of interest # to us. ################################################### sub match_uri { my $uri = shift; return ($uri =~ /xbone/i); } ################################################### # capture the URL (http://.../api*.dtd) that is contained in the # XML string when the parser tries to open it. Extract the # filename to see if a local copy exists and if not if a copy # can be made of the file. once the file or local copy # is available, then open it and return the handle. ################################################### sub open_uri { my $uri = shift; my $file = ""; my $dir = $Bin; # figure of the local file name if ($uri =~ /([^\/]+$)/){ $file = $1; } else { die ("Cannot find the DTD resource necessary"); }; # figure out if there is a copy already somewhere my $found =0; foreach my $path ("$dir/modules/",# node daemon "$dir/../lib", # GUI code "/usr/local/etc/xbone", #default if nothing works "/usr/local/xbone/programs/modules", "/tmp"){ if (-e $path and -e "$path/$file" and -r "$path/$file"){ $file = "$path/$file"; $found = 1; last; }; } if (! $found) { # No copy. make a local copy of the file. worst case a temp # file can be created. in most cases it should not come here. # note the change in order of the paths foreach my $path ("/usr/local/etc/xbone", "/usr/local/xbone/programs/modules", "$dir/modules/", "$dir/../lib", "/tmp" ){ if (-e $path and -w $path){ $file = "$path/$file"; if (not head($uri)){ # does this exist? die ("XML resource $uri does not exist. " . "Please mail xbone\@isi.edu"); } mirror($uri, $file); $found = 1; last; } }; } die "Cannot access local resource $uri" if (!$found); # open this cached copy and return it to the library. my $URI; open $URI, $file or die "Error while accessing local resource $file"; return $URI; } ################################################### # the parser is asking us to read the file. This # is presumably if we want to do some processing # e.g., decompression. We dont have do anything. ################################################### sub read_uri { my $handler = shift; my $length = shift; my $buffer; read($handler, $buffer, $length); return $buffer; } ################################################### # close the file. DTD has been read by now. ################################################### sub close_uri { my $handler = shift; close($handler); } sub XB_XML_parse ($) { my ($xmlref) = @_; my $result = ""; my $parser = undef; eval { $parser = XML::LibXML->new; # => register the callbacks so that we can # transparently redirect them to the local # copy. $parser->match_callback(\&match_uri); $parser->open_callback(\&open_uri); $parser->read_callback(\&read_uri); $parser->close_callback(\&close_uri); $parser->validation(1); $parser->pedantic_parser(1); $parser->load_ext_dtd(1); $parser->expand_entities(1); $parser->complete_attributes(1); #$parser->recover(1); #$parser->enable_linenumbers(1); $parser->parse_string($$xmlref); }; if ($@){ $result = $@; }; return $result; } ############################################################################## # # sub XB_XML_hash ( xmlref ) # # Uses XML::Simple to create a hash of the XML string referenced by xmlref. # xmlref must point to a well-formed XML string. # # Returns a reference to the hash representing the XML structure. ############################################################################## sub XB_XML_hash ($) { my ($xmlref) = @_; my $simple; $simple = new XML::Simple (RootName => 'xbone'); return ($simple->XMLin($$xmlref)); } ############################################################################## # # sub XB_XOL_xbone_list_sub ( xbhref ) # # xbhref is a reference to the hash of an xbone element returned by XML::Simple. # The XML::Simple parse encloses mutiples of an element that appear in series # in a list of hashes, whereas if a single element occurs in isolation, it is # represented as a single hash. # # To make an xbone hash consistent, all elements that can appear under it more # than once in sequence are placed inside lists. ############################################################################## sub XB_XOL_xbone_list_sub ($) { my ($xbhref) = @_; my ($cmdhref, $pcmdhref, $crhref); $crhref = $xbhref->{'credential'}; # substitute for credential element XB_XOL_property_list_sub ($crhref); $cmdhref = $xbhref->{'command'}; if (defined ($pcmdhref = $cmdhref->{'create_overlay_reply'})) { XB_XOL_createovl_reply_list_sub ($pcmdhref); } elsif (defined ($pcmdhref = $cmdhref->{'create_overlay'})) { XB_XOL_createovl_list_sub ($pcmdhref); } elsif (defined ($pcmdhref = $cmdhref->{'list_overlays_reply'})) { XB_XOL_listovls_reply_list_sub ($pcmdhref); } elsif (defined ($pcmdhref = $cmdhref->{'list_overlays'})) { XB_XOL_listovls_list_sub ($pcmdhref); } elsif (defined ($pcmdhref = $cmdhref->{'overlay_status_reply'})) { XB_XOL_ovlstatus_reply_list_sub ($pcmdhref); } elsif (defined ($pcmdhref = $cmdhref->{'overlay_status'})) { XB_XOL_ovlstatus_list_sub ($pcmdhref); } elsif (defined ($pcmdhref = $cmdhref->{'discover_daemons_reply'})) { XB_XOL_discdaemons_reply_list_sub ($pcmdhref); } elsif (defined ($pcmdhref = $cmdhref->{'discover_daemons'})) { XB_XOL_discdaemons_list_sub ($pcmdhref); } elsif (defined ($pcmdhref = $cmdhref->{'destroy_overlay_reply'})) { XB_XOL_destroyovl_reply_list_sub ($pcmdhref); } elsif (defined ($pcmdhref = $cmdhref->{'destroy_overlay'})) { XB_XOL_destroyovl_list_sub ($pcmdhref); } elsif (defined ($pcmdhref = $cmdhref->{'destroyall_overlays_reply'})) { XB_XOL_destroyallovls_reply_list_sub ($pcmdhref); } elsif (defined ($pcmdhref = $cmdhref->{'destroyall_overlays'})) { XB_XOL_destroyallovls_list_sub ($pcmdhref); } elsif (defined ($pcmdhref = $cmdhref->{'host_choices_reply'})) { XB_XOL_hstchoices_reply_list_sub ($pcmdhref); } elsif (defined ($pcmdhref = $cmdhref->{'host_choices'})) { XB_XOL_hstchoices_list_sub ($pcmdhref); } elsif (defined ($pcmdhref = $cmdhref->{'error_reply'})) { XB_XOL_error_reply_list_sub ($pcmdhref); } else { die ("Unknown Xbone command"); }; }; ############################################################################## # # sub XB_XOL_property_list_sub ( parenthref ) # # parenthref is a reference to the hash of an element returned by XML::Simple. # The XML::Simple parse encloses mutiples of an element that appear in series # in a list of hashes, whereas if a single element occurs in isolation, it is # represented as a single hash. # # The data structure returned by XML::Simple is altered so that any property # element is represented as a Perl hash, with any property* or property+ # multiples gathered into a single Perl hash. ############################################################################## sub XB_XOL_property_list_sub ($) { my ($parenthref) = @_; my ($propref); if (defined ($propref = $parenthref->{property})) { # if (ref ($propref) eq 'HASH') # { # $parenthref->{property} = [ $propref ]; # embed in anonymous list # }; if (ref ($propref) eq 'ARRAY') { $parenthref->{property} = XB_XOL_collect_properties ($propref); } else { # singleton is not enclosed in list by XML::Simple $parenthref->{property} = { $propref->{tag} => $propref->{value} }; }; }; }; ############################################################################## # # sub XB_XOL_collect_properties ( lref ) # # lref is a reference to the list of property elements returned by XML::Simple. # The XML::Simple parse encloses mutiples of an element that appear in series # in a list of hashes, whereas if a single element occurs in isolation, it is # represented as a single hash. # # This routine collects all the property element prop and value attributes # into one proplist (hash) and returns a reference to it. ############################################################################## sub XB_XOL_collect_properties ($) { my ($lref) = @_; my (%plhash, $pref) = (); %plhash = (); for $pref (@$lref) { $plhash{$pref->{tag}} = $pref->{value}; }; return (\%plhash); }; ############################################################################## # # sub XB_XOL_argstring_list_sub ( parenthref ) # # parenthref is a reference to the hash of an argstring returned by XML::Simple. # The XML::Simple parse encloses mutiples of an element that appear in series # in a list of hashes, whereas if a single element occurs in isolation, it is # represented as a single hash. # # To make this element hash consistent, any argstring+ or argstring* element # it contains as a son is placed inside a list. ############################################################################## sub XB_XOL_argstring_list_sub ($) { my ($parenthref) = @_; my ($argref); if (defined ($argref = $parenthref->{'argstring'})) { if (ref ($argref) eq 'HASH') { $parenthref->{'argstring'} = [ $argref ]; # embed in anonymous list }; }; }; ############################################################################## # # sub XB_XOL_createovl_reply_list_sub ( covlrhref ) # # covlrhref is a reference to the hash of a create_overlay_reply element returned # by XML::Simple. The XML::Simple parse encloses mutiples of an element that appear # in series in a list of hashes, whereas if a single element occurs in isolation, # it is represented as a single hash. # # To make a create_overlay_reply hash consistent, all elements that can appear more # than once in sequence are placed inside lists. These elements are: # # property, node # ############################################################################## sub XB_XOL_createovl_reply_list_sub ($) { my ($covlrhref) = @_; my ($nref, $nhref, $nlref); XB_XOL_property_list_sub ($covlrhref); # substitute for any property element if (defined ($nref = $covlrhref->{'node'})) # node is optional { if (ref ($nref) eq 'HASH') { $covlrhref->{'node'} = [ $nref ]; # embedded in anonymous list }; $nlref = $covlrhref->{'node'}; foreach $nhref (@$nlref) { XB_XOL_node_list_sub ($nhref); }; # substitute in each vnode element }; }; ############################################################################## # # sub XB_XOL_createovl_list_sub ( covlhref ) # # covlhref is a reference to the hash of a create_overlay element returned by XML::Simple. # The XML::Simple parse encloses mutiples of an element that appear in series # in a list of hashes, whereas if a single element occurs in isolation, it is # represented as a single hash. # # To make a create_overlay hash consistent, all elements that can appear more than # once in sequence are placed inside lists. These elements are: # # property # ############################################################################## sub XB_XOL_createovl_list_sub ($) { my ($covlhref) = @_; my ($xolhref); XB_XOL_property_list_sub ($covlhref); # substitute for any property element $xolhref = $covlhref->{'xol_program'}; # substitute into xol_program element XB_XOL_program_list_sub ($xolhref); }; ############################################################################## # # sub XB_XOL_listovls_reply_list_sub ( lovlshref ) # # lovlshref is a reference to the hash of a list_overlays_reply element returned # by XML::Simple. The XML::Simple parse encloses mutiples of an element that # appear in series in a list of hashes, whereas if a single element occurs in # isolation, it is represented as a single hash. # # To make a list_overlays_reply hash consistent, all elements that can appear # more than once in sequence are placed inside lists. These elements are: # # property, argstring # ############################################################################## sub XB_XOL_listovls_reply_list_sub ($) { my ($lovlshref) = @_; XB_XOL_property_list_sub ($lovlshref); # substitute for any property element XB_XOL_argstring_list_sub ($lovlshref); # substitute for any argstring element }; ############################################################################## # # sub XB_XOL_listovls_list_sub ( lovlshref ) # # lovlshref is a reference to the hash of a list_overlays element returned # by XML::Simple. The XML::Simple parse encloses mutiples of an element that # appear in series in a list of hashes, whereas if a single element occurs in # isolation, it is represented as a single hash. # # To make a list_overlays hash consistent, all elements that can appear # more than once in sequence are placed inside lists. These elements are: # # property # ############################################################################## sub XB_XOL_listovls_list_sub ($) { my ($lovlshref) = @_; XB_XOL_property_list_sub ($lovlshref); # substitute for any property element }; ############################################################################## # # sub XB_XOL_ovlstatus_reply_list_sub ( ovlshref ) # # ovlshref is a reference to the hash of an overlay_status_reply element returned # by XML::Simple. The XML::Simple parse encloses mutiples of an element that # appear in series in a list of hashes, whereas if a single element occurs in # isolation, it is represented as a single hash. # # To make an overlay_status_reply hash consistent, all elements that can appear # more than once in sequence are placed inside lists. These elements are: # # property, node # ############################################################################## sub XB_XOL_ovlstatus_reply_list_sub ($) { my ($ovlshref) = @_; my ($nref, $nhref, $nlref); XB_XOL_property_list_sub ($ovlshref); # substitute for any property element if (defined ($nref = $ovlshref->{'node'})) # node is optional { if (ref ($nref) eq 'HASH') { $ovlshref->{'node'} = [ $nref ]; # embedded in anonymous list }; $nlref = $ovlshref->{'node'}; foreach $nhref (@$nlref) { XB_XOL_node_list_sub ($nhref); }; # substitute in each vnode element }; }; ############################################################################## # # sub XB_XOL_ovlstatus_list_sub ( ovlshref ) # # ovlshref is a reference to the hash of a overlay_status element returned # by XML::Simple. The XML::Simple parse encloses mutiples of an element that # appear in series in a list of hashes, whereas if a single element occurs in # isolation, it is represented as a single hash. # # To make an overlay_status hash consistent, all elements that can appear # more than once in sequence are placed inside lists. These elements are: # # property # ############################################################################## sub XB_XOL_ovlstatus_list_sub ($) { my ($ovlshref) = @_; XB_XOL_property_list_sub ($ovlshref); # substitute for any property element }; ############################################################################## # # sub XB_XOL_discdaemons_reply_list_sub ( ddshref ) # # ddshref is a reference to the hash of a discover_daemons_reply element returned # by XML::Simple. The XML::Simple parse encloses mutiples of an element that # appear in series in a list of hashes, whereas if a single element occurs in # isolation, it is represented as a single hash. # # To make a discover_daemons_reply hash consistent, all elements that can appear # more than once in sequence are placed inside lists. These elements are: # # property, node # ############################################################################## sub XB_XOL_discdaemons_reply_list_sub ($) { my ($ddshref) = @_; my ($nref, $nhref, $nlref); XB_XOL_property_list_sub ($ddshref); # substitute for any property element if (defined ($nref = $ddshref->{'node'})) # node is optional { if (ref ($nref) eq 'HASH') { $ddshref->{'node'} = [ $nref ]; # embedded in anonymous list }; $nlref = $ddshref->{'node'}; foreach $nhref (@$nlref) { XB_XOL_node_list_sub ($nhref); }; # substitute in each vnode element }; }; ############################################################################## # # sub XB_XOL_discdaemons_list_sub ( ddshref ) # # ddshref is a reference to the hash of a discover_daemons element returned # by XML::Simple. The XML::Simple parse encloses mutiples of an element that # appear in series in a list of hashes, whereas if a single element occurs in # isolation, it is represented as a single hash. # # To make a discover_daemons hash consistent, all elements that can appear # more than once in sequence are placed inside lists. These elements are: # # property # ############################################################################## sub XB_XOL_discdaemons_list_sub ($) { my ($ddshref) = @_; XB_XOL_property_list_sub ($ddshref); # substitute for any property element }; ############################################################################## # # sub XB_XOL_destroyovl_reply_list_sub ( dovlhref ) # # dovlhref is a reference to the hash of a destroy_overlay_reply element returned # by XML::Simple. The XML::Simple parse encloses mutiples of an element that # appear in series in a list of hashes, whereas if a single element occurs in # isolation, it is represented as a single hash. # # To make a destroy_overlay_reply hash consistent, all elements that can appear # more than once in sequence are placed inside lists. These elements are: # # property # ############################################################################## sub XB_XOL_destroyovl_reply_list_sub ($) { my ($dovlhref) = @_; XB_XOL_property_list_sub ($dovlhref); # substitute for any property element }; ############################################################################## # # sub XB_XOL_destroyovl_list_sub ( dovlhref ) # # dovlhref is a reference to the hash of a destroy_overlay element returned # by XML::Simple. The XML::Simple parse encloses mutiples of an element that # appear in series in a list of hashes, whereas if a single element occurs in # isolation, it is represented as a single hash. # # To make a destroy_overlay hash consistent, all elements that can appear # more than once in sequence are placed inside lists. These elements are: # # property # ############################################################################## sub XB_XOL_destroyovl_list_sub ($) { my ($dovlhref) = @_; XB_XOL_property_list_sub ($dovlhref); # substitute for any property element }; ############################################################################## # # sub XB_XOL_destroyallovls_reply_list_sub ( dovlhref ) # # dovlhref is a reference to the hash of a destroyall_overlays_reply element returned # by XML::Simple. The XML::Simple parse encloses mutiples of an element that # appear in series in a list of hashes, whereas if a single element occurs in # isolation, it is represented as a single hash. # # To make a destroyall_overlays_reply hash consistent, all elements that can appear # more than once in sequence are placed inside lists. These elements are: # # property # ############################################################################## sub XB_XOL_destroyallovls_reply_list_sub ($) { my ($dovlhref) = @_; XB_XOL_property_list_sub ($dovlhref); # substitute for any property element }; ############################################################################## # # sub XB_XOL_destroyallovls_list_sub ( dovlhref ) # # dovlhref is a reference to the hash of an deatroyall_overlays element returned # by XML::Simple. The XML::Simple parse encloses mutiples of an element that # appear in series in a list of hashes, whereas if a single element occurs in # isolation, it is represented as a single hash. # # To make a destroyall_overlays hash consistent, all elements that can appear # more than once in sequence are placed inside lists. These elements are: # # property # ############################################################################## sub XB_XOL_destroyallovls_list_sub ($) { my ($dovlhref) = @_; XB_XOL_property_list_sub ($dovlhref); # substitute for any property element }; ############################################################################## # # sub XB_XOL_hstchoices_reply_list_sub ( hchref ) # # hchref is a reference to the hash of a host_choices_reply element returned # by XML::Simple. The XML::Simple parse encloses mutiples of an element that # appear in series in a list of hashes, whereas if a single element occurs in # isolation, it is represented as a single hash. # # To make a host_choices_reply hash consistent, all elements that can appear # more than once in sequence are placed inside lists. These elements are: # # node # ############################################################################## sub XB_XOL_hstchoices_reply_list_sub ($) { my ($hchref) = @_; my ($nref, $nhref, $nlref); if (defined ($nref = $hchref->{'node'})) # node is optional { if (ref ($nref) eq 'HASH') { $hchref->{'node'} = [ $nref ]; # embedded in anonymous list }; $nlref = $hchref->{'node'}; foreach $nhref (@$nlref) { XB_XOL_node_list_sub ($nhref); }; # substitute in each vnode element }; }; ############################################################################## # # sub XB_XOL_hstchoices_list_sub ( hchref ) # # hchref is a reference to the hash of a host_choices element returned # by XML::Simple. The XML::Simple parse encloses mutiples of an element that # appear in series in a list of hashes, whereas if a single element occurs in # isolation, it is represented as a single hash. # # To make a host_choices hash consistent, all elements that can appear # more than once in sequence are placed inside lists. These elements are: # # property, node # ############################################################################## sub XB_XOL_hstchoices_list_sub ($) { my ($hchref) = @_; my ($nref, $nhref, $nlref); XB_XOL_property_list_sub ($hchref); # substitute for any property element if (defined ($nref = $hchref->{'node'})) # node is optional { if (ref ($nref) eq 'HASH') { $hchref->{'node'} = [ $nref ]; # embedded in anonymous list }; $nlref = $hchref->{'node'}; foreach $nhref (@$nlref) { XB_XOL_node_list_sub ($nhref); }; # substitute in each vnode element }; }; ############################################################################## # # sub XB_XOL_error_reply_list_sub ( errhref ) # # errhref is a reference to the hash of an error_reply element returned # by XML::Simple. The XML::Simple parse encloses mutiples of an element that # appear in series in a list of hashes, whereas if a single element occurs in # isolation, it is represented as a single hash. # # To make an error_reply hash consistent, all elements that can appear # more than once in sequence are placed inside lists. These elements are: # # property # ############################################################################## sub XB_XOL_error_reply_list_sub ($) { my ($errhref) = @_; XB_XOL_property_list_sub ($errhref); # substitute for any property element }; ############################################################################## # # sub XB_XOL_program_list_sub ( xolhref ) # # xolhref is a reference to the hash of a XOL_program element returned by # XML::Simple. The XML::Simple parse encloses mutiples of an element that appear # in series in a list of hashes, whereas if a single element occurs in isolation, # it is represented as a single hash. # # To make the xolref hash consistent, all elements that can appear more than # once in sequence are placed inside lists. These elements are: # # node_def, iface, link, property and define_prop # ############################################################################## sub XB_XOL_program_list_sub ($) { my ($xolref) = @_; my ($ndref, $eqref, $ndlref, $ndhref, $eqlref, $eqhref); ################################### # Perform substitution for node_def # and define_prop elements ################################### $ndref = $xolref->{'node_def'}; if (ref ($ndref) eq 'HASH') { $xolref->{'node_def'} = [ $ndref ]; # embedded in anonymous list }; $ndlref = $xolref->{'node_def'}; foreach $ndhref (@$ndlref) # substitute in each node_def element { XB_XOL_nodedef_list_sub ($ndhref); }; if (defined ($eqref = $xolref->{'define_prop'})) # define_prop is optional { if (ref ($eqref) eq 'HASH') { $xolref->{'define_prop'} = [ $eqref ]; # embedded in anonymous list }; # We do not substitute into define_prop elements as the property # elements there must appear once only. }; }; ############################################################################## # # sub XB_XOL_nodedef_list_sub ( ndhref ) # # ndhref is a reference to the hash of an node_def element returned by XML::Simple. # The XML::Simple parse encloses mutiples of an element that appear in series # in a list of hashes, whereas if a single element occurs in isolation, it is # represented as a single hash. # # To make an node_def hash consistent, all elements that can appear more than # once in sequence are placed inside lists. These elements are: # # iface, link, and property # ############################################################################## sub XB_XOL_nodedef_list_sub ($) { my ($ndhref) = @_; my ($ifref, $lnref, $vnref, $vnhref, $vnlref, $iflref, $ifhref, $lnlref, $lnhref); my ($aref); ################################### # Perform substitution for iface # link, vnode and property elements ################################### $ifref = $ndhref->{'iface'}; if (ref ($ifref) eq 'HASH') { $ndhref->{'iface'} = [ $ifref ]; # embedded in anonymous list }; $iflref = $ndhref->{'iface'}; foreach $ifhref (@$iflref) # substitute in each iface element { XB_XOL_iface_list_sub ($ifhref); }; if (defined ($lnref = $ndhref->{'link'})) # link is optional { if (ref ($lnref) eq 'HASH') { $ndhref->{'link'} = [ $lnref ]; # embedded in anonymous list }; $lnlref = $ndhref->{'link'}; foreach $lnhref (@$lnlref) { XB_XOL_link_list_sub ($lnhref); }; # substitute in each link element }; if (defined ($vnref = $ndhref->{'vnode'})) # vnode is optional { if (ref ($vnref) eq 'HASH') { $ndhref->{'vnode'} = [ $vnref ]; # embedded in anonymous list }; $vnlref = $ndhref->{'vnode'}; foreach $vnhref (@$vnlref) { XB_XOL_vnode_list_sub ($vnhref); }; # substitute in each vnode element }; if (defined ($aref = $ndhref->{'application'})) # application is optional { if (ref ($aref) eq 'HASH') { $ndhref->{'application'} = [ $aref ]; # embedded in anonymous list }; # dont bother if the application hash is already # an array. }; XB_XOL_property_list_sub ($ndhref); # substitute for any property element }; ############################################################################## # # sub XB_XOL_iface_list_sub ( ifhref ) # # ndhref is a reference to the hash of an iface element returned by XML::Simple. # The XML::Simple parse encloses mutiples of an element that appear in series # in a list of hashes, whereas if a single element occurs in isolation, it is # represented as a single hash. # # To make an iface hash consistent, all elements that can appear more than # once in sequence are placed inside lists. These elements are: # # property # ############################################################################## sub XB_XOL_iface_list_sub ($) { my ($ifhref) = @_; XB_XOL_property_list_sub ($ifhref); # substitute for any property element ################################ # If a renames element exists # it may have a property element ################################ if (defined ($ifhref->{'renames'})) { XB_XOL_renames_list_sub ($ifhref->{'renames'}); }; }; ############################################################################## # # sub XB_XOL_renames_list_sub ( rnhref ) # # rnhref is a reference to the hash of a renames element returned by XML::Simple. # The XML::Simple parse encloses mutiples of an element that appear in series # in a list of hashes, whereas if a single element occurs in isolation, it is # represented as a single hash. # # To make a renames hash consistent, all elements that can appear more than # once in sequence are placed inside lists. These elements are: # # property # ############################################################################## sub XB_XOL_renames_list_sub ($) { my ($rnhref) = @_; XB_XOL_property_list_sub ($rnhref); # substitute for any property element }; ############################################################################## # # sub XB_XOL_link_list_sub ( lnhref ) # # lnhref is a reference to the hash of a link element returned by XML::Simple. # The XML::Simple parse encloses mutiples of an element that appear in series # in a list of hashes, whereas if a single element occurs in isolation, it is # represented as a single hash. # # To make a link hash consistent, all elements that can appear more than # once in sequence are placed inside lists. These elements are: # # property # ############################################################################## sub XB_XOL_link_list_sub ($) { my ($lnhref) = @_; XB_XOL_property_list_sub ($lnhref); # substitute for any property element }; ############################################################################## # # sub XB_XOL_vnode_list_sub ( vnhref ) # # vnhref is a reference to the hash of a vnode element returned by XML::Simple. # The XML::Simple parse encloses mutiples of an element that appear in series # in a list of hashes, whereas if a single element occurs in isolation, it is # represented as a single hash. # # To make an vnode hash consistent, all elements that can appear more than # once in sequence are placed inside lists. These elements are: # # property # ############################################################################## sub XB_XOL_vnode_list_sub ($) { my ($vnhref) = @_; XB_XOL_property_list_sub ($vnhref); # substitute for any property element }; ############################################################################## # # sub XB_XOL_node_list_sub ( ndhref ) # # ndhref is a reference to the hash of a node element returned by XML::Simple. # The XML::Simple parse encloses mutiples of an element that appear in series # in a list of hashes, whereas if a single element occurs in isolation, it is # represented as a single hash. # # To make a node hash consistent, all elements that can appear more than # once in sequence are placed inside lists. These elements are: # # property, tunnel # ############################################################################## sub XB_XOL_node_list_sub ($) { my ($ndhref) = @_; my ($tnref, $tnhref, $tnlref); XB_XOL_property_list_sub ($ndhref); # substitute for any property element if (defined ($tnref = $ndhref->{'tunnel'})) { if (ref ($tnref) eq 'HASH') { $ndhref->{'tunnel'} = [ $tnref ]; # embedded in anonymous list }; $tnlref = $ndhref->{'tunnel'}; foreach $tnhref (@$tnlref) { XB_XOL_tunnel_list_sub ($tnhref); # substitute into tunnel elements }; }; }; ############################################################################## # # sub XB_XOL_tunnel_list_sub ( tnhref ) # # tnhref is a reference to the hash of a tunnel element returned by XML::Simple. # The XML::Simple parse encloses mutiples of an element that appear in series # in a list of hashes, whereas if a single element occurs in isolation, it is # represented as a single hash. # # To make a tunnel hash consistent, all elements that can appear more than # once in sequence are placed inside lists. These elements are: # # property # ############################################################################## sub XB_XOL_tunnel_list_sub ($) { my ($tnhref) = @_; XB_XOL_property_list_sub ($tnhref); # substitute for any property element }; ############################################################################## # # sub XB_XOL_synonym_sub ( xolref, eqlref ) # # Recursively descends through an XML::Simple hash structure for an xol_program # element that is referenced by xolref. eqlref references a list of define_prop # elements. Property elements in the xolref hash are examined for property # elements that have a key field, but no value field. In such a case the # key is assumed to be a synonym for some define_prop element definition. # # The matching define_prop property element is substituted in place for the synonym. # If no match is found, an error occurs. # # Returns an empty string "" if the substitution pass succeeds. # Otherwise, an error string is returned. # # NOTE: This routine MUST be called AFTER the routine XB_XOL_xbone_list_sub () # has operated on the xolref hash. ############################################################################## sub XB_XOL_synonym_sub ($$) { no warnings; # recursive, so prototype causes warnings my ($xolref, $eqlref) = @_; my ($type, $retval); $type = ref ($xolref); if ($type eq 'HASH') { my ($name); foreach $name (keys (%$xolref)) { if ($name eq 'define_prop') # don't substitute into the definitions { next; } elsif ($name eq 'property') { $retval = XB_XOL_properties_perform_substitution ($xolref->{$name}, $eqlref); if ($retval) { return $retval; }; } else { $retval = XB_XOL_synonym_sub ($xolref->{$name}, $eqlref); if ($retval) { return $retval; }; }; }; } elsif ($type eq 'ARRAY') { my ($lelmt); foreach $lelmt (@$xolref) { $retval = XB_XOL_synonym_sub ($lelmt, $eqlref); if ($retval) { return $retval; }; }; }; return ''; # Successful return is empty string, i.e. FALSE }; ############################################################################## # # sub XB_XOL_properties_perform_substitution ( href, eqlref ) # # Examines hash of tag/value key pairs passed in href that are associated # with a property element hash returned by XML::Simple. If a tag/value pair # is missing its value key, the key is assumed to be a synonym. This synonym # is presumed to be defined in some define_prop element definition in the list # referenced by eqlref. # # Matching define_prop tag/value key pairs are substituted in place for # each synonym encountered. If no match is found, an error occurs. # # Returns an empty string "" if the substitution pass succeeds. # Otherwise, an error string is returned. ############################################################################## sub XB_XOL_properties_perform_substitution ($$) { my ($href, $eqlref) = @_; my ($key); foreach $key (keys (%$href)) { if (!defined ($href->{$key})) # no 'value' implies synonym substitution { my ($eqpref); $eqpref = XB_XOL_define_prop_find ($eqlref, $key); if (!defined ($eqpref)) { return ("property $key has no matching define_prop synonym"); }; ######################## # Apply the substitution ######################## $href->{$key} = $eqpref->{value}; }; }; }; ############################################################################## # # sub XB_XOL_define_prop_find ( eqlref, synonym ) # # Searches the define_prop element referenced by eqlref for a matching synonym. # # Returns a reference to the matching property list hash if a match is found. # Otherwise, undef is returned. ############################################################################## sub XB_XOL_define_prop_find ($$) { my ($eqlref, $synonym) = @_; my ($synhref, $result); ##################### # eqlref references # a list of proplists ##################### $result = undef; foreach $synhref (@$eqlref) { if ((defined ($synhref->{'synonym'})) && ($synonym eq $synhref->{'synonym'})) { $result = $synhref->{'property'}; last; }; }; return ($result); } ############################################################################## # # sub XB_XML_choose_parse_error ( errorstrings ) # # errorstrings contains the errors returned by a call to LibXML::parse_string() # The last line containing an "error:" string are returned. ############################################################################## sub XB_XML_choose_parse_error ($) { my ($errorstrings) = @_; my (@lines, $line, $string, $ix); @lines = split /\n/, $errorstrings; $string = 'No error: found in LibXML::parse_string() response.'; $ix = 0; while (defined ($lines[$ix])) { $_ = $lines[$ix]; if (/error:/is) { $string = "$lines[$ix]\n"; }; $ix++; }; return ($string); } #my $msg = ''; # #my $file = 'test1.xml'; ##my $file = 'example.ring.xol'; # #open(FILE, $file) || die ("\nCannot open the file: $file.\n"); #while () { $msg .= $_; }; #close(FILE); # #$_ = XB_XML_parse (\$msg); # #if (!$_) # { print "\n\nSUCCESSFUL PARSE\n\n"; } #else # { # print "\n\nFAILURE:\n$_\n$_\n\n"; # $_ = XB_XML_choose_parse_error ($_); # print "CHOSEN ERROR STRING: $_\n\n"; # exit (1); # }; # #my $href = XB_XML_hash (\$msg); #$_ = Dumper ($href); #print "\n\nHASH:\n\n$_\n\n"; # # #my ($cmdhref, $covlhref, $xolhref); # #$cmdhref = $href->{'command'}; #$covlhref = $cmdhref->{'create_overlay'}; #$xolhref = $covlhref->{'xol_program'}; # ##XB_XOL_createovl_list_sub ($covlhref); # #XB_XOL_xbone_list_sub ($href); # #$_ = Dumper ($href); #print "\n\nXOL PROGRAM LIST SUBSTITUTED:\n\n$_\n\n"; # #XB_XOL_synonym_sub ($href, $xolhref->{'define_prop'}); # #$_ = Dumper ($href); #print "\n\nXOL PROGRAM SYNONYMS SUBSTITUTED:\n\n$_\n\n"; 1; # Insure TRUE return if module is interpreted.