home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / Template.pm < prev    next >
Encoding:
Perl POD Document  |  2003-12-03  |  43.2 KB  |  1,318 lines

  1. #============================================================= -*-perl-*-
  2. #
  3. # Apache::Template
  4. #
  5. # DESCRIPTION
  6. #   Apache/mod_perl handler for the Template Toolkit.
  7. #
  8. # AUTHOR
  9. #   Andy Wardley <abw@wardley.org>
  10. #
  11. # COPYRIGHT
  12. #   Copyright (C) 1996-2003 Andy Wardley.  All Rights Reserved.
  13. #   Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
  14. #
  15. #   This module is free software; you can redistribute it and/or
  16. #   modify it under the same terms as Perl itself.
  17. #
  18. # REVISION
  19. #   $Id: Template.pm,v 1.4 2002/03/12 14:10:25 abw Exp $
  20. #
  21. #========================================================================
  22.  
  23. package Apache::Template;
  24.  
  25. use strict;
  26. use vars qw( $VERSION $DEBUG $ERROR $SERVICE );
  27.  
  28. use mod_perl 1.99_11;     # sanity check for a recent version
  29.  
  30. use Apache::RequestRec ();
  31. use Apache::Module ();
  32. use Apache::Log ();
  33. use Apache::RequestIO ();
  34. use Apache::Const -compile => qw(OK SERVER_ERROR TAKE1 TAKE12 FLAG
  35.                                  ITERATE TAKE2 RSRC_CONF ACCESS_CONF);
  36.  
  37. use Template::Service::Apache;
  38. use Template::Config;
  39.  
  40. $VERSION = '2.00_01';
  41. $ERROR   = '';
  42. $DEBUG   = 0 unless defined $DEBUG;
  43. $Template::Config::SERVICE = 'Template::Service::Apache';
  44.  
  45. our @APACHE_MODULE_COMMANDS = (
  46.     #-- parsing/style options --
  47.     {   name         => 'TT2Tags',
  48.         errmsg       => 'tag style or start and end tags for template directives',
  49.         args_how     => Apache::TAKE12,
  50.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  51.     },
  52.     {   name         => 'TT2PreChomp',
  53.         errmsg       => 'flag to remove newline and whitespace before directives',
  54.         args_how     => Apache::FLAG,
  55.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  56.     },
  57.     {   name         => 'TT2PostChomp',
  58.         errmsg       => 'flag to remove newline and whitespace after directives',
  59.         args_how     => Apache::FLAG,
  60.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  61.     },
  62.     {   name         => 'TT2Trim',
  63.         errmsg       => 'flag to trim whitespace surrounding template output',
  64.         args_how     => Apache::FLAG,
  65.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  66.     },
  67.     {   name         => 'TT2AnyCase',
  68.         errmsg       => 'flag to allow directive keywords in any case',
  69.         args_how     => Apache::FLAG,
  70.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  71.     },
  72.     {   name         => 'TT2Interpolate',
  73.         errmsg       => 'flag to interpolate embedded variable references',
  74.         args_how     => Apache::FLAG,
  75.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  76.     },
  77.  
  78.     #-- file/directory options --
  79.     {   name         => 'TT2IncludePath',
  80.         errmsg       => 'local path(s) containing templates',
  81.         args_how     => Apache::ITERATE,
  82.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  83.     },
  84.     {   name         => 'TT2Absolute',
  85.         errmsg       => 'flag to enable absolute filenames',
  86.         args_how     => Apache::FLAG,
  87.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  88.     },
  89.     {   name         => 'TT2Relative',
  90.         errmsg       => 'flag to enable relative filenames',
  91.         args_how     => Apache::FLAG,
  92.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  93.     },
  94.     {   name         => 'TT2Delimiter',
  95.         errmsg       => 'alternative directory delimiter',
  96.         args_how     => Apache::TAKE1,
  97.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  98.     },
  99.  
  100.     #-- service template options --
  101.     {   name         => 'TT2PreProcess',
  102.         errmsg       => 'template(s) to process before each main template',
  103.         args_how     => Apache::ITERATE,
  104.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  105.     },
  106.     {   name         => 'TT2PostProcess',
  107.         errmsg       => 'template(s) to process after each main template',
  108.         args_how     => Apache::ITERATE,
  109.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  110.     },
  111.     {   name         => 'TT2Process',
  112.         errmsg       => 'template(s) to process instead of each main template',
  113.         args_how     => Apache::ITERATE,
  114.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  115.     },
  116.     {   name         => 'TT2Wrapper',
  117.         errmsg       => 'template(s) to wrap around each main template',
  118.         args_how     => Apache::ITERATE,
  119.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  120.     },
  121.     {   name         => 'TT2Default',
  122.         errmsg       => 'default template to process when another template is not found',
  123.         args_how     => Apache::TAKE1,
  124.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  125.     },
  126.     {   name         => 'TT2Error',
  127.         errmsg       => 'template to process when an uncaught error occurs',
  128.         args_how     => Apache::TAKE1,
  129.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  130.     },
  131.     {   name         => 'TT2Tolerant',
  132.         errmsg       => 'flag to set error tolerance for providers',
  133.         args_how     => Apache::FLAG,
  134.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  135.     },
  136.  
  137.     #-- variable options --
  138.     {   name         => 'TT2Variable',
  139.         errmsg       => 'define a template variable',
  140.         args_how     => Apache::TAKE2,
  141.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  142.     },
  143.     {   name         => 'TT2Constant',
  144.         errmsg       => 'define a constant variable',
  145.         args_how     => Apache::TAKE2,
  146.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  147.     },
  148.     {   name         => 'TT2ConstantsNamespace',
  149.         errmsg       => 'define variable namespace for constants',
  150.         args_how     => Apache::TAKE1,
  151.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  152.     },
  153.  
  154.     #-- runtime template processing options --
  155.     {   name         => 'TT2EvalPerl',
  156.         errmsg       => 'flag to allow PERL blocks to be evaluated',
  157.         args_how     => Apache::FLAG,
  158.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  159.     },
  160.     {   name         => 'TT2LoadPerl',
  161.         errmsg       => 'flag to allow regular Perl modules to be loaded as plugins',
  162.         args_how     => Apache::FLAG,
  163.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  164.     },
  165.     {   name         => 'TT2Recursion',
  166.         errmsg       => 'flag to enable recursion into templates',
  167.         args_how     => Apache::FLAG,
  168.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  169.     },
  170.  
  171.     #-- plugin and filter options --
  172.     {   name         => 'TT2PluginBase',
  173.         errmsg       => 'packages in which to locate for plugins',
  174.         args_how     => Apache::ITERATE,
  175.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  176.     },
  177.  
  178.     #-- caching options --
  179.     {   name         => 'TT2AutoReset',
  180.         errmsg       => 'flag to reset (clear) any BLOCK definitions before processing',
  181.         args_how     => Apache::TAKE1,
  182.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  183.     },
  184.     {   name         => 'TT2CacheSize',
  185.         errmsg       => 'integer limit to the number of compiled templates to cache in memory',
  186.         args_how     => Apache::TAKE1,
  187.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  188.     },
  189.     {   name         => 'TT2CompileExt',
  190.         errmsg       => 'filename extension for caching compiled templates back to disk',
  191.         args_how     => Apache::TAKE1,
  192.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  193.     },
  194.     {   name         => 'TT2CompileDir',
  195.         errmsg       => 'path to directory for caching compiled templates back to disk',
  196.         args_how     => Apache::TAKE1,
  197.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  198.     },
  199.  
  200.     #-- misc options --
  201.     {   name         => 'TT2Debug',
  202.         errmsg       => 'flag to enable debugging',
  203.         args_how     => Apache::FLAG,
  204.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  205.     },
  206.  
  207.     # -- service options --
  208.     {   name         => 'TT2Headers',
  209.         errmsg       => 'list of keywords indicating HTTP headers to add',
  210.         args_how     => Apache::ITERATE,
  211.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  212.     },
  213.     {   name         => 'TT2Params',
  214.         errmsg       => 'list of keywords indicating parameters to add as template variables',
  215.         args_how     => Apache::ITERATE,
  216.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  217.     },
  218.     {   name         => 'TT2ServiceModule',
  219.         errmsg       => 'name of class which implements template service module',
  220.         args_how     => Apache::TAKE1,
  221.         req_override => Apache::RSRC_CONF | Apache::ACCESS_CONF,
  222.     },
  223. );
  224.  
  225. #------------------------------------------------------------------------
  226. # handler($request)
  227. #
  228. # Main Apache/mod_perl content handler which delegates to an
  229. # underlying Template::Service::Apache object.  A service is created that
  230. # is unique to the hostname (e.g. to support multiple configurations for 
  231. # virtual hosts).  This is created and stored in the $SERVICE hash and 
  232. # then reused across requests to the same hostname.  This allows compiled 
  233. # templates to be cached and re-used without requiring re-compilation.  
  234. # The service implements 4 methods for different phases of the request:
  235. #
  236. #   template($request)            # fetch a compiled template
  237. #   params($request)              # build parameter set (template vars)
  238. #   process($template, $params)   # process template
  239. #   headers($request, $template, \$content)
  240. #                                 # set and send http headers
  241. #------------------------------------------------------------------------
  242.  
  243. sub handler {
  244.     my $r = shift;
  245.  
  246.     # create and cache a service for each hostname
  247.     my $service = $SERVICE->{ $r->hostname() } ||= do {
  248.         my $cfg = Apache::Module->get_config(__PACKAGE__, 
  249.                                              $r->server,
  250.                                              $r->per_dir_config) || { };
  251.         warn "setup service for hostname: ", $r->hostname, "  ($cfg):\n", 
  252.              dump_hash($cfg), "\n" if $DEBUG;
  253.         Template::Config->service($cfg) || do {
  254.             $r->log_error(Template::Config->error(), ' ', $r->filename());
  255.             return Apache::SERVER_ERROR;
  256.         };
  257.     };
  258.  
  259.     my $template = $service->template($r);
  260.     return $template unless ref $template;
  261.  
  262.     my $params = $service->params($r);
  263.     return $params unless ref $params;
  264.  
  265.     my $content = $service->process($template, $params);
  266.     unless (defined $content) {
  267.         $r->log_error($service->error(), ' ', $r->filename());
  268.         return Apache::SERVER_ERROR;
  269.     }
  270.  
  271.     $service->headers($r, $template, \$content);
  272.  
  273.     $r->print($content);
  274.  
  275.     return Apache::OK;
  276. }
  277.  
  278.  
  279. #========================================================================
  280. # Configuration Handlers
  281. #========================================================================
  282.  
  283. #------------------------------------------------------------------------
  284. # TT2Tags html          # specify TAG_STYLE
  285. # TT2Tags [* *]         # specify START_TAG and END_TAG
  286. #------------------------------------------------------------------------
  287.  
  288. sub TT2Tags($$$$) {
  289.     my ($cfg, $parms, $start, $end) = @_;
  290.     if (defined $end and length $end) {
  291.         $cfg->{ START_TAG } = quotemeta($start);
  292.         $cfg->{ END_TAG   } = quotemeta($end);
  293.     }
  294.     else {
  295.         $cfg->{ TAG_STYLE } = $start;
  296.     }
  297. }
  298.  
  299. #------------------------------------------------------------------------
  300. # TT2PreChomp On        # enable PRE_CHOMP
  301. #------------------------------------------------------------------------
  302.  
  303. sub TT2PreChomp($$$) {
  304.     my ($cfg, $parms, $on) = @_;
  305.     $cfg->{ PRE_CHOMP } = $on;
  306. }
  307.  
  308. #------------------------------------------------------------------------
  309. # TT2PostChomp On       # enable POST_CHOMP
  310. #------------------------------------------------------------------------
  311.  
  312. sub TT2PostChomp($$$) {
  313.     my ($cfg, $parms, $on) = @_;
  314.     $cfg->{ POST_CHOMP } = $on;
  315. }
  316.  
  317. #------------------------------------------------------------------------
  318. # TT2Trim On            # enable TRIM
  319. #------------------------------------------------------------------------
  320.  
  321. sub TT2Trim($$$) {
  322.     my ($cfg, $parms, $on) = @_;
  323.     $cfg->{ TRIM } = $on;
  324. }
  325.  
  326. #------------------------------------------------------------------------
  327. # TT2AnyCase On         # enable ANYCASE
  328. #------------------------------------------------------------------------
  329.  
  330. sub TT2AnyCase($$$) {
  331.     my ($cfg, $parms, $on) = @_;
  332.     $cfg->{ ANYCASE } = $on;
  333. }
  334.  
  335. #------------------------------------------------------------------------
  336. # TT2Interpolate On     # enable INTERPOLATE
  337. #------------------------------------------------------------------------
  338.  
  339. sub TT2Interpolate($$$) {
  340.     my ($cfg, $parms, $on) = @_;
  341.     $cfg->{ INTERPOLATE } = $on;
  342. }
  343.  
  344. #------------------------------------------------------------------------
  345. # TT2Tolerant On        # enable TOLERANT
  346. #------------------------------------------------------------------------
  347.  
  348. sub TT2Tolerant($$$) {
  349.     my ($cfg, $parms, $on) = @_;
  350.     $cfg->{ TOLERANT } = $on;
  351. }
  352.  
  353. #------------------------------------------------------------------------
  354. # TT2IncludePath /here /there   # define INCLUDE_PATH directories
  355. # TT2IncludePath /elsewhere     # additional INCLUDE_PATH directories
  356. #------------------------------------------------------------------------
  357.  
  358. sub TT2IncludePath($$@) {
  359.     my ($cfg, $parms, $path) = @_;
  360.     my $incpath = $cfg->{ INCLUDE_PATH } ||= [ ];
  361.     push(@$incpath, $path);
  362. }
  363.  
  364. #------------------------------------------------------------------------
  365. # TT2Absolute On        # enable ABSOLUTE file paths
  366. #------------------------------------------------------------------------
  367.  
  368. sub TT2Absolute($$$) {
  369.     my ($cfg, $parms, $on) = @_;
  370.     $cfg->{ ABSOLUTE } = $on;
  371. }
  372.  
  373. #------------------------------------------------------------------------
  374. # TT2Relative On        # enable RELATIVE file paths
  375. #------------------------------------------------------------------------
  376.  
  377. sub TT2Relative($$$) {
  378.     my ($cfg, $parms, $on) = @_;
  379.     $cfg->{ RELATIVE } = $on;
  380. }
  381.  
  382. #------------------------------------------------------------------------
  383. # TT2Delimiter ,        # set alternate directory delimiter
  384. #------------------------------------------------------------------------
  385.  
  386. sub TT2Delimiter($$$) {
  387.     my ($cfg, $parms, $delim) = @_;
  388.     $cfg->{ DELIMITER } = $delim;
  389. }
  390.  
  391. #------------------------------------------------------------------------
  392. # TT2PreProcess config header   # define PRE_PROCESS templates
  393. # TT2PreProcess menu            # additional PRE_PROCESS templates
  394. #------------------------------------------------------------------------
  395.  
  396. sub TT2PreProcess($$@) {
  397.     my ($cfg, $parms, $file) = @_;
  398.     my $preproc = $cfg->{ PRE_PROCESS } ||= [ ];
  399.     push(@$preproc, $file);
  400. }
  401.  
  402. #------------------------------------------------------------------------
  403. # TT2Process main1 main2    # define PROCESS templates
  404. # TT2Process main3          # additional PROCESS template
  405. #------------------------------------------------------------------------
  406.  
  407. sub TT2Process($$@) {
  408.     my ($cfg, $parms, $file) = @_;
  409.     my $process = $cfg->{ PROCESS } ||= [ ];
  410.     push(@$process, $file);
  411. }
  412.  
  413. #------------------------------------------------------------------------
  414. # TT2Wrapper main1 main2    # define WRAPPER templates
  415. # TT2Wrapper main3          # additional WRAPPER template
  416. #------------------------------------------------------------------------
  417.  
  418. sub TT2Wrapper($$@) {
  419.     my ($cfg, $parms, $file) = @_;
  420.     my $wrapper = $cfg->{ WRAPPER } ||= [ ];
  421.     push(@$wrapper, $file);
  422. }
  423.  
  424. #------------------------------------------------------------------------
  425. # TT2PostProcess menu copyright # define POST_PROCESS templates
  426. # TT2PostProcess footer         # additional POST_PROCESS templates
  427. #------------------------------------------------------------------------
  428.  
  429. sub TT2PostProcess($$@) {
  430.     my ($cfg, $parms, $file) = @_;
  431.     my $postproc = $cfg->{ POST_PROCESS } ||= [ ];
  432.     push(@$postproc, $file);
  433. }
  434.  
  435. #------------------------------------------------------------------------
  436. # TT2Default notfound       # define DEFAULT template
  437. #------------------------------------------------------------------------
  438.  
  439. sub TT2Default($$$) {
  440.     my ($cfg, $parms, $file) = @_;
  441.     $cfg->{ DEFAULT } = $file;
  442. }
  443.  
  444. #------------------------------------------------------------------------
  445. # TT2Error error        # define ERROR template
  446. #------------------------------------------------------------------------
  447.  
  448. sub TT2Error($$$) {
  449.     my ($cfg, $parms, $file) = @_;
  450.     $cfg->{ ERROR } = $file;
  451. }
  452.  
  453. #------------------------------------------------------------------------
  454. # TT2EvalPerl On        # enable EVAL_PERL
  455. #------------------------------------------------------------------------
  456.  
  457. sub TT2EvalPerl($$$) {
  458.     my ($cfg, $parms, $on) = @_;
  459.     $cfg->{ EVAL_PERL } = $on;
  460. }
  461.  
  462. #------------------------------------------------------------------------
  463. # TT2LoadPerl On        # enable LOAD_PERL
  464. #------------------------------------------------------------------------
  465.  
  466. sub TT2LoadPerl($$$) {
  467.     my ($cfg, $parms, $on) = @_;
  468.     $cfg->{ LOAD_PERL } = $on;
  469. }
  470.  
  471. #------------------------------------------------------------------------
  472. # TT2Recursion On       # enable RECURSION
  473. #------------------------------------------------------------------------
  474.  
  475. sub TT2Recursion($$$) {
  476.     my ($cfg, $parms, $on) = @_;
  477.     $cfg->{ RECURSION } = $on;
  478. }
  479.  
  480. #------------------------------------------------------------------------
  481. # TT2PluginBase My::Plugins     # define PLUGIN_BASE package(s)
  482. # TT2PluginBase Your::Plugin    # additional PLUGIN_BASE package(s)
  483. #------------------------------------------------------------------------
  484.  
  485. sub TT2PluginBase($$@) {
  486.     my ($cfg, $parms, $base) = @_;
  487.     my $pbases = $cfg->{ PLUGIN_BASE } ||= [ ];
  488.     push(@$pbases, $base);
  489. }
  490.  
  491. #------------------------------------------------------------------------
  492. # TT2AutoReset Off      # disable AUTO_RESET
  493. #------------------------------------------------------------------------
  494.  
  495. sub TT2AutoReset($$$) {
  496.     my ($cfg, $parms, $on) = @_;
  497.     $cfg->{ AUTO_RESET } = $on;
  498. }
  499.  
  500. #------------------------------------------------------------------------
  501. # TT2CacheSize 128      # define CACHE_SIZE
  502. #------------------------------------------------------------------------
  503.  
  504. sub TT2CacheSize($$$) {
  505.     my ($cfg, $parms, $size) = @_;
  506.     $cfg->{ CACHE_SIZE } = $size;
  507. }
  508.  
  509. #------------------------------------------------------------------------
  510. # TT2CompileExt .tt2        # define COMPILE_EXT
  511. #------------------------------------------------------------------------
  512.  
  513. sub TT2CompileExt($$$) {
  514.     my ($cfg, $parms, $ext) = @_;
  515.     $cfg->{ COMPILE_EXT } = $ext;
  516. }
  517.  
  518. #------------------------------------------------------------------------
  519. # TT2CompileDir /var/tt2/cache  # define COMPILE_DIR
  520. #------------------------------------------------------------------------
  521.  
  522. sub TT2CompileDir($$$) {
  523.     my ($cfg, $parms, $dir) = @_;
  524.     $cfg->{ COMPILE_DIR } = $dir;
  525. }
  526.  
  527. #------------------------------------------------------------------------
  528. # TT2Debug On           # enable DEBUG
  529. #------------------------------------------------------------------------
  530.  
  531. sub TT2Debug($$$) {
  532.     my ($cfg, $parms, $on) = @_;
  533.     $cfg->{ DEBUG } = $DEBUG = $on;
  534. }
  535.  
  536. #------------------------------------------------------------------------
  537. # TT2Headers length etag        # add certain HTTP headers
  538. #------------------------------------------------------------------------
  539.  
  540. sub TT2Headers($$@) {
  541.     my ($cfg, $parms, $item) = @_;
  542.     my $headers = $cfg->{ SERVICE_HEADERS } ||= [ ];
  543.     push(@$headers, $item);
  544. }
  545.  
  546. #------------------------------------------------------------------------
  547. # TT2Params uri env pnotes uploads request            # add template vars
  548. #------------------------------------------------------------------------
  549.  
  550. sub TT2Params($$@) {
  551.     my ($cfg, $parms, $item) = @_;
  552.     my $params = $cfg->{ SERVICE_PARAMS } ||= [ ];
  553.     push(@$params, $item);
  554. }
  555.  
  556. #------------------------------------------------------------------------
  557. # TT2ServiceModule   My::Service::Class     # custom service module
  558. #------------------------------------------------------------------------
  559.  
  560. sub TT2ServiceModule($$$) {
  561.     my ($cfg, $parms, $module) = @_;
  562.     $Template::Config::SERVICE = $module;
  563. }
  564.  
  565. #------------------------------------------------------------------------
  566. # TT2Variable name value       # define template variable
  567. #------------------------------------------------------------------------
  568.  
  569. sub TT2Variable($$$$) {
  570.     my ($cfg, $parms, $name, $value) = @_;
  571.     $cfg->{ VARIABLES }->{ $name } = $value;
  572. }
  573.  
  574. #------------------------------------------------------------------------
  575. # TT2Constant   foo  bar
  576. #------------------------------------------------------------------------
  577.  
  578. sub TT2Constant($$@@) {
  579.     my ($cfg, $parms, $name, $value) = @_;
  580.     my $constants = $cfg->{ CONSTANTS } ||= { };
  581.     $constants->{ $name } = $value;
  582. }
  583.  
  584. #------------------------------------------------------------------------
  585. # TT2ConstantsNamespace const
  586. #------------------------------------------------------------------------
  587.  
  588. sub TT2ConstantsNamespace($$$) {
  589.     my ($cfg, $parms, $namespace) = @_;
  590.     $cfg->{ CONSTANTS_NAMESPACE } = $namespace;
  591. }
  592.  
  593.  
  594.  
  595. #========================================================================
  596. # Configuration creators/mergers
  597. #========================================================================
  598.  
  599. my $dir_counter = 1;        # used for debugging/testing of problems
  600. my $srv_counter = 1;        # with SERVER_MERGE and DIR_MERGE
  601.  
  602. sub SERVER_CREATE {
  603.     my $class  = shift;
  604.     my $config = bless { }, $class;
  605.     warn "SERVER_CREATE($class) => $config\n" if $DEBUG;
  606.     return $config;
  607. }
  608.  
  609. sub SERVER_MERGE {
  610.     my ($parent, $config) = @_;
  611.     my $merged = _merge($parent, $config);
  612.     
  613.     if ($DEBUG) {
  614.         $merged->{ counter } = $srv_counter;
  615.         warn "\nSERVER_MERGE #" . $srv_counter++ . "\n" 
  616.             . "$parent\n" . dump_hash($parent) . "\n+\n"
  617.             . "$config\n" . dump_hash($config) . "\n=\n"
  618.             . "$merged\n" . dump_hash($merged) . "\n";
  619.     }
  620.     return $merged;
  621. }
  622.  
  623. sub DIR_CREATE {
  624.     my $class  = shift;
  625.     my $config = bless { }, $class;
  626.     warn "DIR_CREATE($class) => $config\n" if $DEBUG;
  627.     return $config;
  628. }
  629.  
  630. sub DIR_MERGE {
  631.     my ($parent, $config) = @_;
  632.     my $merged = _merge($parent, $config);
  633.     if ($DEBUG) {
  634.         $merged->{ counter } = $dir_counter;
  635.         warn "\nDIR_MERGE #" . $dir_counter++ . "\n" 
  636.             . "$parent\n" . dump_hash($parent) . "\n+\n"
  637.             . "$config\n" . dump_hash($config) . "\n=\n"
  638.             . "$merged\n" . dump_hash($merged) . "\n";
  639.     }
  640.     return $merged;
  641. }
  642.  
  643.  
  644. sub _merge {
  645.     my ($parent, $config) = @_;
  646.  
  647.     # let's not merge with ourselves.
  648.     # it's not.. umm.. natural.
  649.     return $config if $parent eq $config;
  650.     
  651.     my $merged = bless { }, ref($parent);
  652.   
  653.     foreach my $key (keys %$parent) {
  654.         if(!ref $parent->{$key}) {
  655.             $merged->{$key} = $parent->{$key};
  656.         } 
  657.         elsif (ref $parent->{$key} eq 'ARRAY') {
  658.             $merged->{$key} = [ @{$parent->{$key}} ];
  659.         } 
  660.         elsif (ref $parent->{$key} eq 'HASH') {
  661.             $merged->{$key} = { %{$parent->{$key}} };
  662.         } 
  663.         elsif (ref $parent->{$key} eq 'SCALAR') {
  664.             $merged->{$key} = \${$parent->{$key}};
  665.         }
  666.     }
  667.     
  668.     foreach my $key (keys %$config) {
  669.         if(!ref $config->{$key}) {
  670.             $merged->{$key} = $config->{$key};
  671.         } 
  672.         elsif (ref $config->{$key} eq 'ARRAY') {
  673.             push @{$merged->{$key} ||= []}, @{$config->{$key}};
  674.         } 
  675.         elsif (ref $config->{$key} eq 'HASH') {
  676.             $merged->{$key} = { %{$merged->{$key}}, %{$config->{$key}} };
  677.         } 
  678.         elsif (ref $config->{$key} eq 'SCALAR') {
  679.             $merged->{$key} = \${$config->{$key}};
  680.         }
  681.     }
  682.     return $merged;
  683. }
  684.  
  685.  
  686. # debug methods for testing problems with DIR_MERGE, etc.
  687.  
  688. sub dump_hash {
  689.     my $hash = shift;
  690.     my $out = "  {\n";
  691.  
  692.     while (my($key, $value) = (each %$hash)) {
  693.         $value = "[ @$value ]" if ref $value eq 'ARRAY';
  694.         $out .= "      $key => $value\n";
  695.     }
  696.     $out .= "  }";
  697. }
  698.  
  699. sub dump_hash_html {
  700.     my $hash = dump_hash(shift);
  701.     for ($hash) {
  702.         s/>/>/g;
  703.         s/\n/<br>/g;
  704.         s/ / /g;
  705.     }
  706.     return $hash;
  707. }
  708.  
  709.     
  710. 1;
  711.  
  712. __END__
  713.  
  714. =head1 NAME
  715.  
  716. Apache::Template - Apache/mod_perl interface to the Template Toolkit
  717.  
  718. =head1 SYNOPSIS
  719.  
  720.     # add the following to your httpd.conf
  721.     PerlModule          Apache::Template
  722.  
  723.     # set various configuration options, e.g.
  724.     TT2Trim             On
  725.     TT2PostChomp        On
  726.     TT2EvalPerl         On
  727.     TT2IncludePath      /usr/local/tt2/templates
  728.     TT2IncludePath      /home/abw/tt2/lib
  729.     TT2PreProcess       config header
  730.     TT2PostProcess      footer
  731.     TT2Error            error
  732.  
  733.     # now define Apache::Template as a PerlHandler, e.g.
  734.     <Files *.tt2>
  735.         SetHandler      perl-script
  736.         PerlHandler     Apache::Template
  737.     </Files>
  738.  
  739.     <Location /tt2>
  740.         SetHandler      perl-script
  741.         PerlHandler     Apache::Template
  742.     </Location>
  743.  
  744. =head1 DESCRIPTION
  745.  
  746. The Apache::Template module provides a simple interface to the
  747. Template Toolkit from Apache/mod_perl.  The Template Toolkit is a
  748. fast, powerful and extensible template processing system written in
  749. Perl.  It implements a general purpose template language which allows
  750. you to clearly separate application logic, data and presentation
  751. elements.  It boasts numerous features to facilitate in the generation
  752. of web content both online and offline in "batch mode".
  753.  
  754. This documentation describes the Apache::Template module, concerning
  755. itself primarily with the Apache/mod_perl configuration options
  756. (e.g. the httpd.conf side of things) and not going into any great
  757. depth about the Template Toolkit itself.  The Template Toolkit
  758. includes copious documentation which already covers these things in
  759. great detail.  See L<Template> and L<Template::Manual> for further
  760. information.
  761.  
  762. =head1 CONFIGURATION
  763.  
  764. Most of the Apache::Template configuration directives relate directly
  765. to their Template Toolkit counterparts, differing only in having a
  766. 'TT2' prefix, mixed capitalisation and lack of underscores to space
  767. individual words.  This is to keep Apache::Template configuration
  768. directives in keeping with the preferred Apache/mod_perl style.
  769.  
  770. e.g.
  771.  
  772.     Apache::Template  =>  Template Toolkit
  773.     --------------------------------------
  774.     TT2Trim               TRIM
  775.     TT2IncludePath        INCLUDE_PATH
  776.     TT2PostProcess        POST_PROCESS
  777.     ...etc...
  778.  
  779. In some cases, the configuration directives are named or behave
  780. slightly differently to optimise for the Apache/mod_perl environment
  781. or domain specific features.  For example, the TT2Tags configuration
  782. directive can be used to set TAG_STYLE and/or START_TAG and END_TAG
  783. and as such, is more akin to the Template Toolkit TAGS directive.
  784.  
  785. e.g.
  786.  
  787.     TT2Tags     html
  788.     TT2Tags     <!--  -->
  789.  
  790. The configuration directives are listed in full below.  Consult 
  791. L<Template> for further information on their effects within the 
  792. Template Toolkit.
  793.  
  794. =over 4
  795.  
  796. =item TT2Tags
  797.  
  798. Used to set the tags used to indicate Template Toolkit directives
  799. within source templates.  A single value can be specified to 
  800. indicate a TAG_STYLE, e.g.
  801.  
  802.     TT2Tags     html
  803.  
  804. A pair of values can be used to indicate a START_TAG and END_TAG.
  805.  
  806.     TT2Tags     <!--    -->
  807.  
  808. Note that, unlike the Template Toolkit START_TAG and END_TAG
  809. configuration options, these values are automatically escaped to
  810. remove any special meaning within regular expressions.
  811.  
  812.     TT2Tags     [*  *]  # no need to escape [ or *
  813.  
  814. By default, the start and end tags are set to C<[%> and C<%]>
  815. respectively.  Thus, directives are embedded in the form: 
  816. [% INCLUDE my/file %].
  817.  
  818. =item TT2PreChomp
  819.  
  820. Equivalent to the PRE_CHOMP configuration item.  This flag can be set
  821. to have removed any whitespace preceeding a directive, up to and
  822. including the preceeding newline.  Default is 'Off'.
  823.  
  824.     TT2PreChomp     On
  825.  
  826. =item TT2PostChomp
  827.  
  828. Equivalent to the POST_CHOMP configuration item.  This flag can be set
  829. to have any whitespace after a directive automatically removed, up to 
  830. and including the following newline.  Default is 'Off'.
  831.  
  832.     TT2PostChomp    On
  833.  
  834. =item TT2Trim
  835.  
  836. Equivalent to the TRIM configuration item, this flag can be set
  837. to have all surrounding whitespace stripped from template output.
  838. Default is 'Off'.
  839.  
  840.     TT2Trim         On
  841.  
  842. =item TT2AnyCase
  843.  
  844. Equivalent to the ANY_CASE configuration item, this flag can be set
  845. to allow directive keywords to be specified in any case.  By default,
  846. this setting is 'Off' and all directive (e.g. 'INCLUDE', 'FOREACH', 
  847. etc.) should be specified in UPPER CASE only.
  848.  
  849.     TT2AnyCase      On
  850.  
  851. =item TT2Interpolate
  852.  
  853. Equivalent to the INTERPOLATE configuration item, this flag can be set
  854. to allow simple variables of the form C<$var> to be embedded within
  855. templates, outside of regular directives.  By default, this setting is
  856. 'Off' and variables must appear in the form [% var %], or more explicitly,
  857. [% GET var %].
  858.  
  859.     TT2Interpolate  On
  860.  
  861. =item TT2IncludePath
  862.  
  863. Equivalent to the INCLUDE_PATH configuration item.  This can be used
  864. to specify one or more directories in which templates are located.
  865. Multiple directories may appear on each TT2IncludePath directive line,
  866. and the directive may be repeated.  Directories are searched in the 
  867. order defined.
  868.  
  869.     TT2IncludePath  /usr/local/tt2/templates
  870.     TT2InludePath   /home/abw/tt2   /tmp/tt2
  871.  
  872. Note that this only affects templates which are processed via
  873. directive such as INCLUDE, PROCESS, INSERT, WRAPPER, etc.  The full
  874. path of the main template processed by the Apache/mod_perl handler is
  875. generated (by Apache) by appending the request URI to the
  876. DocumentRoot, as per usual.  For example, consider the following
  877. configuration extract:
  878.  
  879.     DocumentRoot    /usr/local/web/ttdocs
  880.     [...]
  881.     TT2IncludePath  /usr/local/tt2/templates
  882.  
  883.     <Files *.tt2>
  884.     SetHandler  perl-script
  885.         PerlHandler     Apache::Template
  886.     </Files>
  887.  
  888. A request with a URI of '/foo/bar.tt2' will cause the handler to
  889. process the file '/usr/local/web/ttdocs/foo/bar.tt2' (i.e.
  890. DocumentRoot + URI).  If that file should include a directive such
  891. as [% INCLUDE foo/bar.tt2 %] then that template should exist as the
  892. file '/usr/local/tt2/templates/foo/bar.tt2' (i.e. TT2IncludePath + 
  893. template name).
  894.  
  895. =item TT2Absolute
  896.  
  897. Equivalent to the ABSOLUTE configuration item, this flag can be enabled
  898. to allow templates to be processed (via INCLUDE, PROCESS, etc.) which are
  899. specified with absolute filenames.
  900.  
  901.     TT2Absolute     On
  902.  
  903. With the flag enabled a template directive of the form:
  904.  
  905.     [% INCLUDE /etc/passwd %]
  906.  
  907. will be honoured.  The default setting is 'Off' and any attempt to
  908. load a template by absolute filename will result in a 'file' exception
  909. being throw with a message indicating that the ABSOLUTE option is not
  910. set.  See L<Template> for further discussion on exception handling.
  911.  
  912. =item TT2Relative
  913.  
  914. Equivalent to the RELATIVE configuration item.  This is similar to the 
  915. TT2Absolute option, but relating to files specified with a relative filename,
  916. that is, starting with './' or '../'
  917.  
  918.     TT2Relative On
  919.  
  920. Enabling the option permits templates to be specifed as per this example:
  921.  
  922.     [% INCLUDE ../../../etc/passwd %]
  923.  
  924. As with TT2Absolute, this option is set 'Off', causing a 'file' exception
  925. to be thrown if used in this way.
  926.  
  927. =item TT2Delimiter
  928.  
  929. Equivalent to the DELIMTER configuration item, this can be set to define 
  930. an alternate delimiter for separating multiple TT2IncludePath options.
  931. By default, it is set to ':', and thus multiple directories can be specified
  932. as:
  933.  
  934.     TT2IncludePath  /here:/there
  935.  
  936. Note that Apache implicitly supports space-delimited options, so the
  937. following is also valid and defines 3 directories, /here, /there and
  938. /anywhere.
  939.  
  940.     TT2IncludePath  /here:/there /anywhere
  941.  
  942. If you're unfortunate enough to be running Apache on a Win32 system and 
  943. you need to specify a ':' in a path name, then set the TT2Delimiter to 
  944. an alternate value to avoid confusing the Template Toolkit into thinking
  945. you're specifying more than one directory:
  946.  
  947.     TT2Delimiter    ,
  948.     TT2IncludePath  C:/HERE D:/THERE E:/ANYWHERE
  949.  
  950. =item TT2PreProcess
  951.  
  952. Equivalent to PRE_PROCESS, this option allows one or more templates to
  953. be named which should be processed before the main template.  This can
  954. be used to process a global configuration file, add canned headers,
  955. etc.  These templates should be located in one of the TT2IncludePath
  956. directories, or specified absolutely if the TT2Absolute option is set.
  957.  
  958.     TT2PreProcess   config header
  959.  
  960. =item TT2PostProcess
  961.  
  962. Equivalent to POST_PROCESS, this option allow one or more templates to
  963. be named which should be processed after the main template, e.g. to
  964. add standard footers.  As per TTPreProcess, these should be located in
  965. one of the TT2IncludePath directories, or specified absolutely if the
  966. TT2Absolute option is set.
  967.  
  968.     TT2PostProcess  copyright footer
  969.  
  970. =item TT2Process
  971.  
  972. This is equivalent to the PROCESS configuration item.  It can be used
  973. to specify one or more templates to be process instead of the main
  974. template.  This can be used to apply a standard "wrapper" around all
  975. template files processed by the handler.
  976.  
  977.     TT2Process      mainpage
  978.  
  979. The original template (i.e. whose path is formed from the DocumentRoot
  980. + URI, as explained in the L<TT2IncludePath|TT2IncludePath> item
  981. above) is preloaded and available as the 'template' variable.  This a 
  982. typical TT2Process template might look like:
  983.  
  984.     [% PROCESS header %]
  985.     [% PROCESS $template %] 
  986.     [% PROCESS footer %]
  987.  
  988. Note the use of the leading '$' on template to defeat the auto-quoting
  989. mechanism which is applied to INCLUDE, PROCESS, etc., directives.  The
  990. directive would otherwise by interpreted as:
  991.  
  992.     [% PROCESS "template" %]
  993.  
  994. =item TT2Wrapper
  995.  
  996. This is equivalent to the WRAPPER configuration item.  It can be used
  997. to specify one or more templates to be wrapped around the content 
  998. generated by processing the main page template.
  999.  
  1000.     TT2Wrapper      sitewrap
  1001.  
  1002. The original page template is processed first.  The wrapper template
  1003. is then processed, with the C<content> variable containing the output
  1004. generated by processing the main page template.
  1005.  
  1006. Multiple wrapper templates can be specified.  For example, to wrap each
  1007. page in the F<layout> template, and then to wrap that in the F<htmlpage> 
  1008. template, you would write:
  1009.  
  1010.     TT2Wrapper htmlpage layout
  1011.  
  1012. Or:
  1013.  
  1014.     TT2Wrapper htmlpage
  1015.     TT2Wrapper layout
  1016.  
  1017. Note that the TT2Wrapper options are specified in "outside-in" order 
  1018. (i.e. the outer wrapper, followed by the inner wrapper).  However, 
  1019. they are processed in reverse "inside-out" order (i.e. the page content,
  1020. followed by the inner wrapper, followed by the outer wrapper).
  1021.  
  1022. =item TT2Default
  1023.  
  1024. This is equivalent to the DEFAULT configuration item.  This can be
  1025. used to name a template to be used in place of a missing template
  1026. specified in a directive such as INCLUDE, PROCESS, INSERT, etc.  Note
  1027. that if the main template is not found (i.e. that which is mapped from
  1028. the URI) then the handler will decline the request, resulting in a 404
  1029. - Not Found.  The template specified should exist in one of the 
  1030. directories named by TT2IncludePath.
  1031.  
  1032.     TT2Default      nonsuch
  1033.  
  1034. =item TT2Error
  1035.  
  1036. This is equivalent to the ERROR configuration item.  It can be
  1037. used to name a template to be used to report errors that are otherwise
  1038. uncaught.  The template specified should exist in one of the 
  1039. directories named by TT2IncludePath.  When the error template is 
  1040. processed, the 'error' variable will be set to contain the relevant
  1041. error details.
  1042.  
  1043.     TT2Error        error
  1044.  
  1045. =item TT2Variable
  1046.  
  1047. This option allows you to define values for simple template variables.
  1048. If you have lots of variables to define then you'll probably want to 
  1049. put them in a config template and pre-process it with TT2PreProcess.
  1050.  
  1051.     TT2Variable     version  3.14
  1052.  
  1053. =item TT2Constant
  1054.  
  1055. This option allows you to define values for constants.  These are
  1056. similar to regular TT variables, but are resolved once when the
  1057. template is compiled.
  1058.  
  1059.     TT2Constant     pi  3.14
  1060.  
  1061. =item TT2ConstantsNamespace
  1062.  
  1063. Constants are accessible via the 'constants' namespace by default (e.g.
  1064. [% constants.pi %].  This option can be used to provide an alternate
  1065. namespace for constants.
  1066.  
  1067.     TT2ConstantNamespace  my
  1068.  
  1069. =item TT2EvalPerl
  1070.  
  1071. This is equivalent to the EVAL_PERL configuration item.  It can be
  1072. enabled to allow embedded [% PERL %] ... [% END %] sections
  1073. within templates.  It is disabled by default and any PERL sections
  1074. encountered will raise 'perl' exceptions with the message 'EVAL_PERL
  1075. not set'.
  1076.  
  1077.     TT2EvalPerl     On
  1078.  
  1079. =item TT2LoadPerl
  1080.  
  1081. This is equivalent to the LOAD_PERL configuration item which allows
  1082. regular Perl modules to be loaded as Template Toolkit plugins via the 
  1083. USE directive.  It is set 'Off' by default.
  1084.  
  1085.     TT2LoadPerl     On
  1086.  
  1087. =item TT2Recursion
  1088.  
  1089. This is equivalent to the RECURSION option which allows templates to
  1090. recurse into themselves either directly or indirectly.  It is set
  1091. 'Off' by default.
  1092.  
  1093.     TT2Recursion    On
  1094.  
  1095. =item TT2PluginBase
  1096.  
  1097. This is equivalent to the PLUGIN_BASE option.  It allows multiple 
  1098. Perl packages to be specified which effectively form a search path
  1099. for loading Template Toolkit plugins.  The default value is 
  1100. 'Template::Plugin'.
  1101.  
  1102.     TT2PluginBase   My::Plugins  Your::Plugins
  1103.  
  1104. =item TT2AutoReset
  1105.  
  1106. This is equivalent to the AUTO_RESET option and is enabled by default.
  1107. It causes any template BLOCK definitions to be cleared before each
  1108. main template is processed.
  1109.  
  1110.     TT2AutoReset    Off
  1111.  
  1112. =item TT2CacheSize
  1113.  
  1114. This is equivalent to the CACHE_SIZE option.  It can be used to limit 
  1115. the number of compiled templates that are cached in memory.  The default
  1116. value is undefined and all compiled templates will be cached in memory.
  1117. It can be set to a specified numerical value to define the maximum
  1118. number of templates, or to 0 to disable caching altogether.
  1119.  
  1120.     TT2CacheSize    64
  1121.  
  1122. =item TT2CompileExt
  1123.  
  1124. This is equivalent to the COMPILE_EXT option.  It can be used to
  1125. specify a filename extension which the Template Toolkit will use for
  1126. writing compiled templates back to disk, thus providing cache
  1127. persistance.
  1128.  
  1129.     TT2CompileExt   .ttc
  1130.  
  1131. =item TT2CompileDir
  1132.  
  1133. This is equivalent to the COMPILE_DIR option.  It can be used to
  1134. specify a root directory under which compiled templates should be 
  1135. written back to disk for cache persistance.  Any TT2IncludePath 
  1136. directories will be replicated in full under this root directory.
  1137.  
  1138.     TT2CompileDir   /var/tt2/cache
  1139.  
  1140. =item TT2Debug
  1141.  
  1142. This is equivalent to the DEBUG option which enables Template Toolkit
  1143. debugging.  The main effect is to raise additional warnings when
  1144. undefined variables are used but is likely to be expanded in a future
  1145. release to provide more extensive debugging capabilities.
  1146.  
  1147.     TT2Debug        On
  1148.  
  1149. =item TT2Tolerant
  1150.  
  1151. This is equivalent to the TOLERANT option which makes the Template
  1152. Toolkit providers tolerant to errors.
  1153.  
  1154.     TT2Tolerant     On
  1155.  
  1156. =item TT2Headers
  1157.  
  1158. Allows you to specify which HTTP headers you want added to the 
  1159. response.  Current permitted values are: 'modified' (Last-Modified),
  1160. 'length' (Content-Length), 'etag' (E-Tag) or 'all' (all the above).
  1161.  
  1162.     TT2Headers      all
  1163.  
  1164. =item TT2Params
  1165.  
  1166. Allows you to specify which parameters you want defined as template
  1167. variables.  Current permitted values are 'uri', 'env' (hash of
  1168. environment variables), 'params' (hash of CGI parameters), 'pnotes'
  1169. (the request pnotes hash), 'cookies' (hash of cookies), 'uploads' (a
  1170. list of Apache::Upload instances), 'request' (the Apache::Request
  1171. object) or 'all' (all of the above).
  1172.  
  1173.     TT2Params       uri env params uploads request
  1174.  
  1175. When set, these values can then be accessed from within any 
  1176. template processed:
  1177.  
  1178.     The URI is [% uri %]
  1179.  
  1180.     Server name is [% env.SERVER_NAME %]
  1181.  
  1182.     CGI params are:
  1183.     <table>
  1184.     [% FOREACH key = params.keys %]
  1185.        <tr>
  1186.      <td>[% key %]</td>  <td>[% params.$key %]</td>
  1187.        </tr>
  1188.     [% END %]
  1189.     </table>
  1190.  
  1191. =item TT2ServiceModule
  1192.  
  1193. The modules have been designed in such a way as to make it easy to
  1194. subclass the Template::Service::Apache module to create your own
  1195. custom services.  
  1196.  
  1197. For example, the regular service module does a simple 1:1 mapping of
  1198. URI to template using the request filename provided by Apache, but
  1199. you might want to implement an alternative scheme.  You might prefer,
  1200. for example, to map multiple URIs to the same template file, but to
  1201. set some different template variables along the way.  
  1202.  
  1203. To do this, you can subclass Template::Service::Apache and redefine
  1204. the appropriate methods.  The template() method performs the task of
  1205. mapping URIs to templates and the params() method sets up the template
  1206. variable parameters.  Or if you need to modify the HTTP headers, then
  1207. headers() is the one for you.
  1208.  
  1209. The TT2ServiceModule option can be set to indicate the name of your
  1210. custom service module.  The following trivial example shows how you
  1211. might subclass Template::Service::Apache to add an additional parameter,
  1212. in this case as the template variable 'message'.
  1213.  
  1214.     <perl>
  1215.     package My::Service::Module;
  1216.     use base qw( Template::Service::Apache );
  1217.  
  1218.     sub params {
  1219.     my $self = shift;
  1220.         my $params = $self->SUPER::params(@_);
  1221.         $params->{ message } = 'Hello World';
  1222.         return $params;
  1223.     }
  1224.     </perl>
  1225.  
  1226.     PerlModule          Apache::Template
  1227.     TT2ServiceModule    My::Service::Module
  1228.  
  1229. =back
  1230.  
  1231. =head1 CONFIGURATION MERGING
  1232.  
  1233. The Apache::Template module creates a separate service for each
  1234. virtual server.  Each virtual server can have its own configuration.
  1235. Any globally defined options will be merged with any server-specific 
  1236. ones.  
  1237.  
  1238. The following examples illustrates two separate virtual servers being
  1239. configured in one Apache configuration file.
  1240.  
  1241.     PerlModule        Apache::Template
  1242.     TT2IncludePath    /usr/local/tt2/templates
  1243.     TT2Params       request params
  1244.     TT2Wrapper      html/page
  1245.  
  1246.     NameVirtualHost 127.0.0.1
  1247.  
  1248.     <VirtualHost 127.0.0.1>
  1249.         ServerName     shoveit
  1250.         SetHandler     perl-script
  1251.         PerlHandler    Apache::Template
  1252.         TT2Wrapper     layout_a
  1253.     </VirtualHost>
  1254.  
  1255.     <VirtualHost 127.0.0.1>
  1256.        ServerName     kickflip
  1257.        SetHandler     perl-script
  1258.        PerlHandler    Apache::Template
  1259.        TT2Wrapper     layout_b
  1260.     </VirtualHost>
  1261.  
  1262. In this example, the C<shoveit> virtual host will be configured as if written:
  1263.  
  1264.     PerlModule        Apache::Template
  1265.     TT2IncludePath    /usr/local/tt2/templates
  1266.     TT2Params       request params
  1267.     TT2Wrapper      html/page
  1268.     TT2Wrapper      layout_a
  1269.  
  1270. The second C<TTWrapper> option (C<layout_a>) is added to the shared
  1271. configuration block.
  1272.  
  1273. The C<kickflip> virtual host will be configured as if written:
  1274.  
  1275.     PerlModule        Apache::Template
  1276.     TT2IncludePath    /usr/local/tt2/templates
  1277.     TT2Params       request params
  1278.     TT2Wrapper      html/page
  1279.     TT2Wrapper      layout_b
  1280.  
  1281. Here, the C<layout_b> wrapper template is used instead of C<layout_a>.
  1282.  
  1283. Apache::Template does not correctly handle different configurations for
  1284. separate directories, location or files within the same virtual server.
  1285.  
  1286. =head1 AUTHOR
  1287.  
  1288. Andy Wardley E<lt>abw@wardley.orgE<gt>
  1289.  
  1290. This module has been derived in part from the 'Grover' module by
  1291. Darren Chamberlain (darren@boston.com).  Darren kindly donated his
  1292. code for integration into the Apache::Template module.
  1293.  
  1294. =head1 VERSION
  1295.  
  1296. This is version 2.00_01 of the Apache::Template module.
  1297.  
  1298. =head1 COPYRIGHT
  1299.  
  1300.     Copyright (C) 1996-2003 Andy Wardley.  All Rights Reserved.
  1301.     Copyright (C) 1998-2002 Canon Research Centre Europe Ltd.
  1302.  
  1303. This module is free software; you can redistribute it and/or
  1304. modify it under the same terms as Perl itself.
  1305.  
  1306. =head1 SEE ALSO
  1307.  
  1308. For further information about the Template Toolkit, see L<Template>
  1309. or http://www.template-toolkit.org/
  1310.  
  1311. =cut
  1312.  
  1313. # Local Variables:
  1314. # mode: perl
  1315. # perl-indent-level: 4
  1316. # indent-tabs-mode: nil
  1317. # End:
  1318.