home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / perl5 / PPI / Cache.pm next >
Encoding:
Perl POD Document  |  2010-07-06  |  6.1 KB  |  305 lines

  1. package PPI::Cache;
  2.  
  3. =pod
  4.  
  5. =head1 NAME
  6.  
  7. PPI::Cache - The PPI Document Caching Layer
  8.  
  9. =head1 SYNOPSIS
  10.  
  11.   # Set the cache
  12.   use PPI::Cache path => '/var/cache/ppi-cache';
  13.   
  14.   # Manually create a cache
  15.   my $Cache = PPI::Cache->new(
  16.       path     => '/var/cache/perl/class-PPI',
  17.       readonly => 1,
  18.   );
  19.  
  20. =head1 DESCRIPTION
  21.  
  22. C<PPI::Cache> provides the default caching functionality for L<PPI>.
  23.  
  24. It integrates automatically with L<PPI> itself. Once enabled, any attempt
  25. to load a document from the filesystem will be cached via cache.
  26.  
  27. Please note that creating a L<PPI::Document> from raw source or something
  28. other object will B<not> be cached.
  29.  
  30. =head2 Using PPI::Cache
  31.  
  32. The most common way of using C<PPI::Cache> is to provide parameters to
  33. the C<use> statement at the beginning of your program.
  34.  
  35.   # Load the class but do not set a cache
  36.   use PPI::Cache;
  37.   
  38.   # Use a fairly normal cache location
  39.   use PPI::Cache path => '/var/cache/ppi-cache';
  40.  
  41. Any of the arguments that can be provided to the C<new> constructor can
  42. also be provided to C<use>.
  43.  
  44. =head1 METHODS
  45.  
  46. =cut
  47.  
  48. use strict;
  49. use Carp          ();
  50. use File::Spec    ();
  51. use File::Path    ();
  52. use Storable      ();
  53. use Digest::MD5   ();
  54. use Params::Util  qw{_INSTANCE _SCALAR};
  55. use PPI::Document ();
  56.  
  57. use vars qw{$VERSION};
  58. BEGIN {
  59.     $VERSION = '1.213';
  60. }
  61.  
  62. use constant VMS => !! ( $^O eq 'VMS' );
  63.  
  64. sub import {
  65.     my $class = ref $_[0] ? ref shift : shift;
  66.     return 1 unless @_;
  67.  
  68.     # Create a cache from the params provided
  69.     my $cache = $class->new(@_);
  70.  
  71.     # Make PPI::Document use it
  72.     unless ( PPI::Document->set_cache( $cache ) ) {
  73.         Carp::croak("Failed to set cache in PPI::Document");
  74.     }
  75.  
  76.     1;
  77. }
  78.  
  79.  
  80.  
  81.  
  82.  
  83. #####################################################################
  84. # Constructor and Accessors
  85.  
  86. =pod
  87.  
  88. =head2 new param => $value, ...
  89.  
  90. The C<new> constructor creates a new standalone cache object.
  91.  
  92. It takes a number of parameters to control the cache.
  93.  
  94. =over
  95.  
  96. =item path
  97.  
  98. The C<path> param sets the base directory for the cache. It must already
  99. exist, and must be writable.
  100.  
  101. =item readonly
  102.  
  103. The C<readonly> param is a true/false flag that allows the use of an
  104. existing cache by a less-privileged user (such as the web user).
  105.  
  106. Existing documents will be retrieved from the cache, but new documents
  107. will not be written to it.
  108.  
  109. =back
  110.  
  111. Returns a new C<PPI::Cache> object, or dies on error.
  112.  
  113. =cut
  114.  
  115. sub new {
  116.     my $class  = shift;
  117.     my %params = @_;
  118.  
  119.     # Path should exist and be usable
  120.     my $path = $params{path}
  121.         or Carp::croak("Cannot create PPI::Cache, no path provided");
  122.     unless ( -d $path ) {
  123.         Carp::croak("Cannot create PPI::Cache, path does not exist");
  124.     }
  125.     unless ( -r $path and -x $path ) {
  126.         Carp::croak("Cannot create PPI::Cache, no read permissions for path");
  127.     }
  128.     if ( ! $params{readonly} and ! -w $path ) {
  129.         Carp::croak("Cannot create PPI::Cache, no write permissions for path");
  130.     }
  131.  
  132.     # Create the basic object
  133.     my $self = bless {
  134.         path     => $path,
  135.         readonly => !! $params{readonly},
  136.     }, $class;
  137.  
  138.     $self;
  139. }
  140.  
  141. =pod
  142.  
  143. =head2 path
  144.  
  145. The C<path> accessor returns the path on the local filesystem that is the
  146. root of the cache.
  147.  
  148. =cut
  149.  
  150. sub path { $_[0]->{path} }
  151.  
  152. =pod
  153.  
  154. =head2 readonly
  155.  
  156. The C<readonly> accessor returns true if documents should not be written
  157. to the cache.
  158.  
  159. =cut
  160.  
  161. sub readonly { $_[0]->{readonly} }
  162.  
  163.  
  164.  
  165.  
  166.  
  167. #####################################################################
  168. # PPI::Cache Methods
  169.  
  170. =pod
  171.  
  172. =head2 get_document $md5sum | \$source
  173.  
  174. The C<get_document> method checks to see if a Document is stored in the
  175. cache and retrieves it if so.
  176.  
  177. =cut
  178.  
  179. sub get_document {
  180.     my $self = ref $_[0]
  181.         ? shift
  182.         : Carp::croak('PPI::Cache::get_document called as static method');
  183.     my $md5hex = $self->_md5hex(shift) or return undef;
  184.     $self->_load($md5hex);
  185. }
  186.  
  187. =pod
  188.  
  189. =head2 store_document $Document
  190.  
  191. The C<store_document> method takes a L<PPI::Document> as argument and
  192. explicitly adds it to the cache.
  193.  
  194. Returns true if saved, or C<undef> (or dies) on error.
  195.  
  196. FIXME (make this return either one or the other, not both)
  197.  
  198. =cut
  199.  
  200. sub store_document {
  201.     my $self     = shift;
  202.     my $Document = _INSTANCE(shift, 'PPI::Document') or return undef;
  203.  
  204.     # Shortcut if we are readonly
  205.     return 1 if $self->readonly;
  206.  
  207.     # Find the filename to save to
  208.     my $md5hex = $Document->hex_id or return undef;
  209.  
  210.     # Store the file
  211.     $self->_store( $md5hex, $Document );
  212. }
  213.  
  214.  
  215.  
  216.  
  217.  
  218. #####################################################################
  219. # Support Methods
  220.  
  221. # Store an arbitrary PPI::Document object (using Storable) to a particular
  222. # path within the cache filesystem.
  223. sub _store {
  224.     my ($self, $md5hex, $object) = @_;
  225.     my ($dir, $file) = $self->_paths($md5hex);
  226.  
  227.     # Save the file
  228.     File::Path::mkpath( $dir, 0, 0755 ) unless -d $dir;
  229.     if ( VMS ) {
  230.         Storable::lock_nstore( $object, $file );
  231.     } else {
  232.         Storable::nstore( $object, $file );
  233.     }
  234. }
  235.  
  236. # Load an arbitrary object (using Storable) from a particular
  237. # path within the cache filesystem.
  238. sub _load {
  239.     my ($self, $md5hex) = @_;
  240.     my (undef, $file) = $self->_paths($md5hex);
  241.  
  242.     # Load the file
  243.     return '' unless -f $file;
  244.     my $object = VMS
  245.         ? Storable::retrieve( $file )
  246.         : Storable::lock_retrieve( $file );
  247.  
  248.     # Security check
  249.     unless ( _INSTANCE($object, 'PPI::Document') ) {
  250.         Carp::croak("Security Violation: Object in '$file' is not a PPI::Document");
  251.     }
  252.  
  253.     $object;
  254. }
  255.  
  256. # Convert a md5 to a dir and file name
  257. sub _paths {
  258.     my $self   = shift;
  259.     my $md5hex = lc shift;
  260.     my $dir    = File::Spec->catdir( $self->path, substr($md5hex, 0, 1), substr($md5hex, 0, 2) );
  261.     my $file   = File::Spec->catfile( $dir, $md5hex . '.ppi' );
  262.     return ($dir, $file);
  263. }
  264.  
  265. # Check a md5hex param
  266. sub _md5hex {
  267.     my $either = shift;
  268.     my $it     = _SCALAR($_[0])
  269.         ? PPI::Util::md5hex(${$_[0]})
  270.         : $_[0];
  271.     return (defined $it and ! ref $it and $it =~ /^[a-f0-9]{32}\z/si)
  272.         ? lc $it
  273.         : undef;
  274. }
  275.  
  276. 1;
  277.  
  278. =pod
  279.  
  280. =head1 TO DO
  281.  
  282. - Finish the basic functionality
  283.  
  284. - Add support for use PPI::Cache auto-setting $PPI::Document::CACHE
  285.  
  286. =head1 SUPPORT
  287.  
  288. See the L<support section|PPI/SUPPORT> in the main module.
  289.  
  290. =head1 AUTHOR
  291.  
  292. Adam Kennedy E<lt>adamk@cpan.orgE<gt>
  293.  
  294. =head1 COPYRIGHT
  295.  
  296. Copyright 2005 - 2010 Adam Kennedy.
  297.  
  298. This program is free software; you can redistribute
  299. it and/or modify it under the same terms as Perl itself.
  300.  
  301. The full text of the license can be found in the
  302. LICENSE file included with this module.
  303.  
  304. =cut
  305.