Author: spadkins
Date: Tue Apr  6 06:36:42 2010
New Revision: 13887

Added:
   p5ee/trunk/App-Context/lib/App/Context/ModPerl.pm
Modified:
   p5ee/trunk/App-Context/lib/Apache/App.pm
   p5ee/trunk/App-Context/lib/App.pm
   p5ee/trunk/App-Context/lib/App/Context/HTTP.pm
   p5ee/trunk/App-Context/lib/App/Session/HTMLHidden.pm

Log:
Early development snapshot for mod_perl support. Not tested well for backward 
compatibility.

Modified: p5ee/trunk/App-Context/lib/Apache/App.pm
==============================================================================
--- p5ee/trunk/App-Context/lib/Apache/App.pm    (original)
+++ p5ee/trunk/App-Context/lib/Apache/App.pm    Tue Apr  6 06:36:42 2010
@@ -2,15 +2,126 @@
 #############################################################################
 ## $Id: App.pm 3666 2006-03-11 20:34:10Z spadkins $
 #############################################################################
+## Note: Much of this code is borrowed from Apache::DBI
+##       In doing so, I have made a half-hearted attempt to make this mod_perl 
1.X compatible.
+##       However, I have never run it on mod_perl 1.X, only on mod_perl 2.X.
+##       When someone debugs this on mod_perl 1.X, please let me know what you 
had to do to make it work.
+#############################################################################
 
 package Apache::App;
-$VERSION = (q$Revision: 3666 $ =~ /(\d[\d\.]*)/)[0];  # VERSION numbers 
generated by svn
+$VERSION = (q$Revision: 3666 $ =~ /(\d[\d\.]*)/)[0];
+use strict;
+
+use constant MP2 => (exists $ENV{MOD_PERL_API_VERSION} &&
+                            $ENV{MOD_PERL_API_VERSION} == 2) ? 1 : 0;
+
+BEGIN {
+    if (MP2) {
+        require mod_perl2;
+        require Apache2::Module;
+        require Apache2::RequestUtil;
+        require Apache2::ServerUtil;
+        require Apache2::Const;
+        require Apache::DBI;
+
+        my $s = Apache2::ServerUtil->server;
+        $s->push_handlers(PerlChildInitHandler => \&child_init_handler);
+        $s->push_handlers(PerlChildExitHandler => \&child_exit_handler);
+        $s->push_handlers(PerlCleanupHandler   => \&request_cleanup_handler);
+    }
+    elsif (defined $modperl::VERSION && $modperl::VERSION > 1 && 
$modperl::VERSION < 1.99) {
+        require Apache;
+        require Apache::DBI;
+
+        Carp::carp("Apache.pm was not loaded\n")
+              and return unless $INC{'Apache.pm'};
+        if (Apache->can('push_handlers')) {
+            Apache->push_handlers(PerlChildInitHandler => 
\&child_init_handler);
+            Apache->push_handlers(PerlChildExitHandler => 
\&child_exit_handler);
+            Apache->push_handlers(PerlCleanupHandler   => 
\&request_cleanup_handler);
+        }
+    }
+}
 
-use Apache ();
+use Carp ();
 use App;
 
+my (@service_on_init);             # services to be initialized when a new 
httpd child is created
 my %env = %ENV;
