package Apache2::ASP::ApplicationStateManager; use strict; use warnings 'all'; use Storable qw( freeze thaw ); use DBI; use Scalar::Util 'weaken'; use base 'Ima::DBI'; use Digest::MD5 'md5_hex'; #============================================================================== sub new { my ($class, %args) = @_; my $s = bless { }, $class; my $conn = $s->context->config->data_connections->application; local $^W = 0; __PACKAGE__->set_db('Main', $conn->dsn, $conn->username, $conn->password ); if( my $res = $s->retrieve ) { return $res; } else { return $s->create; }# end if() }# end new() #============================================================================== sub context { $Apache2::ASP::HTTPContext::ClassName->current; }# end context() #============================================================================== sub create { my $s = shift; local $s->db_Main->{AutoCommit} = 1; my $sth = $s->db_Main->prepare(<<""); INSERT INTO asp_applications ( application_id, application_data ) VALUES ( ?, ? ) $sth->execute( $s->context->config->web->application_name, freeze( {} ) ); $sth->finish(); return $s->retrieve(); }# end create() #============================================================================== sub retrieve { my $s = shift; my $sth = $s->dbh->prepare_cached(<<""); SELECT application_data FROM asp_applications WHERE application_id = ? $sth->execute( $s->context->config->web->application_name ); my ($data) = $sth->fetchrow; $sth->finish(); return unless $data; $data = thaw($data) || {}; undef(%$s); $s = bless $data, ref($s); no warnings 'uninitialized'; $s->{__signature} = md5_hex( join ":", map { "$_:$s->{$_}" } grep { $_ ne '__signature' } sort keys(%$s) ); return $s; }# end retrieve() #============================================================================== sub save { my $s = shift; no warnings 'uninitialized'; return if $s->{__signature} eq md5_hex( join ":", map { "$_:$s->{$_}" } grep { $_ ne '__signature' } sort keys(%$s) ); $s->{__signature} = md5_hex( join ":", map { "$_:$s->{$_}" } grep { $_ ne '__signature' } sort keys(%$s) ); local $s->db_Main->{AutoCommit} = 1; my $sth = $s->db_Main->prepare_cached(<<""); UPDATE asp_applications SET application_data = ? WHERE application_id = ? my $data = { %$s }; delete($data->{__signature} ); $sth->execute( freeze( $data ), $s->context->config->web->application_name ); $sth->finish(); 1; }# end save() #============================================================================== sub dbh { my $s = shift; return $s->db_Main; }# end dbh() #============================================================================== sub DESTROY { my $s = shift; delete($s->{$_}) foreach keys(%$s); }# end DESTROY() 1;# return true: __END__ =pod =head1 NAME Apache2::ASP::ApplicationStateManager - The $Application object =head1 SYNOPSIS # In a handler, ASP script or your GlobalASA: $Application->{some_gobal_thing} = "A new value"; # ...then, in all requests to the server... my $val = $Application->{some_global_thing}; # You can also store objects: $Application->{some_object} = My::Thing->new( ... ); # You can access the current $Application through the context also: my $app = Apache2::ASP::HTTPContext->current->application; =head1 DESCRIPTION All C<$Application> objects are instances of one or another subclass of C. C is the base class for all ApplicationStateManagers. The C<$Application> object is implemented as a simple, blessed hash with no special magick going on anywhere. C<$Application> is not a blessed hash and does not depend on special semantics, nor does it expect special treatment. =head2 Storage By default, when it is time to store the contents of the C<$Application> object for later retrieval, the venerable L module is used. The resulting binary blob is stored in the database referred to in the C part of the config. =head2 Configuration The C configuration file should contain a section like the following: ... ... Apache2::ASP::ApplicationStateManager::SQLite DBI:mysql:dbname:hostname sa s3cr3t! ... ... =head2 Database Storage The table that the C<$Application> object is stored in has the following structure: CREATE TABLE asp_applications ( application_id varchar(100) NOT NULL, application_data blob, PRIMARY KEY (application_id) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; Different databases will have different ways of spelling that, but the structure is clear. =head1 PUBLIC METHODS =head2 save( ) Stores the object in the database. Returns true. =head1 BUGS It's possible that some bugs have found their way into this release. Use RT L to submit bug reports. =head1 HOMEPAGE Please visit the Apache2::ASP homepage at L to see examples of Apache2::ASP in action. =head1 AUTHOR John Drago L =head1 COPYRIGHT AND LICENSE Copyright 2007 John Drago, All rights reserved. This software is free software. It may be used and distributed under the same terms as Perl itself. =cut