Icon for Dimension.orgIcon for TalentIcon for ToolsIcon for Doorways.org
Icon for ToolsIcon for Perl Tools

MMAgic Demo: MMAgic.pl Source File

  • Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

MMAgic.pl

Go to the documentation of this file.
00001 #!/usr/bin/perl
00002 #
00003 =head1 NAME
00004 
00005 MMAgic.pl - Demonstrate use of various MMAgic packages.
00006 
00007 =head1 SYNOPSIS
00008 
00009     usage: MMAgic.pl <flag>* <file>
00010     <flag>
00011         --curse         # cause endless recursion in process() function
00012         --show          # show object parsed from input file before conversion
00013         --trace=<tag>   # trace processing for SUBS and/or DETAIL
00014                         #   (can be used multiple times)
00015 
00016 =head1 DESCRIPTION
00017 
00018 Simple program to convert a configuration file in Perl data structure code
00019 into WDDX (XML data exchange format) format.
00020 
00021 The real purpose of this script is to demonstrate the use of selected
00022 <tt>MMAgic</tt> libraries from my personal toolkit.
00023 
00024 =over
00025 
00026 =item MMAgic::Data
00027 
00028 Loads data from a file that written in Perl data structure syntax.
00029 This is done by simply evaluating the contents of the file using the Perl interpreter.
00030 The <tt>Safe</tt> module is used to lock down the kinds of operations that the
00031 interpreter will parse, in an attempt to make this mechanism safe.
00032 
00033 =item MMAgic::Log
00034 
00035 Tagged log statements in a consistent format.
00036 Uses indentable output stream to show stack depth context of log statements.
00037 Provides data dump formats and subroutine information as required.
00038 
00039 =item MMAgic::Output
00040 
00041 Indentable output stream used by Log.pm.
00042 Also used to generate nicely formatted WDDX output in this example.
00043 
00044 =item MMAgic::Trace
00045 
00046 Filter-based trace mechanism.
00047 When disabled, trace statements are merely comments,
00048 so there is no run-time penalty.
00049 
00050 =back
00051 
00052 =head1 EXAMPLES
00053 
00054     MMAgic.pl                                        # usage message
00055     MMAgic.pl demo/book.data                         # working example
00056     MMAgic.pl demo/time.data                         # bad data file error
00057     MMAgic.pl demo/oops.data                         # non-existent data file
00058     MMAgic.pl demo/book.data --trace=SUBS            # see trace statements
00059     MMAgic.pl demo/book.data --trace=SUBS --trace=DETAIL
00060     MMAgic.pl demo/book.data --trace=SUBS --curse    # endless recursion
00061 
00062 =head1 METHODS
00063 
00064 =over
00065 
00066 =cut
00067 
00068 use     strict;
00069 use     warnings;
00070 use     UNIVERSAL   qw(isa);
00071 
00072 use     FindBin;
00073 use     File::Basename;
00074 use     Getopt::Long;
00075 use     Pod::Usage;
00076 
00077 use lib $FindBin::Bin;
00078 
00079 use     MMAgic::Data;
00080 use     MMAgic::Log;
00081 use     MMAgic::Trace;
00082 
00083 our %option;
00084 
00085 ###########################################################################
00086 
00087 =item   C<process($data, $stream)>
00088 
00089 Recursively process the data object to generate WDDX output.
00090 
00091 =cut
00092 
00093 #=| \param  $data   Data structure from which to generate WDDX output.
00094 #=| \param  $stream MMAgic::Output stream on which to generate WDDX output
00095 
00096 sub process
00097     {
00098     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00099     # MMAgic Demo:
00100     #   The Log->method() mechanism looks up the stack for the function name.
00101     #   The block() call returns an indentation object that causes
00102     #   automagic indentation of output log and pops indent when
00103     #   the indentation object is destroyed at the end of the function.
00104     #   Can't do that in Java!!!
00105     # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00106 #!# my  $auto   = Log->method(@_)->block;                       #[SUBS]
00107     my  $data   = shift;
00108     my  $stream = shift;
00109 
00110     if (isa($data, 'HASH'))
00111         {
00112 #!#     Log->trace('Found HASH object');                        #[DETAIL]
00113         $stream->print("<struct>\n")->pushIndent;
00114         
00115         map {
00116             $stream->print("<var name='$_'>\n")->pushIndent;
00117                 process($data->{$_}, $stream);
00118             $stream->popIndent->print("</var>\n");
00119             } keys %$data;
00120 
00121         $stream->popIndent->print("</struct>\n");
00122         }
00123 
00124     elsif (isa($data, 'ARRAY'))
00125         {
00126 #!#     Log->trace('Found ARRAY object');                       #[DETAIL]
00127         $stream->print("<array length='", scalar(@$data), "'>\n")->pushIndent;
00128         
00129         map {
00130             process($_, $stream);
00131             } @$data;
00132 
00133         $stream->popIndent->print("</array>\n");
00134         }
00135     
00136     elsif (ref($data))
00137         {
00138         # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00139         # MMAgic Demo:
00140         #   Not interpolating the object allows the Log mechanism
00141         #   to handle various aberrant cases, such as undef:
00142         # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00143         Log->warning('Unknown data object:  ', $data);
00144         $stream->print("<string>Error converting:  $data</string>\n");
00145         }
00146 
00147     elsif (! defined($data))
00148         {
00149 #!#     Log->trace('Found undefined object');                   #[DETAIL]
00150         $stream->print("<null/>\n");
00151         }
00152     
00153     elsif ($data =~ /[-+]?\d+(?:\.\d+)?/)
00154         {
00155 #!#     Log->trace('Found numeric object');                     #[DETAIL]
00156         $stream->print('<number>', $data, "</number>\n");
00157         }
00158     
00159     else
00160         {
00161         # By default it must be a string (or printable as such):
00162 #!#     Log->trace('Found string object');                      #[DETAIL]
00163         $stream->print('<string>', $data, "</string>\n");
00164         
00165         if ($option{curse})
00166             {
00167             # Simulate an infinite recursion error:
00168             process($data, $stream);
00169             }
00170         }
00171     }
00172 
00173 ###########################################################################
00174 ###########################################################################
00175 #
00176 # Main program.
00177 #
00178 
00179 # Parameter parsing using standard Perl packages:
00180 
00181 pod2usage(2)
00182     unless GetOptions(\%option, qw(curse! show trace=s help));
00183 
00184 pod2usage(1)
00185     if $option{help};
00186 
00187 pod2usage('No files specified for conversion')
00188     unless @ARGV;
00189 
00190 $option{file} = shift @ARGV;
00191 
00192 Log->crash('Non-existent file ', $option{file})
00193     unless -f $option{file};
00194 
00195 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00196 # MMAgic Demo:
00197 #   Setup error logging...
00198 #   MMAgic::Output provides an indentable output stream.
00199 #   MMAgic::Log adds useful logging functions and a class-level interface.
00200 #   It also places a timestamp and a log type on each line:
00201 #
00202 #       2002/05/13 19:06:30 [E] error message
00203 #       2002/05/13 19:06:30 [W] warning message
00204 #       2002/05/13 19:06:30 [T] trace statement
00205 #       2002/05/13 19:06:30 [I] informational message
00206 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00207 
00208 Log->handle;    # Initiate __WARN__ and __DIE__ handlers
00209                 #   which redirect to current Log.
00210 
00211 ###########################################################################
00212 
00213 Log->info('Starting ', $0);
00214 
00215 my  $data;
00216 
00217 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00218 # MMAgic Demo:
00219 #   Open input file as a MMAgic::Data object.
00220 #   MMAgic::Data actually evaluates the file contents which are
00221 #   in Perl data structure syntax within a Safe context to
00222 #   prevent execution of unauthorized code.
00223 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00224 
00225 tie $data, 'MMAgic::Data', $option{file};
00226 
00227 Log->trace('Actual object:')->display($data)
00228     if $option{show};
00229 
00230 my ($name, $path, $suff) = fileparse($option{file}, '\.[^\.]*');
00231 
00232 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00233 # MMAgic Demo:
00234 #   Open output file as MMAgic::Output stream which supports indentation.
00235 #   Indentation supports makes it easier to generate readable WDDX output.
00236 # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00237 
00238 my  $wddx = new MMAgic::Output(pathname => "$path$name.wddx");
00239 
00240 # Generate the WDDX output:
00241 
00242 $wddx->print(<<WDDX_HDR);
00243 <?xml version='1.0'?>
00244 <!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
00245 
00246 <wddxPacket version='1.0'>
00247   <header/>
00248 
00249   <data>
00250 WDDX_HDR
00251 
00252 $wddx->pushIndent(4);
00253     process($data, $wddx);
00254 $wddx->popIndent;
00255 
00256 $wddx->print(<<WDDX_FTR);
00257   </data>
00258 </wddxPacket>
00259 WDDX_FTR
00260 
00261 Log->info('Finished ', $0);
00262 
00263 __END__
00264 
00265 =back
00266 
00267 =head1 AUTHOR
00268 
00269 Marc M. Adkins, L<mailto:Perl@Doorways.org>
00270 
00271 =head1 COPYRIGHT AND LICENSE
00272 
00273 Copyright 2004-2008 by Marc M. Adkins
00274 
00275 =cut

Generated on Mon Dec 27 2010 15:15:42 for MMAgic Demo by  doxygen 1.7.1

www.dimension.org logo

(C)opyright 1998 - 2012 Dimension.org

WebMaster