package JCRDispatcher; # -------------------------------------------------------------------- # The copyright and all other proprietary rights in this Database # (including software - SEE LICENSING AGREEMENT) are the sole and # exclusive property of the Institute for Scientific Information # (ISI). This Database and source code, or any derivative works # thereof, are confidential and proprietary to ISI . Therefore, # duplication, reuse, redistribution, reverse assembling, reverse # compiling, or translation of the Database, source code, or any # portion thereof IS NOT PERMITTED. Consult Licensing Agreement. # -------------------------------------------------------------------- # $Id: use strict; use Apache::Constants qw(:common); use Apache::Cookie; use AppError; use Cache; use ISIConfig; use Data::Dumper; use DB; use ISIBench; use JCRErrorList; use JCRUtil; use Log::Log4perl qw(get_logger); use JCRPage; use JCRSession; use SessionUtils; sub handler { my $logger = get_logger("JCRDispatcher"); my $r = shift; my $request = SessionUtils::merge_request( 'apache' => $r ); my ($session, $db, $ret, $module, $page); $logger->debug("Processing request : ", sub{Dumper($request)}); # Get the current app name my $app = SessionUtils::get_app_name(); # Load up our application's CF.pm file my $config = ISIConfig->new( 'app' => $app, 'autoload' => 1 ); # Grab our request $logger->debug("Getting RQ from query..."); my $rq = (exists $request->{RQ})? uc($request->{RQ}) : 'HOME'; ISIBench::start('n' => $rq); $logger->debug("RQ is: $rq"); # # First connect to session # $session = JCRSession->new( 'product_code' => $CF::product_code, 'server_uri' => $CF::server_uri, ); $logger->debug("Session object: $session OR ", ref($session)); if (defined($session) && (ref($session) =~ /.*session/i)) { $logger->debug("Successfully obtained Session object"); # Open or connect to session my %cookies = Apache::Cookie->fetch; if ($rq =~ /(HOME|IMPACT|FULL_JOURNAL|IF_CAT_BOXPLOT)/i) { if ( $rq =~ /HOME/i && $request->{PointOfEntry} =~ /FULL_JOURNAL/i ) { $session->set( 'name' => 'supress_return_to_summary', 'value' => 1, ); } elsif ( $rq =~ /HOME/i && $request->{PointOfEntry} =~ /IMPACT/i ) { $session->set( 'name' => 'supress_return_to_summary', 'value' => 1, ); } elsif ( $rq =~ /HOME/i && $request->{PointOfEntry} =~ /IF_CAT_BOXPLOT/i ) { # added for boxplot request $session->set( 'name' => 'supress_return_to_summary', 'value' => 1, ); }elsif ( $rq =~ /HOME/i ) { $session->set( 'name' => 'supress_return_to_summary', 'value' => 0, ); } if (exists ($request->{SID})) { $logger->debug("Opening New Session with portal sid: ", $request->{SID}); $ret = $session->open( 'sid' => $request->{SID}, 'product' => $CF::product_code ); # Set a session cookie unless ($ret>0) { $logger->debug(qq|Creating $CF::cookie_sid with value $session->{SID}|); my $sidcookie = Apache::Cookie->new( $r, -name => $CF::cookie_sid, -value => $session->{SID}, ); $sidcookie->bake; undef $sidcookie; } } elsif (exists($cookies{$CF::cookie_sid}) && length($cookies{$CF::cookie_sid}->value)) { $logger->debug("Session Cookie : ", $cookies{$CF::cookie_sid}->value); # We have an existing SID, so try to reconnect to session $logger->debug("Opening Existing Session with SID: ", $cookies{$CF::cookie_sid}->value); $ret = $session->open( 'sid' => $cookies{jcrsid}->value, 'product' => $CF::product_code ); $ret = undef if ((grep(/^$rq$/i, @$CF::session_free_requests)) && ($ret =~ /^10\d\d$/)); unless ( $ret <= 0 ) { # We had an error somewhere, so throw an error page &_throw_error( 'error' => $ret, 'apache' => $r, 'SID' => $session->{SID}, 'mode' => 'ERROR_BY_CODE', 'app' => $app); ISIBench::stop('n' => $rq); } } else { $logger->error("Missing Portal SID to create new session"); $ret = 1017; } } elsif (exists($cookies{$CF::cookie_sid}) && length($cookies{$CF::cookie_sid}->value)) { $logger->debug("Session Cookie : ", $cookies{$CF::cookie_sid}->value); # We have an existing SID, so try to reconnect to session $logger->debug("Opening Existing Session with SID: ", $cookies{$CF::cookie_sid}->value); $ret = $session->open( 'sid' => $cookies{jcrsid}->value, 'product' => $CF::product_code ); $ret = undef if ((grep(/^$rq$/i, @$CF::session_free_requests)) && ($ret =~ /^10\d\d$/)); unless ( $ret <= 0 ) { # We had an error somewhere, so throw an error page &_throw_error( 'error' => $ret, 'apache' => $r, 'SID' => $session->{SID}, 'mode' => 'ERROR_BY_CODE', 'app' => $app ); ISIBench::stop('n' => $rq); } } else { $logger->error("Could not open or create new session"); $ret = 1001; } } else { $ret = $session; } # # Second: connect to database # $db = DB->new( 'db_vendor' => $CF::database_vendor, 'name' => $CF::database_name, 'username' => $CF::database_user, 'password' => $CF::database_password, 'port' => $CF::database_port, 'hostname' => $CF::database_host ); unless (defined($db) && (ref($db) =~ /db/i)) { $ret = $db; } $logger->debug("Successfully obtained DB connection"); # # Third: Process Portal Request # $ret = undef if ((grep(/^$rq$/i, @$CF::session_free_requests)) && ($ret =~ /^10\d\d$/)); unless ($ret) { if (exists ($request->{PointOfEntry})) { $logger->debug("PointOfEntry = ", $request->{PointOfEntry}); # Are we loading a cached page? if ($request->{PointOfEntry} eq 'LastPage') { my $page_html = SessionUtils::load_session_cache( 'session' => $session ); if ((defined($page_html)) && (ref($page_html) =~ /hash/i)) { Page::paint(undef, 'content' => $page_html->{content}, 'headers' => 'Content-type: text/html' ); ISIBench::stop('n' => $rq); return OK; } else { $logger->error("Could not load session cache. (#$page_html)"); } } else { $rq = uc($request->{PointOfEntry}); } } } # # Fourth: Validate RQ Request # unless ($ret) { $logger->debug("Validating RQ: $rq"); unless (exists $CF::requests->{$rq}) { $ret = 2; } else { $module = $CF::requests->{$rq}; } } # # Fifth: If we have a valid request, save any limit changes to the session # Note this only happens if it is a request from the home page, and this # check happens here because it effects multiple pages at once. # Get the year and edition selection unless ($ret) { if ($rq =~ /(?:select|search|select_all)/i) { # Get the selected edition from query or session my $session_edition = $session->get( 'value' => 'edition' ); my $edition = $request->{edition} || $session_edition->{edition}; unless ($edition =~ /(?:science|social)/i) { $logger->debug("Invalid edition: $edition"); $ret = 2; } else { # Get the selected year from query or session my $session_year = $session->get( 'value' => 'year' ); my $year = ($edition eq 'science') ? $request->{science_year} : $request->{social_year}; unless (defined $year) { $year = $session_year->{year} }; unless ($year) { $logger->debug("Could not get subscription"); $ret = 2; } else { # Make sure the user has permission to access my $permissions = $session->get_editions( 'year_min' => $CF::data_year_start, 'year_max' => $CF::data_year_end, ); unless(($year >= $permissions->{$edition}->{start_year}) && ($year <= $permissions->{$edition}->{end_year})) { $logger->debug("Subscription Error"); $ret = 1003; } $session->set( 'name' => 'edition', 'value' => $edition, ); $session->set( 'name' => 'year', 'value' => $year, ); $session->set( 'name' => 'HOME_rq', 'value' => $rq, ); } } } } # # Fifth: Execute Page Generation Module # # Create the page object $ret = undef if ((grep(/^$rq$/i, @$CF::session_free_requests)) && ($ret =~ /^10\d\d$/)); unless ($ret) { $logger->debug("Creating $module object"); eval { no strict 'refs'; require "$module.pm"; use strict 'refs'; }; if ($@) { $logger->error("Error loading $module.pm!\n$@"); $ret = 1; } else { $page = $module->new( 'session' => $session, 'db' => $db, 'apache' => $r, 'request' => $request, ); $logger->debug("Creating $module returned: $page"); unless (defined($page) && (ref($page) =~ /$module/i)) { $logger->error("Could not create $module object!"); $ret = $page; } else { # Now execute the page object $ret = $page->build_page( 'rq' => $rq, 'type' => 'html', ); if ($ret) { $logger->error("Could not build page via $module object!"); } } } } # # Sixth: Grab page content and headers # unless ($ret) { $logger->debug("Calling $module get_content()"); my $content = $page->get_content(); my $headers = $page->get_headers(); # # Seventh: Commit Session changes # $session->commit(); # # Eighth: Present page to user # my $page_html = $page->paint( 'content' => $content, 'headers' => $headers ); # At this point the page has been painted to the user, so we should stop our request # timer now since the request has completed in the eyes of the user ISIBench::stop('n' => $rq); # # Nineth: Cache the page # unless ($rq =~ /(?:HELP|TITLE_CHANGES|SAVE_MARKED|GRAPH_IMPACT|GRAPH_BOXPLOT|CORRECTIONS|TITLES_FULL)/) { # Only cache HTML pages here if ($headers =~ /^Content-type: text\/html$/im) { SessionUtils::save_session_cache( 'session' => $session, 'data' => $page_html, ); } } } else { my $error_string = $session->getError(); $error_string =~ /^(.*?):/; $error_string = $1; $error_string =~ tr/a-z/A-Z/; # If we have an error string from Session, get the correct code for it if ( length($error_string) > 1 ) { $logger->error("string: $error_string"); # We had an error somewhere, so throw an error page my $errorlist = JCRErrorList->new(); if (defined($errorlist) && (ref($errorlist) =~ /jcrerrorlist/i)) { $ret = $errorlist->get_code('error' => $error_string); } else { # Undefined Error $ret = 1; } } # We had an error somewhere, so throw an error page &_throw_error( 'error' => $ret, 'apache' => $r, 'SID' => $session->{SID}, 'mode' => 'ERROR_BY_CODE', 'app' => $app ); ISIBench::stop('n' => $rq); } # That's all folks! return OK; } # Subroutine to throw the error screen. It will load the error screen # template and populate it with the provided error code's text message sub _throw_error(\%) { my $logger = get_logger("JCRDispatcher"); my $args = (ref $_[0] eq 'HASH') ? shift : { @_ }; my $app = $args->{app}; $logger->debug("Throwing Error: ", $args->{error}); # Create error page object my $page = AppError->new( 'apache' => $args->{apache}, 'request' => { 'error' => $args->{error}, 'mode' => $args->{mode}, }, ); $page->build_page( 'app' => $app, 'cookie' => $CF::cookie_sid, ); $page->paint(); } 1;