mach 2003/10/20 13:58:02
Modified: . Tag: axkit-pipeline-2 MANIFEST lib/Apache/AxKit Tag: axkit-pipeline-2 Cache.pm lib/Apache/AxKit/Language Tag: axkit-pipeline-2 HtmlDoc.pm LibXSLT.pm XSP.pm t/conf Tag: axkit-pipeline-2 extra.last.conf.in t/xslt-basic Tag: axkit-pipeline-2 02_include.t Added: lib/Apache/AxKit Tag: axkit-pipeline-2 Pipeline.pm lib/Apache/AxKit/Pipeline Tag: axkit-pipeline-2 Cache.pm Head.pm Language.pm LibXSLT.pm Trace.pm Transformer.pm XSP.pm t/htdocs/pipeline/cache Tag: axkit-pipeline-2 01.xml t/htdocs/style/pipeline/cache Tag: axkit-pipeline-2 01.xsl t/pipeline Tag: axkit-pipeline-2 01cache.t Log: Big commit of new pipeline code. Lots of new shiny pipeline modules. Minor changes to some Language::* modules (will be ported eventually), changes to Cache.pm adding dependancy checking. Test and Enjoy. Revision Changes Path No revision No revision 1.20.2.1 +10 -1 xml-axkit/MANIFEST Index: MANIFEST =================================================================== RCS file: /home/cvs/xml-axkit/MANIFEST,v retrieving revision 1.20 retrieving revision 1.20.2.1 diff -u -r1.20 -r1.20.2.1 --- MANIFEST 19 Oct 2003 16:09:36 -0000 1.20 +++ MANIFEST 20 Oct 2003 20:58:01 -0000 1.20.2.1 @@ -157,6 +157,12 @@ lib/Apache/AxKit/Provider/FileWrite.pm lib/Apache/AxKit/Provider/Filter.pm lib/Apache/AxKit/Provider/Scalar.pm +lib/Apache/AxKit/Pipeline.pm +lib/Apache/AxKit/Pipeline/Trace.pm +lib/Apache/AxKit/Pipeline/XSP.pm +lib/Apache/AxKit/Pipeline/LibXSLT.pm +lib/Apache/AxKit/Pipeline/Cache.pm +lib/Apache/AxKit/Pipeline/Language.pm lib/Apache/AxKit/StyleChooser/Cookie.pm lib/Apache/AxKit/StyleChooser/FileSuffix.pm lib/Apache/AxKit/StyleChooser/PathInfo.pm @@ -208,5 +214,8 @@ t/htdocs/uri/axkit/subrequest.xml t/htdocs/style/uri/axkit/01.xsl t/htdocs/style/uri/axkit/subrequest.xsl - +t/htdocs/pipeline/cache/01.xml +t/htdocs/style/pipeline/cache +t/htdocs/style/pipeline/cache/01.xsl +t/pipeline/01cache.t typemap No revision No revision 1.12.2.1 +120 -51 xml-axkit/lib/Apache/AxKit/Cache.pm Index: Cache.pm =================================================================== RCS file: /home/cvs/xml-axkit/lib/Apache/AxKit/Cache.pm,v retrieving revision 1.12 retrieving revision 1.12.2.1 diff -u -r1.12 -r1.12.2.1 --- Cache.pm 3 Oct 2003 18:38:38 -0000 1.12 +++ Cache.pm 20 Oct 2003 20:58:01 -0000 1.12.2.1 @@ -1,5 +1,3 @@ -# $Id$ - package Apache::AxKit::Cache; use strict; @@ -72,14 +70,15 @@ } my $self = bless { - apache => $r, - key => $key, - no_cache => $no_cache, - dir => $cachedir, - file => "$cachedir/$primary/$secondary/$key", - gzip => $gzip, + apache => $r, + key => $key, + no_cache => $no_cache, + dir => $cachedir, + file => "$cachedir/$primary/$secondary/$key", + gzip => $gzip, + depends => {}, # extras => [EMAIL PROTECTED], - }, $class; + }, $class; if (my $alternate = $AxKit::Cfg->CacheModule()) { AxKit::reconsecrate($self, $alternate); @@ -108,8 +107,10 @@ sub write { my $self = shift; + my ($content, $encoding) = @_; + $content = ref($content) ? $$content : $content; return if $self->{no_cache}; - my $encoding = $_[1] || 'raw'; + $encoding ||= 'raw'; AxKit::Debug(7, "[Cache] writing cache file $self->{file}"); my $fh = Apache->gensym(); my $tmp_filename = $self->{file}."new$$"; @@ -117,7 +118,7 @@ # flock($fh, LOCK_EX); # seek($fh, 0, 0); # truncate($fh, 0); - print $fh $_[0]; + print $fh $content; close $fh; rename($tmp_filename, $self->{file}) || throw Apache::AxKit::Exception::IO( -text => "Couldn't rename cachefile: $!"); @@ -125,11 +126,21 @@ else { throw Apache::AxKit::Exception::IO( -text => "Couldn't open cachefile for writing: $!"); } + + if (AxKit::sysopen($fh, $tmp_filename, O_WRONLY|O_CREAT, 'raw')) { + print $fh join("\n", keys %{$self->{'depends'}}); + close $fh; + rename($tmp_filename, $self->{file}.'.depends') + || throw Apache::AxKit::Exception::IO( -text => "Couldn't rename cachefile: $!"); + } + else { + throw Apache::AxKit::Exception::IO( -text => "Couldn't open cachefile for writing: $!"); + } if ($self->{gzip} && $AxKit::Cfg->GzipOutput) { AxKit::Debug(3, "Creating gzip output cache: $self->{file}.gz"); if (my $gz = gzopen($self->{file}.'new.gz', "wb")) { - $gz->gzwrite($_[0]); + $gz->gzwrite($content); $gz->gzclose(); rename($self->{file}.'new.gz', $self->{file}.'.gz') || throw Apache::AxKit::Exception::IO( -text => "Couldn't rename gzipped cachefile: $!"); @@ -141,22 +152,25 @@ } sub read { - my $self = shift; - return if $self->{no_cache}; + my ($self) = @_; my $encoding = $_[0] || 'raw'; - my $fh = Apache->gensym(); - if (AxKit::sysopen($fh, $self->{file}, O_RDONLY, $encoding)) { - flock($fh, LOCK_SH); - local $/; - return <$fh>; - # close($fh); - # close unlocks automatically + return if $self->{no_cache}; + if($self->check_dependencies()) { + my $fh = Apache->gensym(); + if (AxKit::sysopen($fh, $self->{file}, O_RDONLY, $encoding)) { + flock($fh, LOCK_SH); + local $/; + return <$fh>; + # close($fh); + # close unlocks automatically + } } - return ''; + return undef; } sub get_fh { my $self = shift; + warn("cache get_fh called"); return if $self->{no_cache}; my $fh = Apache->gensym(); if (AxKit::sysopen($fh, $self->{file}, O_RDONLY, 'raw')) { @@ -203,7 +217,9 @@ sub deliver { my $self = shift; - return SERVER_ERROR if $self->{no_cache}; + Apache::AxKit::Exception::Error->throw( + -text => 'attempt to deliver from cache when no cache set' + ) if $self->{no_cache}; my $r = $self->{apache}; { @@ -215,46 +231,99 @@ } } - if ($r->content_type eq 'changeme' && !$r->notes('axkit_passthru_type')) { - $AxKit::Cfg->AllowOutputCharset(1); - $r->content_type('text/html; charset=' . ($AxKit::Cfg->OutputCharset || "UTF-8")); - } - elsif ($r->notes('axkit_passthru_type')) { - $r->content_type($AxKit::OrigType); - } +# if ($r->content_type eq 'changeme' && !$r->notes('axkit_passthru_type')) { +# $AxKit::Cfg->AllowOutputCharset(1); +# $r->content_type('text/html; charset=' . ($AxKit::Cfg->OutputCharset || "UTF-8")); +# } +# elsif ($r->notes('axkit_passthru_type')) { +# $r->content_type($AxKit::OrigType); +# } my ($transformer, $doit) = AxKit::get_output_transformer(); - if ($doit) { - AxKit::Debug(4, "Cache: Transforming content and printing to browser"); - $r->pnotes('xml_string',$self->read()); - return OK; # upstream deliver_to_browser should handle the rest - } - else { - AxKit::Debug(4, "Cache: Sending untransformed content to browser"); + throw Apache::AxKit::Exception::Error->throw( + -text => "cache deliver called when cache can't fast deliver" + ) if $doit; + + AxKit::Debug(4, "Cache: Sending untransformed content to browser"); + + # Make sure we unset PATH_INFO or wierd things can happen! + $ENV{PATH_INFO} = ''; + $r->path_info(''); + + if ($self->{gzip} && $AxKit::Cfg->DoGzip) { + AxKit::Debug(4, 'Cache: Delivering gzipped output'); + $r->filename($self->{file}.'.gz'); + } + else { + $r->filename($self->{file}); + } - # Make sure we unset PATH_INFO or wierd things can happen! - $ENV{PATH_INFO} = ''; - $r->path_info(''); - - if ($self->{gzip} && $AxKit::Cfg->DoGzip) { - AxKit::Debug(4, 'Cache: Delivering gzipped output'); - $r->filename($self->{file}.'.gz'); - } - else { - $r->filename($self->{file}); - } + # Apache::AxKit::Exception::Declined->throw(); # handler will catch +} + +sub add_dependencies{ + my $self = shift; + foreach my $d ( @_ ) { + $self->{'depends'}->{$d}++; + } +} - return DECLINED; - } +sub load_dependencies{ + my $self = shift; + return if $self->{no_cache}; + my $fh = Apache->gensym(); + my @depends; + if (AxKit::sysopen($fh, $self->{file}.'.depends', O_RDONLY,'raw')) { + flock($fh, LOCK_SH); + @depends = <$fh>; + chomp(@depends); + close($fh); + # close unlocks automatically + } else { + # there should always be a cache dependency file + # since an empty file is different to there not being a file + Apache::AxKit::Exception::Error->throw( -text => "no cache dependency file"); + } + return @depends; +} + +sub check_dependencies{ + my ($self) = @_; + + my $r = $self->{'apache'}; + + foreach my $dependency ( $self->load_dependencies() ) { + + # nasty $self->apache here cause the number of places + # I'd have to check/change for passing $r was too many + # to bother with. Hopefully this will all get cleaned up. + # well, it changes the interface to cache->read(). + + $dependency =~ s|^\{(\w+)\}||; + my $dep_type = $1; + AxKit::Debug(3, "Checking dependency: $dependency of type $dep_type"); + my $dep = ($dep_type eq "style") ? + Apache::AxKit::Provider->new_style_provider($r, key => $dependency) : + Apache::AxKit::Provider->new($r, key => $dependency); + + if ( $dep->has_changed( $self->mtime() ) ) { + AxKit::Debug(4, "dependency: $dependency newer"); + return 0; + } + } + return 1; } sub reset { my $self = shift; unlink $self->{file}; -} + unlink $self->{file}.".depends"; + unlink $self->{file}.".gz"; + unlink $self->{file}.".type"; + } sub mtime { my $self = shift; No revision Index: Cache.pm =================================================================== RCS file: /home/cvs/xml-axkit/lib/Apache/AxKit/Cache.pm,v retrieving revision 1.12 retrieving revision 1.12.2.1 diff -u -r1.12 -r1.12.2.1 --- Cache.pm 3 Oct 2003 18:38:38 -0000 1.12 +++ Cache.pm 20 Oct 2003 20:58:01 -0000 1.12.2.1 @@ -1,5 +1,3 @@ -# $Id$ - package Apache::AxKit::Cache; use strict; @@ -72,14 +70,15 @@ } my $self = bless { - apache => $r, - key => $key, - no_cache => $no_cache, - dir => $cachedir, - file => "$cachedir/$primary/$secondary/$key", - gzip => $gzip, + apache => $r, + key => $key, + no_cache => $no_cache, + dir => $cachedir, + file => "$cachedir/$primary/$secondary/$key", + gzip => $gzip, + depends => {}, # extras => [EMAIL PROTECTED], - }, $class; + }, $class; if (my $alternate = $AxKit::Cfg->CacheModule()) { AxKit::reconsecrate($self, $alternate); @@ -108,8 +107,10 @@ sub write { my $self = shift; + my ($content, $encoding) = @_; + $content = ref($content) ? $$content : $content; return if $self->{no_cache}; - my $encoding = $_[1] || 'raw'; + $encoding ||= 'raw'; AxKit::Debug(7, "[Cache] writing cache file $self->{file}"); my $fh = Apache->gensym(); my $tmp_filename = $self->{file}."new$$"; @@ -117,7 +118,7 @@ # flock($fh, LOCK_EX); # seek($fh, 0, 0); # truncate($fh, 0); - print $fh $_[0]; + print $fh $content; close $fh; rename($tmp_filename, $self->{file}) || throw Apache::AxKit::Exception::IO( -text => "Couldn't rename cachefile: $!"); @@ -125,11 +126,21 @@ else { throw Apache::AxKit::Exception::IO( -text => "Couldn't open cachefile for writing: $!"); } + + if (AxKit::sysopen($fh, $tmp_filename, O_WRONLY|O_CREAT, 'raw')) { + print $fh join("\n", keys %{$self->{'depends'}}); + close $fh; + rename($tmp_filename, $self->{file}.'.depends') + || throw Apache::AxKit::Exception::IO( -text => "Couldn't rename cachefile: $!"); + } + else { + throw Apache::AxKit::Exception::IO( -text => "Couldn't open cachefile for writing: $!"); + } if ($self->{gzip} && $AxKit::Cfg->GzipOutput) { AxKit::Debug(3, "Creating gzip output cache: $self->{file}.gz"); if (my $gz = gzopen($self->{file}.'new.gz', "wb")) { - $gz->gzwrite($_[0]); + $gz->gzwrite($content); $gz->gzclose(); rename($self->{file}.'new.gz', $self->{file}.'.gz') || throw Apache::AxKit::Exception::IO( -text => "Couldn't rename gzipped cachefile: $!"); @@ -141,22 +152,25 @@ } sub read { - my $self = shift; - return if $self->{no_cache}; + my ($self) = @_; my $encoding = $_[0] || 'raw'; - my $fh = Apache->gensym(); - if (AxKit::sysopen($fh, $self->{file}, O_RDONLY, $encoding)) { - flock($fh, LOCK_SH); - local $/; - return <$fh>; - # close($fh); - # close unlocks automatically + return if $self->{no_cache}; + if($self->check_dependencies()) { + my $fh = Apache->gensym(); + if (AxKit::sysopen($fh, $self->{file}, O_RDONLY, $encoding)) { + flock($fh, LOCK_SH); + local $/; + return <$fh>; + # close($fh); + # close unlocks automatically + } } - return ''; + return undef; } sub get_fh { my $self = shift; + warn("cache get_fh called"); return if $self->{no_cache}; my $fh = Apache->gensym(); if (AxKit::sysopen($fh, $self->{file}, O_RDONLY, 'raw')) { @@ -203,7 +217,9 @@ sub deliver { my $self = shift; - return SERVER_ERROR if $self->{no_cache}; + Apache::AxKit::Exception::Error->throw( + -text => 'attempt to deliver from cache when no cache set' + ) if $self->{no_cache}; my $r = $self->{apache}; { @@ -215,46 +231,99 @@ } } - if ($r->content_type eq 'changeme' && !$r->notes('axkit_passthru_type')) { - $AxKit::Cfg->AllowOutputCharset(1); - $r->content_type('text/html; charset=' . ($AxKit::Cfg->OutputCharset || "UTF-8")); - } - elsif ($r->notes('axkit_passthru_type')) { - $r->content_type($AxKit::OrigType); - } +# if ($r->content_type eq 'changeme' && !$r->notes('axkit_passthru_type')) { +# $AxKit::Cfg->AllowOutputCharset(1); +# $r->content_type('text/html; charset=' . ($AxKit::Cfg->OutputCharset || "UTF-8")); +# } +# elsif ($r->notes('axkit_passthru_type')) { +# $r->content_type($AxKit::OrigType); +# } my ($transformer, $doit) = AxKit::get_output_transformer(); - if ($doit) { - AxKit::Debug(4, "Cache: Transforming content and printing to browser"); - $r->pnotes('xml_string',$self->read()); - return OK; # upstream deliver_to_browser should handle the rest - } - else { - AxKit::Debug(4, "Cache: Sending untransformed content to browser"); + throw Apache::AxKit::Exception::Error->throw( + -text => "cache deliver called when cache can't fast deliver" + ) if $doit; + + AxKit::Debug(4, "Cache: Sending untransformed content to browser"); + + # Make sure we unset PATH_INFO or wierd things can happen! + $ENV{PATH_INFO} = ''; + $r->path_info(''); + + if ($self->{gzip} && $AxKit::Cfg->DoGzip) { + AxKit::Debug(4, 'Cache: Delivering gzipped output'); + $r->filename($self->{file}.'.gz'); + } + else { + $r->filename($self->{file}); + } - # Make sure we unset PATH_INFO or wierd things can happen! - $ENV{PATH_INFO} = ''; - $r->path_info(''); - - if ($self->{gzip} && $AxKit::Cfg->DoGzip) { - AxKit::Debug(4, 'Cache: Delivering gzipped output'); - $r->filename($self->{file}.'.gz'); - } - else { - $r->filename($self->{file}); - } + # Apache::AxKit::Exception::Declined->throw(); # handler will catch +} + +sub add_dependencies{ + my $self = shift; + foreach my $d ( @_ ) { + $self->{'depends'}->{$d}++; + } +} - return DECLINED; - } +sub load_dependencies{ + my $self = shift; + return if $self->{no_cache}; + my $fh = Apache->gensym(); + my @depends; + if (AxKit::sysopen($fh, $self->{file}.'.depends', O_RDONLY,'raw')) { + flock($fh, LOCK_SH); + @depends = <$fh>; + chomp(@depends); + close($fh); + # close unlocks automatically + } else { + # there should always be a cache dependency file + # since an empty file is different to there not being a file + Apache::AxKit::Exception::Error->throw( -text => "no cache dependency file"); + } + return @depends; +} + +sub check_dependencies{ + my ($self) = @_; + + my $r = $self->{'apache'}; + + foreach my $dependency ( $self->load_dependencies() ) { + + # nasty $self->apache here cause the number of places + # I'd have to check/change for passing $r was too many + # to bother with. Hopefully this will all get cleaned up. + # well, it changes the interface to cache->read(). + + $dependency =~ s|^\{(\w+)\}||; + my $dep_type = $1; + AxKit::Debug(3, "Checking dependency: $dependency of type $dep_type"); + my $dep = ($dep_type eq "style") ? + Apache::AxKit::Provider->new_style_provider($r, key => $dependency) : + Apache::AxKit::Provider->new($r, key => $dependency); + + if ( $dep->has_changed( $self->mtime() ) ) { + AxKit::Debug(4, "dependency: $dependency newer"); + return 0; + } + } + return 1; } sub reset { my $self = shift; unlink $self->{file}; -} + unlink $self->{file}.".depends"; + unlink $self->{file}.".gz"; + unlink $self->{file}.".type"; + } sub mtime { my $self = shift; No revision Index: Cache.pm =================================================================== RCS file: /home/cvs/xml-axkit/lib/Apache/AxKit/Cache.pm,v retrieving revision 1.12 retrieving revision 1.12.2.1 diff -u -r1.12 -r1.12.2.1 --- Cache.pm 3 Oct 2003 18:38:38 -0000 1.12 +++ Cache.pm 20 Oct 2003 20:58:01 -0000 1.12.2.1 @@ -1,5 +1,3 @@ -# $Id$ - package Apache::AxKit::Cache; use strict; @@ -72,14 +70,15 @@ } my $self = bless { - apache => $r, - key => $key, - no_cache => $no_cache, - dir => $cachedir, - file => "$cachedir/$primary/$secondary/$key", - gzip => $gzip, + apache => $r, + key => $key, + no_cache => $no_cache, + dir => $cachedir, + file => "$cachedir/$primary/$secondary/$key", + gzip => $gzip, + depends => {}, # extras => [EMAIL PROTECTED], - }, $class; + }, $class; if (my $alternate = $AxKit::Cfg->CacheModule()) { AxKit::reconsecrate($self, $alternate); @@ -108,8 +107,10 @@ sub write { my $self = shift; + my ($content, $encoding) = @_; + $content = ref($content) ? $$content : $content; return if $self->{no_cache}; - my $encoding = $_[1] || 'raw'; + $encoding ||= 'raw'; AxKit::Debug(7, "[Cache] writing cache file $self->{file}"); my $fh = Apache->gensym(); my $tmp_filename = $self->{file}."new$$"; @@ -117,7 +118,7 @@ # flock($fh, LOCK_EX); # seek($fh, 0, 0); # truncate($fh, 0); - print $fh $_[0]; + print $fh $content; close $fh; rename($tmp_filename, $self->{file}) || throw Apache::AxKit::Exception::IO( -text => "Couldn't rename cachefile: $!"); @@ -125,11 +126,21 @@ else { throw Apache::AxKit::Exception::IO( -text => "Couldn't open cachefile for writing: $!"); } + + if (AxKit::sysopen($fh, $tmp_filename, O_WRONLY|O_CREAT, 'raw')) { + print $fh join("\n", keys %{$self->{'depends'}}); + close $fh; + rename($tmp_filename, $self->{file}.'.depends') + || throw Apache::AxKit::Exception::IO( -text => "Couldn't rename cachefile: $!"); + } + else { + throw Apache::AxKit::Exception::IO( -text => "Couldn't open cachefile for writing: $!"); + } if ($self->{gzip} && $AxKit::Cfg->GzipOutput) { AxKit::Debug(3, "Creating gzip output cache: $self->{file}.gz"); if (my $gz = gzopen($self->{file}.'new.gz', "wb")) { - $gz->gzwrite($_[0]); + $gz->gzwrite($content); $gz->gzclose(); rename($self->{file}.'new.gz', $self->{file}.'.gz') || throw Apache::AxKit::Exception::IO( -text => "Couldn't rename gzipped cachefile: $!"); @@ -141,22 +152,25 @@ } sub read { - my $self = shift; - return if $self->{no_cache}; + my ($self) = @_; my $encoding = $_[0] || 'raw'; - my $fh = Apache->gensym(); - if (AxKit::sysopen($fh, $self->{file}, O_RDONLY, $encoding)) { - flock($fh, LOCK_SH); - local $/; - return <$fh>; - # close($fh); - # close unlocks automatically + return if $self->{no_cache}; + if($self->check_dependencies()) { + my $fh = Apache->gensym(); + if (AxKit::sysopen($fh, $self->{file}, O_RDONLY, $encoding)) { + flock($fh, LOCK_SH); + local $/; + return <$fh>; + # close($fh); + # close unlocks automatically + } } - return ''; + return undef; } sub get_fh { my $self = shift; + warn("cache get_fh called"); return if $self->{no_cache}; my $fh = Apache->gensym(); if (AxKit::sysopen($fh, $self->{file}, O_RDONLY, 'raw')) { @@ -203,7 +217,9 @@ sub deliver { my $self = shift; - return SERVER_ERROR if $self->{no_cache}; + Apache::AxKit::Exception::Error->throw( + -text => 'attempt to deliver from cache when no cache set' + ) if $self->{no_cache}; my $r = $self->{apache}; { @@ -215,46 +231,99 @@ } } - if ($r->content_type eq 'changeme' && !$r->notes('axkit_passthru_type')) { - $AxKit::Cfg->AllowOutputCharset(1); - $r->content_type('text/html; charset=' . ($AxKit::Cfg->OutputCharset || "UTF-8")); - } - elsif ($r->notes('axkit_passthru_type')) { - $r->content_type($AxKit::OrigType); - } +# if ($r->content_type eq 'changeme' && !$r->notes('axkit_passthru_type')) { +# $AxKit::Cfg->AllowOutputCharset(1); +# $r->content_type('text/html; charset=' . ($AxKit::Cfg->OutputCharset || "UTF-8")); +# } +# elsif ($r->notes('axkit_passthru_type')) { +# $r->content_type($AxKit::OrigType); +# } my ($transformer, $doit) = AxKit::get_output_transformer(); - if ($doit) { - AxKit::Debug(4, "Cache: Transforming content and printing to browser"); - $r->pnotes('xml_string',$self->read()); - return OK; # upstream deliver_to_browser should handle the rest - } - else { - AxKit::Debug(4, "Cache: Sending untransformed content to browser"); + throw Apache::AxKit::Exception::Error->throw( + -text => "cache deliver called when cache can't fast deliver" + ) if $doit; + + AxKit::Debug(4, "Cache: Sending untransformed content to browser"); + + # Make sure we unset PATH_INFO or wierd things can happen! + $ENV{PATH_INFO} = ''; + $r->path_info(''); + + if ($self->{gzip} && $AxKit::Cfg->DoGzip) { + AxKit::Debug(4, 'Cache: Delivering gzipped output'); + $r->filename($self->{file}.'.gz'); + } + else { + $r->filename($self->{file}); + } - # Make sure we unset PATH_INFO or wierd things can happen! - $ENV{PATH_INFO} = ''; - $r->path_info(''); - - if ($self->{gzip} && $AxKit::Cfg->DoGzip) { - AxKit::Debug(4, 'Cache: Delivering gzipped output'); - $r->filename($self->{file}.'.gz'); - } - else { - $r->filename($self->{file}); - } + # Apache::AxKit::Exception::Declined->throw(); # handler will catch +} + +sub add_dependencies{ + my $self = shift; + foreach my $d ( @_ ) { + $self->{'depends'}->{$d}++; + } +} - return DECLINED; - } +sub load_dependencies{ + my $self = shift; + return if $self->{no_cache}; + my $fh = Apache->gensym(); + my @depends; + if (AxKit::sysopen($fh, $self->{file}.'.depends', O_RDONLY,'raw')) { + flock($fh, LOCK_SH); + @depends = <$fh>; + chomp(@depends); + close($fh); + # close unlocks automatically + } else { + # there should always be a cache dependency file + # since an empty file is different to there not being a file + Apache::AxKit::Exception::Error->throw( -text => "no cache dependency file"); + } + return @depends; +} + +sub check_dependencies{ + my ($self) = @_; + + my $r = $self->{'apache'}; + + foreach my $dependency ( $self->load_dependencies() ) { + + # nasty $self->apache here cause the number of places + # I'd have to check/change for passing $r was too many + # to bother with. Hopefully this will all get cleaned up. + # well, it changes the interface to cache->read(). + + $dependency =~ s|^\{(\w+)\}||; + my $dep_type = $1; + AxKit::Debug(3, "Checking dependency: $dependency of type $dep_type"); + my $dep = ($dep_type eq "style") ? + Apache::AxKit::Provider->new_style_provider($r, key => $dependency) : + Apache::AxKit::Provider->new($r, key => $dependency); + + if ( $dep->has_changed( $self->mtime() ) ) { + AxKit::Debug(4, "dependency: $dependency newer"); + return 0; + } + } + return 1; } sub reset { my $self = shift; unlink $self->{file}; -} + unlink $self->{file}.".depends"; + unlink $self->{file}.".gz"; + unlink $self->{file}.".type"; + } sub mtime { my $self = shift; 1.1.2.1 +279 -0 xml-axkit/lib/Apache/AxKit/Attic/Pipeline.pm No revision No revision 1.5.2.1 +46 -13 xml-axkit/lib/Apache/AxKit/Language/HtmlDoc.pm Index: HtmlDoc.pm =================================================================== RCS file: /home/cvs/xml-axkit/lib/Apache/AxKit/Language/HtmlDoc.pm,v retrieving revision 1.5 retrieving revision 1.5.2.1 diff -u -r1.5 -r1.5.2.1 --- HtmlDoc.pm 28 Jul 2003 22:53:20 -0000 1.5 +++ HtmlDoc.pm 20 Oct 2003 20:58:01 -0000 1.5.2.1 @@ -12,6 +12,8 @@ use Apache::AxKit::Language; use Apache::AxKit::LibXMLSupport; use Apache::AxKit::Provider; +use Apache::URI; +use URI; use XML::LibXSLT; use IPC::Run qw(run); use Cwd; @@ -21,6 +23,8 @@ sub stylesheet_exists () { 0; } + + sub handler { my $class = shift; my ($r, $xml_provider, undef, $last_in_chain) = @_; @@ -46,12 +50,48 @@ $dom = $parser->parse_string($source_text, $r->uri()); } $dom->process_xinclude(); + + XML::LibXSLT->register_function("perl://apache/axkit/language/htmldoc", "url_fix", + sub { my ($ref) = @_; + my $str = $ref; + eval { + my $r = Apache->request(); + my $realabs = Apache::URI->parse($r)->unparse(); + $str = URI->new_abs( $ref, $realabs ); + }; + return "$str"; + } + ); + my $style_dom = $parser->parse_string(<< 'EOX','.'); <?xml version="1.0"?> -<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"> -<xsl:output method="html" encoding="ISO-8859-15"/> -<xsl:template match="*"><xsl:copy select="."><xsl:copy-of select="@*"/><xsl:apply-templates/></xsl:copy></xsl:template> -<xsl:template match="text()"><xsl:value-of select="."/></xsl:template> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:x="http://www.w3.org/1999/xhtml" + xmlns:perl="perl://apache/axkit/language/htmldoc"> + <xsl:output method="html" encoding="ISO-8859-15"/> + <xsl:template match="*"> + <!-- output mode="html" does not react nicely to namespaced elements --> + <xsl:element name="{name()}"> + <xsl:apply-templates select="@*"/> + <xsl:apply-templates/> + </xsl:element> + </xsl:template> + <xsl:template match="@*"> + <xsl:attribute name="{name()}"><xsl:value-of select="."/></xsl:attribute> + </xsl:template> + <xsl:template match="comment()"> + <!-- htmldoc uses comments as processing instructions --> + <xsl:copy> + <xsl:apply-templates/> + </xsl:copy> + </xsl:template> + <xsl:template match="text()"> + <xsl:value-of select="."/> + </xsl:template> + <xsl:template match="@href|@x:href"> + <xsl:attribute name="href"><xsl:value-of select="perl:url_fix(.)"/></xsl:attribute> + </xsl:template> </xsl:stylesheet> EOX my $stylesheet = XML::LibXSLT->parse_stylesheet($style_dom); @@ -59,16 +99,9 @@ my $result; my $input = $stylesheet->output_string($results); - my $host = $r->hostname; - $input =~ s{ href="/}{ href="http://$host/}g; - my $path = $r->document_root; - $input =~ s{ src="/}{ src="$path/}g; - $path = $r->uri; - $path =~ s{/+[^/]*$}{/}; - $input =~ s{ href="(?!/|.{0,5}:)}{ href="http://$host$path}g; AxKit::Debug(8, "About to shell out to htmldoc - hope you have it installed..."); AxKit::Debug(10, $input); - run(['htmldoc','--quiet','--format','pdf13','--truetype','--size','a4','--color','--charset','8859-15','--webpage',$r->dir_config->get('AxHtmlDocOptions'),'-'],\$input,\$result); + run(['htmldoc','--quiet','--format','pdf13','--embedfonts','--size','a4','--color','--charset','8859-15','--webpage',$r->dir_config->get('AxHtmlDocOptions'),'-'],\$input,\$result); if (substr($result,0,5) ne '%PDF-') { throw Apache::AxKit::Exception::Error(-text => 'htmldoc returned error: '.$result); 1.22.2.1 +3 -1 xml-axkit/lib/Apache/AxKit/Language/LibXSLT.pm Index: LibXSLT.pm =================================================================== RCS file: /home/cvs/xml-axkit/lib/Apache/AxKit/Language/LibXSLT.pm,v retrieving revision 1.22 retrieving revision 1.22.2.1 diff -u -r1.22 -r1.22.2.1 --- LibXSLT.pm 31 Jul 2003 16:48:15 -0000 1.22 +++ LibXSLT.pm 20 Oct 2003 20:58:01 -0000 1.22.2.1 @@ -45,6 +45,7 @@ } else { $xmlstring = $r->pnotes('xml_string'); + delete $r->pnotes()->{'xml_string'}; } my $parser = XML::LibXML->new(); @@ -136,6 +137,7 @@ AxKit::Debug(7, "[LibXSLT] storing results in pnotes(dom_tree) ($r)"); $r->pnotes('dom_tree', $results); + delete $r->pnotes()->{'xml_string'}; # warn "LibXSLT returned $output \n"; # print $stylesheet->output_string($results); 1.51.2.1 +29 -3 xml-axkit/lib/Apache/AxKit/Language/XSP.pm Index: XSP.pm =================================================================== RCS file: /home/cvs/xml-axkit/lib/Apache/AxKit/Language/XSP.pm,v retrieving revision 1.51 retrieving revision 1.51.2.1 diff -u -r1.51 -r1.51.2.1 --- XSP.pm 3 Oct 2003 18:38:38 -0000 1.51 +++ XSP.pm 20 Oct 2003 20:58:01 -0000 1.51.2.1 @@ -42,6 +42,28 @@ # return $parser->parsefile($filename); # } +sub compile{ + my ($class, $r, $key, $package, $to_parse) = @_; + + _register_me_and_others(); + +# warn "XSP Parse: $xmlfile\n"; + + my $handler = AxKit::XSP::SAXHandler->new_handler( + XSP_Package => $package, + XSP_Line => $key, + XSP_Debug => 1, + ); + + my $parser = AxKit::XSP::SAXParser->new( + Handler => $handler, + ); + + local $Apache::AxKit::Language::XSP::ResNamespaces = $r->dir_config('XSPResNamespaces'); + + return $parser->parse($to_parse); +} + sub handler { my $class = shift; my ($r, $xml, undef, $last_in_chain) = @_; @@ -1188,8 +1210,7 @@ ); sub has_changed { - my $class = shift; - my $mtime = shift; + my ($package, $mtime, $r, $key) = @_; return 1; } @@ -1197,6 +1218,11 @@ my $class = shift; my ($r, $cgi) = @_; return ''; +} + +sub enable_cache{ + my ($package, $r, $key) = @_; + return 0; } sub handler { No revision No revision 1.1.2.1 +296 -0 xml-axkit/lib/Apache/AxKit/Pipeline/Attic/Cache.pm 1.1.2.1 +42 -0 xml-axkit/lib/Apache/AxKit/Pipeline/Attic/Head.pm 1.1.2.1 +123 -0 xml-axkit/lib/Apache/AxKit/Pipeline/Attic/Language.pm 1.1.2.1 +164 -0 xml-axkit/lib/Apache/AxKit/Pipeline/Attic/LibXSLT.pm 1.1.2.1 +123 -0 xml-axkit/lib/Apache/AxKit/Pipeline/Attic/Trace.pm 1.1.2.1 +56 -0 xml-axkit/lib/Apache/AxKit/Pipeline/Attic/Transformer.pm 1.1.2.1 +261 -0 xml-axkit/lib/Apache/AxKit/Pipeline/Attic/XSP.pm No revision No revision 1.7.2.1 +10 -1 xml-axkit/t/conf/extra.last.conf.in Index: extra.last.conf.in =================================================================== RCS file: /home/cvs/xml-axkit/t/conf/extra.last.conf.in,v retrieving revision 1.7 retrieving revision 1.7.2.1 diff -u -r1.7 -r1.7.2.1 --- extra.last.conf.in 19 Oct 2003 16:09:36 -0000 1.7 +++ extra.last.conf.in 20 Oct 2003 20:58:01 -0000 1.7.2.1 @@ -11,7 +11,7 @@ eval { require XML::LibXSLT; }; unless ($@) { - $AxAddStyleMap = "text/xsl Apache::AxKit::Language::LibXSLT"; + $AxAddStyleMap = "text/xsl Apache::AxKit::Pipeline::LibXSLT"; $has_libxslt = 1; } @@ -133,5 +133,14 @@ SetHandler axkit AxResetProcessors AxAddProcessor text/xsl /style/uri/axkit/subrequest.xsl +</Location> + +<Location "/pipeline/cache/01.xml"> + SetHandler axkit + AxNoCache off + AxCacheDir .cache + PerlSetVar AxCacheDebugHeaders 1 + AxResetProcessors + AxAddProcessor text/xsl /style/pipeline/cache/01.xsl </Location> No revision No revision 1.1.2.1 +2 -0 xml-axkit/t/htdocs/pipeline/cache/Attic/01.xml No revision No revision 1.1.2.1 +9 -0 xml-axkit/t/htdocs/style/pipeline/cache/Attic/01.xsl No revision No revision 1.1.2.1 +25 -0 xml-axkit/t/pipeline/Attic/01cache.t No revision No revision 1.1.4.1 +1 -1 xml-axkit/t/xslt-basic/02_include.t Index: 02_include.t =================================================================== RCS file: /home/cvs/xml-axkit/t/xslt-basic/02_include.t,v retrieving revision 1.1 retrieving revision 1.1.4.1 diff -u -r1.1 -r1.1.4.1 --- 02_include.t 26 May 2003 01:41:28 -0000 1.1 +++ 02_include.t 20 Oct 2003 20:58:02 -0000 1.1.4.1 @@ -7,7 +7,7 @@ sub test_basic { my $resp = GET '/xslt-basic/02_include.xml' ; - #warn "GOT CONTENT:" . $resp->content(); +# warn "GOT CONTENT:" . $resp->content(); return 0 unless $resp->content =~ /Included overrides default/gi; return 1; }