-my $context;
+my ($context);
+
+#############################################################################
+# This is supposed to be called in a startup script.
+# stores the data_source of all connections, which are supposed to be created
+# upon server startup, and creates a PerlChildInitHandler, which initiates
+# the connections.  Provide a handler which creates all connections during
+# server startup
+#############################################################################
+
+sub init_service_on_child_init {
+    my (@args) = @_;
+    shift(@args);                    # get rid of class name
+    push(@service_on_init, [...@args]);
+}
+
+######################################################################################
+# PerlChildInitHandler : runs during child server startup.
+######################################################################################
+# Note: this handler runs in every child server, but not in the main server.
+######################################################################################
+
+sub child_init_handler {
+    my ($child_pool, $s) = @_;
+    warn("$$ Apache::App child_init\n");
+
+    #my $context = App->context();
+    #if (@service_on_init) {
+    #    for my $service_init_args (@service_on_init) {
+    #        $context->service(@$service_init_args);
+    #    }
+    #}
+
+    return 1; # (MP2 ? Apache2::Const::OK : Apache::OK);
+}
+
+######################################################################################
+# PerlChildExitHandler : runs during child server shutdown.
+######################################################################################
+
+sub child_exit_handler {
+    my ($child_pool, $s) = @_;
+    warn("$$ Apache::App child_exit\n");
+    return 1; # (MP2 ? Apache2::Const::OK : Apache::OK);
+}
+
+######################################################################################
+# PerlCleanupHandler : runs after the response has been sent to the client
+######################################################################################
+
+sub request_cleanup_handler {
+    warn("$$ Apache::App request_cleanup\n");
+#    my $Idx = shift;
+#
+#    my $prefix = "$$ Apache::DBI            ";
+#    debug(2, "$prefix PerlCleanupHandler");
+#
+#    my $dbh = $Connected{$Idx};
+#    if ($Rollback{$Idx}
+#        and $dbh 
+#        and $dbh->{Active}
+#        and !$dbh->{AutoCommit}
+#        and eval {$dbh->rollback}) {
+#        debug (2, "$prefix PerlCleanupHandler rollback for '$Idx'");
+#    }
+#
+#    delete $Rollback{$Idx};
+#
+    1;
+}
+
+######################################################################################
+# Response Handler
+######################################################################################
 
 sub handler {
     my $r = shift;
@@ -82,7 +193,7 @@
 EOF
         $r->print($header);
         my $options = $context->{options} || {};
-        foreach (sort keys %$options) {
+        foreach my $key (sort keys %$options) {
             $r->print("$key = $options->{$key}\n");
         }
         return;
@@ -106,6 +217,10 @@
     }
 }
 
+######################################################################################
+# Special URL-driven Responses
+######################################################################################
+
 sub info {
     my $r = shift;
     my $header = <<EOF;
@@ -137,5 +252,39 @@
     }
 }
 
+# prepare menu item for Apache::Status
+#sub status_function {
+#    my($r, $q) = @_;
+#
+#    my(@s) = qw(<TABLE><TR><TD>Datasource</TD><TD>Username</TD></TR>);
+#    for (1 .. 5) {
+#        push @s, '<TR><TD>',
+#            join('</TD><TD>',
+#                 ($_, "tbd"), "</TD></TR>\n";
+#    }
+#    push @s, '</TABLE>';
+#
+#    \...@s;
+#}
+
+#if (MP2) {
+#    if (Apache2::Module::loaded('Apache2::Status')) {
+#          Apache2::Status->menu_item(
+#                                   'DBI' => 'DBI connections',
+#                                    \&status_function
+#                                  );
+#    }
+#}
+#else {
+#   if ($INC{'Apache.pm'}                       # is Apache.pm loaded?
+#       and Apache->can('module')               # really?
+#       and Apache->module('Apache::Status')) { # Apache::Status too?
+#       Apache::Status->menu_item(
+#                                'DBI' => 'DBI connections',
+#                                \&status_function
+#                                );
+#   }
+#}
+
 1;
 

