1*9780544fSAndrew Rist#************************************************************** 2cdf0e10cSrcweir# 3*9780544fSAndrew Rist# Licensed to the Apache Software Foundation (ASF) under one 4*9780544fSAndrew Rist# or more contributor license agreements. See the NOTICE file 5*9780544fSAndrew Rist# distributed with this work for additional information 6*9780544fSAndrew Rist# regarding copyright ownership. The ASF licenses this file 7*9780544fSAndrew Rist# to you under the Apache License, Version 2.0 (the 8*9780544fSAndrew Rist# "License"); you may not use this file except in compliance 9*9780544fSAndrew Rist# with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir# 11*9780544fSAndrew Rist# http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir# 13*9780544fSAndrew Rist# Unless required by applicable law or agreed to in writing, 14*9780544fSAndrew Rist# software distributed under the License is distributed on an 15*9780544fSAndrew Rist# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*9780544fSAndrew Rist# KIND, either express or implied. See the License for the 17*9780544fSAndrew Rist# specific language governing permissions and limitations 18*9780544fSAndrew Rist# under the License. 19cdf0e10cSrcweir# 20*9780544fSAndrew Rist#************************************************************** 21*9780544fSAndrew Rist 22*9780544fSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir 25cdf0e10cSrcweir# 26cdf0e10cSrcweir# Eis.pm - package for accessing/manipulating the EIS database via SOAP 27cdf0e10cSrcweir# 28cdf0e10cSrcweir 29cdf0e10cSrcweirpackage Eis; 30cdf0e10cSrcweiruse strict; 31cdf0e10cSrcweir 32cdf0e10cSrcweiruse SOAP::Lite; 33cdf0e10cSrcweiruse Class::Struct; 34cdf0e10cSrcweiruse Carp; 35cdf0e10cSrcweir 36cdf0e10cSrcweir# Declaration of class Eis together with ctor and accessors. 37cdf0e10cSrcweir# See 'perldoc Class::Struct' for details 38cdf0e10cSrcweir 39cdf0e10cSrcweirstruct Eis => [ 40cdf0e10cSrcweir # public members 41cdf0e10cSrcweir uri => '$', # name of webservice 42cdf0e10cSrcweir proxy_list => '@', # list of proxy URLs 43cdf0e10cSrcweir current_proxy => '$', # current proxy (index in proxy_list) 44cdf0e10cSrcweir net_proxy => '$', # network proxy to pass through firewall 45cdf0e10cSrcweir # private members 46cdf0e10cSrcweir eis_connector => '$' # SOAP connector to EIS database 47cdf0e10cSrcweir]; 48cdf0e10cSrcweir 49cdf0e10cSrcweir#### public methods #### 50cdf0e10cSrcweir 51cdf0e10cSrcweir# Any not predeclared method call to this package is 52cdf0e10cSrcweir# interpreted as a SOAP method call. We use the AUTOLOAD 53cdf0e10cSrcweir# mechanism to intercept these calls and delgate them 54cdf0e10cSrcweir# to the eis_connector. 55cdf0e10cSrcweir# See the 'Camel Book', 3rd edition, page 337 for an 56cdf0e10cSrcweir# explanation of the AUTOLOAD mechanism. 57cdf0e10cSrcweirsub AUTOLOAD 58cdf0e10cSrcweir{ 59cdf0e10cSrcweir my $self = shift; 60cdf0e10cSrcweir my $callee = $Eis::AUTOLOAD; # $callee now holds the name of 61cdf0e10cSrcweir # called subroutine 62cdf0e10cSrcweir # 63cdf0e10cSrcweir return if $callee =~ /::DESTROY$/; 64cdf0e10cSrcweir $callee = substr($callee, 5); 65cdf0e10cSrcweir 66cdf0e10cSrcweir my $sl = $self->eis_connector(); 67cdf0e10cSrcweir if ( !$sl ) { 68cdf0e10cSrcweir $sl = $self->init_eis_connector(); 69cdf0e10cSrcweir $self->eis_connector($sl); 70cdf0e10cSrcweir } 71cdf0e10cSrcweir 72cdf0e10cSrcweir my $response; 73cdf0e10cSrcweir while ( 1 ) { 74cdf0e10cSrcweir # Call callee() on web service. 75cdf0e10cSrcweir eval { $response = $sl->$callee(@_) }; 76cdf0e10cSrcweir if ( $@ ) { 77cdf0e10cSrcweir # Transport error (server not available, timeout, etc). 78cdf0e10cSrcweir # Use backup server. 79cdf0e10cSrcweir print STDERR ("Warning: web service unavailable. Trying backup server.\n"); 80cdf0e10cSrcweir if ( !$self->set_next_proxy() ) { 81cdf0e10cSrcweir # All proxies tried, out of luck 82cdf0e10cSrcweir carp("ERROR: Connection to EIS database failed.\n"); 83cdf0e10cSrcweir return undef; 84cdf0e10cSrcweir } 85cdf0e10cSrcweir } 86cdf0e10cSrcweir else { 87cdf0e10cSrcweir last; 88cdf0e10cSrcweir } 89cdf0e10cSrcweir } 90cdf0e10cSrcweir 91cdf0e10cSrcweir if ( $response->fault() ) { 92cdf0e10cSrcweir my $fault_msg = get_soap_fault_message($response); 93cdf0e10cSrcweir die $fault_msg; # throw $fault_msg as exception 94cdf0e10cSrcweir } 95cdf0e10cSrcweir else { 96cdf0e10cSrcweir return $response->result(); 97cdf0e10cSrcweir } 98cdf0e10cSrcweir} 99cdf0e10cSrcweir 100cdf0e10cSrcweir#### public class methods #### 101cdf0e10cSrcweir 102cdf0e10cSrcweir# Turn scalar into SOAP string. 103cdf0e10cSrcweirsub to_string 104cdf0e10cSrcweir{ 105cdf0e10cSrcweir my $value = shift; 106cdf0e10cSrcweir 107cdf0e10cSrcweir return SOAP::Data->type(string => $value); 108cdf0e10cSrcweir} 109cdf0e10cSrcweir 110cdf0e10cSrcweir#### non public instance methods #### 111cdf0e10cSrcweir 112cdf0e10cSrcweir# Initialize SOAP connection to EIS. 113cdf0e10cSrcweirsub init_eis_connector 114cdf0e10cSrcweir{ 115cdf0e10cSrcweir my $self = shift; 116cdf0e10cSrcweir 117cdf0e10cSrcweir # Init current_proxy with first element of the proxy list. 118cdf0e10cSrcweir my $current = $self->current_proxy(0); 119cdf0e10cSrcweir 120cdf0e10cSrcweir if ( !$self->uri() ) { 121cdf0e10cSrcweir carp("ERROR: web service URI not set."); 122cdf0e10cSrcweir return undef; 123cdf0e10cSrcweir } 124cdf0e10cSrcweir 125cdf0e10cSrcweir if ( !$self->proxy_list->[$current] ) { 126cdf0e10cSrcweir carp("ERROR: proxy list not proper initialized."); 127cdf0e10cSrcweir return undef; 128cdf0e10cSrcweir } 129cdf0e10cSrcweir 130cdf0e10cSrcweir # might be needed to get through a firewall 131cdf0e10cSrcweir if ( defined($self->net_proxy()) ) { 132cdf0e10cSrcweir $ENV{HTTPS_PROXY}=$self->net_proxy(); 133cdf0e10cSrcweir } 134cdf0e10cSrcweir 135cdf0e10cSrcweir my $proxy = $self->proxy_list()->[$current]; 136cdf0e10cSrcweir if ( $proxy =~ /^\s*https\:\/\// ) { 137cdf0e10cSrcweir # SOAP::Lite does not complain if Crypt::SSLeay is not available, 138cdf0e10cSrcweir # but crypted connections will just not work. Force the detection of 139cdf0e10cSrcweir # Crypt::SSLeay for https connections and fail with a meaningful 140cdf0e10cSrcweir # message if it's not available. 141cdf0e10cSrcweir require Crypt::SSLeay; 142cdf0e10cSrcweir } 143cdf0e10cSrcweir return create_eis_connector($self->uri(), $proxy); 144cdf0e10cSrcweir} 145cdf0e10cSrcweir 146cdf0e10cSrcweir# Advance one entry in proxy list. 147cdf0e10cSrcweirsub set_next_proxy 148cdf0e10cSrcweir{ 149cdf0e10cSrcweir my $self = shift; 150cdf0e10cSrcweir 151cdf0e10cSrcweir my @proxies = @{$self->proxy_list()}; 152cdf0e10cSrcweir my $current = $self->current_proxy(); 153cdf0e10cSrcweir 154cdf0e10cSrcweir if ( $current == $#proxies ) { 155cdf0e10cSrcweir return 0; 156cdf0e10cSrcweir } 157cdf0e10cSrcweir else { 158cdf0e10cSrcweir $self->current_proxy(++$current); 159cdf0e10cSrcweir my $next_proxy = $self->proxy_list()->[$current]; 160cdf0e10cSrcweir $self->eis_connector()->proxy($next_proxy); 161cdf0e10cSrcweir return 1; 162cdf0e10cSrcweir } 163cdf0e10cSrcweir} 164cdf0e10cSrcweir 165cdf0e10cSrcweir#### misc #### 166cdf0e10cSrcweir 167cdf0e10cSrcweir# Create new SOAP EIS conector. 168cdf0e10cSrcweirsub create_eis_connector 169cdf0e10cSrcweir{ 170cdf0e10cSrcweir my $uri = shift; 171cdf0e10cSrcweir my $proxy = shift; 172cdf0e10cSrcweir 173cdf0e10cSrcweir my $sl; 174cdf0e10cSrcweir 175cdf0e10cSrcweir # With version 0.66 of SOAP::Lite the uri() method 176cdf0e10cSrcweir # has been deprecated in favour of ns(). There 177cdf0e10cSrcweir # seems to be no way to switch of the deprecation warning 178cdf0e10cSrcweir # (which may be a bug in this version of SOAP::Lite). 179cdf0e10cSrcweir # Since older versions do not support the ns() method we 180cdf0e10cSrcweir # either force everyone to upgrade now, or make the following 181cdf0e10cSrcweir # dependent on the SOAP::Lite version. 182cdf0e10cSrcweir my ($vmaj, $vmin) = (0, 0); 183cdf0e10cSrcweir if( $SOAP::Lite::VERSION =~ m/([0-9]*)\.([0-9]*)/ ) { 184cdf0e10cSrcweir $vmaj = $1; 185cdf0e10cSrcweir $vmin = $2; 186cdf0e10cSrcweir if ( $vmaj > 0 || ( $vmaj == 0 && $vmin >= 66 ) ) { 187cdf0e10cSrcweir $sl = SOAP::Lite 188cdf0e10cSrcweir -> ns($uri) 189cdf0e10cSrcweir -> proxy($proxy); 190cdf0e10cSrcweir } 191cdf0e10cSrcweir else { 192cdf0e10cSrcweir $sl = SOAP::Lite 193cdf0e10cSrcweir -> uri($uri) 194cdf0e10cSrcweir -> proxy($proxy); 195cdf0e10cSrcweir } 196cdf0e10cSrcweir } 197cdf0e10cSrcweir else { 198cdf0e10cSrcweir carp("ERROR: Can't determine SOAP::Lite version."); 199cdf0e10cSrcweir } 200cdf0e10cSrcweir 201cdf0e10cSrcweir return $sl; 202cdf0e10cSrcweir} 203cdf0e10cSrcweir 204cdf0e10cSrcweir# Retrieve SOAP fault message. 205cdf0e10cSrcweirsub get_soap_fault_message 206cdf0e10cSrcweir{ 207cdf0e10cSrcweir my $faulty_response = shift; 208cdf0e10cSrcweir my $fault_msg = join(', ', $faulty_response->faultcode(), 209cdf0e10cSrcweir $faulty_response->faultstring(), 210cdf0e10cSrcweir $faulty_response->faultdetail()); 211cdf0e10cSrcweir return $fault_msg; 212cdf0e10cSrcweir} 213cdf0e10cSrcweir 214cdf0e10cSrcweir#### 215cdf0e10cSrcweir 216cdf0e10cSrcweir1; # needed by "use" or "require" 217