Modified: p5ee/trunk/App-Context/lib/App.pm
==============================================================================
--- p5ee/trunk/App-Context/lib/App.pm   (original)
+++ p5ee/trunk/App-Context/lib/App.pm   Tue Apr  6 06:36:42 2010
@@ -667,8 +667,7 @@
                 $options->{context_class} = $ENV{APP_CONTEXT_CLASS};
             }
             else {   # try autodetection ...
-                my $gateway = $ENV{GATEWAY_INTERFACE};
-                if (defined $gateway && $gateway =~ /CGI-Perl/) { # mod_perl?
+                if ($ENV{MOD_PERL}) {
                     $options->{context_class} = "App::Context::ModPerl";
                 }
                 elsif ($ENV{HTTP_USER_AGENT}) {  # running as CGI script?

Modified: p5ee/trunk/App-Context/lib/App/Context/HTTP.pm
==============================================================================
--- p5ee/trunk/App-Context/lib/App/Context/HTTP.pm      (original)
+++ p5ee/trunk/App-Context/lib/App/Context/HTTP.pm      Tue Apr  6 06:36:42 2010
@@ -311,7 +311,7 @@
         if (!$request_class) {
             my $gateway = $ENV{GATEWAY_INTERFACE};
             # TODO: need to distinguish between PerlRun, Registry, libapreq, 
other
-            if (defined $gateway && $gateway =~ /CGI-Perl/) {  # mod_perl?
+            if ($ENV{MOD_PERL}) {  # mod_perl: Registry
                 $request_class = "App::Request::CGI";
             }
             elsif ($ENV{HTTP_USER_AGENT}) {  # running as CGI script?
@@ -325,10 +325,7 @@
         eval {
             $self->{request} = App->new($request_class, "new", $self, 
$self->{options});
         };
-        if ($@) {
-            $self->add_message("Context::HTTP::request(): $@");
-            print STDERR "request=$self->{request} err...@]\n";
-        }
+        # ignore the failure to find a request. no request is currently 
available. method will return undef.
     }
 
     &App::sub_exit($self->{request}) if ($App::trace);

Added: p5ee/trunk/App-Context/lib/App/Context/ModPerl.pm
==============================================================================
--- (empty file)
+++ p5ee/trunk/App-Context/lib/App/Context/ModPerl.pm   Tue Apr  6 06:36:42 2010
@@ -0,0 +1,278 @@
+
+#############################################################################
+## $Id: ModPerl.pm 13649 2009-12-07 21:02:32Z spadkins $
+#############################################################################
+
+package App::Context::ModPerl;
+$VERSION = (q$Revision: 13649 $ =~ /(\d[\d\.]*)/)[0];  # VERSION numbers 
generated by svn
+
+use App;
+use App::Context::HTTP;
+
+...@isa = ( "App::Context::HTTP" );
+
+#use App::UserAgent;
+#use Time::HiRes qw(gettimeofday tv_interval);
+#use Date::Format;
+
+use strict;
+
+=head1 NAME
+
+App::Context::ModPerl - context in which we are currently running
+
+=head1 SYNOPSIS
+
+   # ... official way to get a Context object ...
+   use App;
+   $context = App->context();
+   $config = $context->config();   # get the configuration
+   $config->dispatch_events();     # dispatch events
+
+   # ... alternative way (used internally) ...
+   use App::Context::ModPerl;
+   $context = App::Context::ModPerl->new();
+
+=cut
+
+#############################################################################
+# DESCRIPTION
+#############################################################################
+
+=head1 DESCRIPTION
+
+A Context class models the environment (aka "context)
+in which the current process is running.
+For the App::Context::ModPerl class, this models the
+web application runtime environments which is mod_perl (perl embedded in the 
Apache server).
+It gets events from HTTP user agents via the HTTP protocol
+and produces (mostly) HTML pages as output.
+
+=cut
+
+#############################################################################
+# PROTECTED METHODS
+#############################################################################
+
+=head1 Protected Methods:
+
+The following methods are intended to be called by subclasses of the
+current class.
+
+=cut
+
+#############################################################################
+# _init()
+#############################################################################
+
+#=head2 _init()
+#
+#The _init() method is called from within the standard Context constructor.
+#
+#The _init() method sets debug flags.
+#
+#    * Signature: $context->_init($args)
+#    * Param:     $args            hash{string} [in]
+#    * Return:    void
+#    * Throws:    App::Exception
+#    * Since:     0.01
+#
+#    Sample Usage: 
+#
+#    $context->_init($args);
+#
+#=cut
+#
+#sub _init {
+#    &App::sub_entry if ($App::trace);
+#    my ($self, $args) = @_;
+#    $args = {} if (!defined $args);
+#
+#    eval {
+#        $self->{user_agent} = App::UserAgent->new($self);
+#    };
+#    $self->add_message("Context::HTTP::_init(): $@") if ($@);
+#
+#    &App::sub_exit() if ($App::trace);
+#}
+
+#############################################################################
+# PROTECTED METHODS
+#############################################################################
+
+=head1 Protected Methods
+
+These methods are considered protected because no class is ever supposed
+to call them.  They may however be called by the context-specific drivers.
+
+=cut
+
+sub dispatch_events {
+    &App::sub_entry if ($App::trace);
+    my ($self) = @_;
+    # do nothing
+    &App::sub_exit() if ($App::trace);
+}
+
+sub dispatch_events_from_request_begin {
+    &App::sub_entry if ($App::trace);
+    my ($self) = @_;
+    my $events = $self->{events};
+    my $request = $self->request();
+
+    my $session_id = $request->get_session_id();
+    my $session = $self->session($session_id);
+    $self->set_current_session($session);
+
+    my $request_events = $request->get_events();
+    if ($request_events && $#$request_events > -1) {
+        push(@$events, @$request_events);
+    }
+    $self->init_profiler_log();
+
+    &App::sub_exit() if ($App::trace);
+}
+
+sub dispatch_events_from_request {
+    &App::sub_entry if ($App::trace);
+    my ($self) = @_;
+
+    my ($content_length);
+    my $content_description = "Unknown";
+
+    $self->dispatch_events_from_request_begin();
+    my $events = $self->{events};
+
+    my $options  = $self->{options};
+    my $app      = $options->{app} || "app";
+    my $profiler = $options->{"app.Context.profiler"};
+    my ($app_scope, $app_scope_id_type, $app_scope_id, $content_name);
+
+    eval {
+        my $user = $self->user();
+        my $authorization = $self->authorization();
+        my ($event, $service_type, $service_name, $method, $args, 
$return_results, $return_event_results, $event_results);
+        my $results = "";
+        # my $display_current_widget = 1;
+
+        if ($#$events > -1) {
+            if ($profiler) {
+                $self->profile_start("event");
+            }
+            while ($#$events > -1) {
+                $event = shift(@$events);
+                ($service_type, $service_name, $method, $args, 
$return_event_results) = @$event;
+                if 
($authorization->is_authorized("/App/$service_type/$service_name/$method", 
$user)) {
+                    $event_results = $self->call($service_type, $service_name, 
$method, $args);
+                    if ($return_event_results) {
+                        $results = $event_results;
+                        $return_results = 1;
+                    }
+                    $user = $self->user();
+                }
+            }
+            if ($profiler) {
+                my $args_str  = (ref($args) eq "ARRAY") ? join(",", @$args) : 
$args;
+                $app_scope    = 
"$service_type($service_name).$method($args_str)";
+                $self->profile_stop("event");
+            }
+        }
+        $service_type = $self->so_get("default","ctype","SessionObject");
+        $service_name = $self->so_get("default","cname");
+
+        if ($authorization->is_authorized("/App/$service_type/$service_name", 
$user)) {
+            # do nothing
+        }
+        else {
+            if ($self->session_object_exists("login_${app}")) {
+                $service_name = "login_${app}";
+            }
+            else {
+                $service_name = "login";
+            }
+        }
+
+        $results = $self->service($service_type, $service_name) if 
(!$return_results);
+
+        my $response = $self->response();
+        my $ref = ref($results);
+        if (!$ref || $ref eq "ARRAY" || $ref eq "HASH") {
+            $app_scope = "results [$ref]";
+            if ($profiler) {
+                $self->update_profiler_log($app_scope, $service_name, 
$app_scope_id_type, $app_scope_id);
+            }
+            $response->content($results);
+        }
+        elsif ($results->isa("App::Service")) {
+            ($app_scope, $app_scope_id_type, $app_scope_id, $content_name) = 
$results->content_description();
+            $content_name ||= $service_name;
+            if ($profiler) {
+                $self->update_profiler_log($app_scope, $content_name, 
$app_scope_id_type, $app_scope_id);
+            }
+            $response->content($results->content());
+            $response->content_type($results->content_type());
+        }
+        else {
+            $app_scope = "$service_type($service_name).internals()";
+            if ($profiler) {
+                $self->update_profiler_log($app_scope, $service_name, 
$app_scope_id_type, $app_scope_id);
+            }
+            $response->content($results->internals());
+        }
+
+        if ($profiler) {
+            $self->profile_start("xfer", 1);
+        }
+        $content_length = $self->send_response();
+
+        if ($profiler) {
+            $self->{profile_state}{app_scope} = $app_scope;
+            $self->{profile_state}{content_length} = $content_length;
+        }
+    };
+    if ($@) {
+        $content_length = $self->send_error($@);
+        if ($profiler) {
+            $self->{profile_state}{app_scope} = "ERROR [$app_scope]: $@";
+            $self->{profile_state}{content_length} = $content_length;
+        }
+    }
+
+    if ($self->{options}{debug_context}) {
+        print STDERR $self->dump();
+    }
+
+    $self->dispatch_events_from_request_finish();
+    &App::sub_exit() if ($App::trace);
+}
+
+sub dispatch_events_from_request_finish {
+    &App::sub_entry if ($App::trace);
+    my ($self) = @_;
+    $self->restore_default_session();
+    $self->shutdown();  # assume we won't be doing anything else (this can be 
overridden)
+    &App::sub_exit() if ($App::trace);
+}
+
+#############################################################################
+# request()
+#############################################################################
+
+=head2 request()
+
+    * Signature: $context->request()
+    * Param:     void
+    * Return:    void
+    * Throws:    App::Exception
+    * Since:     0.01
+
+    Sample Usage: 
+
+    $context->request();
+
+The request() method gets the current Request being handled in the Context.
+
+=cut
+
+1;
+

Modified: p5ee/trunk/App-Context/lib/App/Session/HTMLHidden.pm
==============================================================================
--- p5ee/trunk/App-Context/lib/App/Session/HTMLHidden.pm        (original)
+++ p5ee/trunk/App-Context/lib/App/Session/HTMLHidden.pm        Tue Apr  6 
06:36:42 2010
@@ -261,12 +261,20 @@
 sub _init {
     &App::sub_entry if ($App::trace);
     my ($self, $args) = @_;
-    my ($cgi, $sessiontext, $store);
+    my ($cgi, $sessiontext, $store, $request);
 
     $self->{context} = $args->{context};
     $store = {};
     $cgi = $args->{cgi} if (defined $args);
-    $cgi = $self->{context}->request()->{cgi} if (!defined $cgi);
+
+    eval {
+        $request = $self->{context}->request();
+    };
+    # ignore it if it fails
+
+    if (!defined $cgi) {
+        $cgi = $request->{cgi} if ($request);
+    }
 
     if (defined $cgi) {
         $sessiontext = $cgi->param("app.sessiondata");
@@ -283,32 +291,34 @@
         }
     }
 
-    my $options = $self->{context}{options};
-    my $cookie_attribs = $options->{"app.Session.cookie_attribs"};
-    if ($cookie_attribs) {
-        my $cookiedata = {};
-
-        my $app = $options->{"app"};
-        my $cookietext = $cgi->cookie("app_session_${app}_persist");
-        if ($cookietext) {
-            $cookietext =~ s/ /\+/g;
-            my $length = length($cookietext);
-            my $pad = 4 - ($length % 4);
-            $pad = 0 if ($pad == 4);
-            $cookietext .= ("=" x $pad) if ($pad);
-            $cookietext =~ s/(.{76})/$1\n/g;
-            $cookietext .= "\n";
-#print "Session::Cookie->_init(): sessiontext = [\n$sessiontext\n]\n";
-            $cookiedata = 
thaw(Compress::Zlib::memGunzip(MIME::Base64::decode($cookietext)));
-        }
-
-        foreach my $cookie_attrib (split(/[ ,;]+/, $cookie_attribs)) {
-            if ($cookie_attrib =~ /^([^-]+)-(.+)$/) {
-                $store->{SessionObject}{$1}{$2} = $cookiedata->{$1}{$2};
+    if ($request) {
+        my $options = $self->{context}{options};
+        my $cookie_attribs = $options->{"app.Session.cookie_attribs"};
+        if ($cookie_attribs) {
+            my $cookiedata = {};
+
+            my $app = $options->{"app"};
+            my $cookietext = $cgi->cookie("app_session_${app}_persist");
+            if ($cookietext) {
+                $cookietext =~ s/ /\+/g;
+                my $length = length($cookietext);
+                my $pad = 4 - ($length % 4);
+                $pad = 0 if ($pad == 4);
+                $cookietext .= ("=" x $pad) if ($pad);
+                $cookietext =~ s/(.{76})/$1\n/g;
+                $cookietext .= "\n";
+                #print "Session::Cookie->_init(): sessiontext = 
[\n$sessiontext\n]\n";
+                $cookiedata = 
thaw(Compress::Zlib::memGunzip(MIME::Base64::decode($cookietext)));
             }
-            elsif ($cookie_attrib) {
-                $store->{SessionObject}{default}{$cookie_attrib} =
-                    $cookiedata->{default}{$cookie_attrib};
+
+            foreach my $cookie_attrib (split(/[ ,;]+/, $cookie_attribs)) {
+                if ($cookie_attrib =~ /^([^-]+)-(.+)$/) {
+                    $store->{SessionObject}{$1}{$2} = $cookiedata->{$1}{$2};
+                }
+                elsif ($cookie_attrib) {
+                    $store->{SessionObject}{default}{$cookie_attrib} =
+                        $cookiedata->{default}{$cookie_attrib};
+                }
             }
         }
     }

Reply via email to