File Coverage

blib/lib/Net/SDEE.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             # Net::SDEE.pm
2             #
3             # $Id: SDEE.pm,v 1.4 2005/03/07 20:12:39 jminieri Exp $
4             #
5             # Copyright (c) 2004-2005 Joe Minieri and OpenService (www.open.com).
6             # All rights reserved.
7             # This program is free software; you can redistribute it and/or modify it under the same
8             # terms as Perl itself.
9             #
10              
11             package Net::SDEE;
12              
13 1     1   28141 use 5.006001;
  1         4  
  1         42  
14 1     1   6 use strict;
  1         2  
  1         35  
15 1     1   4 use warnings;
  1         7  
  1         30  
16              
17 1     1   1167 use LWP::UserAgent;
  1         82893  
  1         35  
18              
19 1     1   651 use XML::SDEE;
  0            
  0            
20             use Net::SDEE::Query;
21             use Net::SDEE::Session;
22             use Net::SDEE::Subscription;
23              
24             our $VERSION = '0.01';
25              
26             #
27             # These are the parameters for each query type
28             my @_open_parameters = qw/action sessionId startTime events idsAlertSeverities force/;
29             my @_get_parameters = qw/action sessionId subscriptionId timeout maxNbrOfEvents confirm/;
30             my @_cancel_parameters = qw/action sessionId subscriptionId/;
31             my @_close_parameters = qw/action sessionId subscriptionId/;
32              
33             ##########################################################################################
34             #
35             # AUTOLOAD get/set methods when they're generic
36             #
37             use vars '$AUTOLOAD';
38             sub AUTOLOAD {
39             no strict 'refs';
40             my ($self, $value) = @_;
41              
42             my $method =($AUTOLOAD =~ /.*::([_\w]+)$/)[0];
43             return if $method eq 'DESTROY';
44              
45             #
46             # Pass all unknown methods to the session object
47             unless(defined($method) and exists($self->{ _session }->{ $method })) {
48             $self->call_debug("No such parameter $method");
49             return undef;
50             }
51              
52             # set this up for next time
53             *{$AUTOLOAD} = sub {
54             my ($self, $value) = @_;
55             if (defined($value)) {
56             return $self->{ _session }->{ $method } = $value;
57             } else {
58             return defined($self->{ _session }->{ $method })?$self->{ _session }->{ $method }:undef;
59             }
60             };
61              
62             goto &$AUTOLOAD;
63             }
64             #
65             ##########################################################################################
66              
67             ##########################################################################################
68             #
69             # Debug callback routine
70             #
71             sub debug_log {
72             my $message = shift;
73              
74             unless(defined($message)) { return undef }
75              
76             # caller 0 = current
77             # caller 1 = eval
78             # caller 2 = call_debug
79             # caller 3 = actual caller
80             my $caller = (caller(3))[3];
81             print "$caller() $message\n";
82             #warn $message;
83             }
84              
85             sub debug_callback {
86             my ($self, $callback) = @_;
87              
88             unless(defined($callback)) {
89             return $self->{ _debug_callback };
90             }
91              
92             $self->set_callback('_debug_callback', $callback);
93             }
94              
95             sub call_debug {
96             my $self = shift;
97              
98             return unless(defined($self->{ _debug_callback }));
99              
100             if(defined($self->debug)) {
101             my $handler = $self->{ _debug_callback };
102             my $ret = eval { &$handler(@_); };
103              
104             return (defined($ret))?$ret:$@;
105             } else {
106             return undef;
107             }
108             }
109              
110             sub debug {
111             my ($self, $debug) = @_;
112              
113             if(defined($debug)) {
114             return $self->{ _debug } = $debug;
115             } else {
116             return $self->{ _debug };
117             }
118             }
119              
120             #
121             ##########################################################################################
122              
123             ##########################################################################################
124             #
125             # Callback setting/executing methods
126             #
127             sub execute {
128             my $self = shift;
129              
130             return unless(defined($self->{ _callback }));
131              
132             my $handler = $self->{ _callback };
133             my $ret = eval {
134             # block out die/warn just in case...
135             local $SIG{ __DIE__ };
136             local $SIG{ __WARN__ };
137             &$handler(@_);
138             };
139              
140             return (defined($ret))?$ret:$@;
141             }
142              
143             sub set_callback {
144             my ($self, $which, $callback) = @_;
145              
146             unless(defined($callback) and defined($which)) {
147             return $self->{ $which };
148             }
149              
150             if(ref($callback) eq 'CODE') {
151             $self->{ $which } = $callback;
152             } else {
153             return undef;
154             }
155             }
156              
157             sub callback {
158             my ($self, $callback) = @_;
159              
160             unless(defined($callback)) {
161             return $self->{ _callback };
162             }
163              
164             $self->set_callback('_callback', $callback);
165             }
166              
167             sub returnResults {
168             my $self = shift;
169             my $results = shift;
170              
171             if(defined($self->returnRawXML)) {
172             # return RAW XML only
173             return defined($self->callback)?$self->execute($results, @_):$results;
174             }
175              
176             my $returnContents;
177             unless(defined($self->{ _xml }->XML)) {
178             $self->{ _xml }->consume($results);
179             if($self->{ _xml }->isError) {
180             $self->call_debug( $self->{ _xml }->getErrorString );
181             }
182             }
183              
184             if(defined($self->returnXML)) {
185             # return PROCESSED XML only
186             $returnContents = $self->{ _xml }->SDEE;
187             return defined($self->callback)?$self->execute($returnContents, @_):$returnContents;
188             }
189              
190             # return only events
191             if(defined($self->callback)) {
192             # execute "callback" for each event
193             my @returnValues;
194             while(my $event = $self->{ _xml }->getEvent) {
195             my $ret = $self->execute($event, @_);
196             push(@returnValues, $ret);
197             }
198             return \@returnValues;
199             } else {
200             $returnContents = $self->{ _xml }->getEvents;
201             return defined($self->callback)?$self->execute($returnContents, @_):$returnContents;
202             }
203             }
204             #
205             ##########################################################################################
206              
207             ##########################################################################################
208             #
209             # set/get methods
210             #
211             sub returnRawXML {
212             my ($self, $returnRawXML) = @_;
213              
214             if(defined($returnRawXML)) {
215             return $self->{ _returnRawXML } = $returnRawXML;
216             } else {
217             return $self->{ _returnRawXML };
218             }
219             }
220              
221             sub returnXML {
222             my ($self, $returnXML) = @_;
223              
224             if(defined($returnXML)) {
225             return $self->{ _returnXML } = $returnXML;
226             } else {
227             return $self->{ _returnXML };
228             }
229             }
230              
231             sub returnEvents {
232             my ($self, $returnEvents) = @_;
233              
234             if(defined($returnEvents)) {
235             return $self->{ _returnEvents } = $returnEvents;
236             } else {
237             return $self->{ _returnEvents };
238             }
239             }
240             #
241             ##########################################################################################
242              
243             ##########################################################################################
244             #
245             sub getNumberOfSubscriptions {
246             my $self = shift;
247              
248             return scalar keys %{$self->{ _subscriptions }};
249             }
250              
251             sub getSubscription {
252             my ($self, $subscriptionId) = @_;
253              
254             unless(defined($subscriptionId) and exists($self->{ _subscriptions }->{ $subscriptionId })) { return undef }
255              
256             return $self->{ _subscriptions }->{ $subscriptionId };
257             }
258              
259             sub getSubscriptionIds {
260             my $self = shift;
261              
262             my @returnValue = keys %{$self->{ _subscriptions }};
263             return \@returnValue;
264             }
265              
266             sub addSubscription {
267             my $self = shift;
268              
269             if( $#_ == 0 and ref($_[0]) eq 'Net::SDEE::Subscription') {
270             return $self->open($_[0]);
271             } else {
272             return $self->open(Net::SDEE::Subscription->new(@_));
273             }
274             }
275              
276             sub deleteSubscription {
277             my ($self, $subscriptionId) = @_;
278              
279             unless(defined($subscriptionId) and exists($self->{ _subscriptions }->{ $subscriptionId })) { return undef }
280              
281             return delete($self->{ _subscriptions }->{ $subscriptionId });
282             }
283              
284             sub addQuery {
285             my $self = shift;
286              
287             if( $#_ == 0 and ref($_[0]) eq 'Net::SDEE::Query') {
288             $self->{ _query } = $_[0];
289             } else {
290             $self->{ _query } = Net::SDEE::Query->new(@_);
291             }
292             }
293              
294             sub addSession {
295             my $self = shift;
296              
297             if( $#_ == 0 and ref($_[0]) eq 'Net::SDEE::Session') {
298             $self->{ _session } = $_[0];
299             } else {
300             $self->{ _session } = Net::SDEE::Session->new(@_);
301             }
302             }
303             #
304             ##########################################################################################
305              
306             ##########################################################################################
307             #
308             sub new {
309             my $caller = shift;
310             my %args = @_;
311              
312             my $class = (ref($caller) or $caller);
313             my $self = bless {
314             '_xml', XML::SDEE->new(),
315             '_session', undef,
316             '_subscriptions', {},
317             '_query', undef,
318             '_callback', undef,
319             '_returnXML', undef,
320             '_returnRawXML', undef,
321             '_returnEvents', undef,
322             '_debug', undef,
323             '_debug_callback', \&debug_log
324             }, $class;
325              
326             if(defined($args{ Session }) and ref($args{ Session }) eq 'Net::SDEE::Session') {
327             $self->{ _session } = $args{ Session };
328             delete($args{ Session }); # clean up for loop @ bottom
329             } else {
330             $self->{ _session } = Net::SDEE::Session->new();
331             }
332              
333             if(defined($args{ Query }) and ref($args{ Query }) eq 'Net::SDEE::Query') {
334             $self->{ _query } = $args{ Query };
335             delete($args{ Query }); # clean up for loop @ bottom
336              
337             # we should NOT have both, so drop the subscription if we do...
338             delete($args{ Subscription });
339             }
340              
341             #
342             # Note, we cannot pass in a Subscription because we need an Subscription ID that
343             # we only get when we connect.
344             #
345             foreach my $attribute ( keys %args ) {
346             $self->$attribute( $args{ $attribute });
347             }
348              
349             #
350             # If we've set 'returnXML', then make sure 'returnEvents' is unset.
351             # Also, if 'returnXML' is not set, make sure 'returnEvents' is set.
352             if(defined($self->returnRawXML)) {
353             # return RAW XML
354             $self->returnXML(undef);
355             $self->returnEvents(undef);
356             } elsif(defined($self->returnXML)) {
357             # return PROCESSED XML
358             $self->returnRawXML(undef);
359             $self->returnEvents(undef);
360             } else {
361             # return Events
362             $self->returnXML(undef);
363             $self->returnRawXML(undef);
364             $self->returnEvents(1);
365             }
366              
367             return $self;
368             }
369              
370             #
371             # Opens a session
372             # Parameters:
373             # - action = open
374             # - startTime = 0
375             # - events = evtype
376             # - idsAlertSeverities
377             # - force = yes/no
378             #
379             # Response Code:
380             # - errLimitExceeded = server has reached subscription limit
381             #
382             # Return subscriptionID
383             #
384             sub open {
385             my $self = shift;
386              
387             my $subscription = undef;
388             if(defined($_[0]) and ref($_[0]) eq 'Net::SDEE::Subscription') {
389             # got a subscription object
390             $subscription = shift;
391             } else {
392             # don't have a subscription object, make a new one
393             $subscription = Net::SDEE::Subscription->new();
394             }
395              
396             unless(defined($subscription->sessionId)) {
397             if(my $sessionId = $self->{ _session }->sessionId) {
398             $subscription->sessionId($sessionId);
399             }
400             }
401              
402             if( $#_ > 0 ) {
403             my %args = @_;
404             foreach my $parameter (keys %args) {
405             $subscription->$parameter($args{ $parameter });
406             }
407             }
408              
409             $subscription->action('open');
410            
411             my $LWP = LWP::UserAgent->new();
412             my $result = $LWP->post(
413             $self->{ _session }->getURL,
414             $subscription->getParameters(@_open_parameters),
415             %{ $self->{ _session }->getHeader }
416             );
417              
418             if($result->is_success) {
419             if($self->{ _session }->Type eq 'subscription') {
420             if(my $cookie = $result->headers('SET-COOKIE')) {
421             $self->{ _session }->Cookie((split(';', $cookie))[0]);
422             } else {
423             $self->call_debug( 'No Cookie in header: ' . $result->status_line);
424             return undef;
425             }
426             $self->{ _session }->state('opened');
427             }
428              
429             $self->{ _xml }->reset;
430             $self->{ _xml }->consume($result->content);
431             if(my $sessionId = $self->{ _xml }->sessionId) {
432             $self->sessionId($sessionId);
433             $subscription->sessionId($sessionId);
434             $self->call_debug("New SessionID: $sessionId");
435             } elsif($sessionId = $self->{ _session }->sessionId) {
436             $self->call_debug("Existing SessionID: $sessionId");
437             } else {
438             $self->call_debug('NO SessionID');
439             }
440             if(my $subscriptionId = $self->{ _xml }->subscriptionId) {
441             $subscription->subscriptionId($subscriptionId);
442             $self->{ _subscriptions }->{ $subscriptionId } = $subscription;
443             $self->call_debug("New SubscriptionID: $subscriptionId");
444             }
445             } else {
446             $self->call_debug( 'open failed: ' . $result->status_line);
447             return undef;
448             }
449             return $self->returnResults($result->content, $subscription->subscriptionId);
450             }
451              
452             #
453             # Retrieve Events
454             # Parameters:
455             # - action = get
456             # - timeout = # (blocking, waiting for events )
457             # - maxNbrOfEvents = #
458             # - confirm = yes/no
459             # * unconfirmed events will be resent
460             #
461             # Response Codes:
462             # - missedEvents - server dropped events since last retrieval
463             # - errNotFound - subscription not open
464             # - errInUse - retrieval already taking place
465             #
466             sub get {
467             my ($self, $subscriptionId) = @_;
468              
469             my $parameters;
470             if(defined($subscriptionId)) {
471             # setup for subscription
472              
473             # perhaps should call open() to fix these? but what to do w/ returned XML?
474             unless(defined($self->{ _subscriptions }->{ $subscriptionId })) {
475             $self->call_debug("No such subscription Id: $subscriptionId");
476             return undef;
477             }
478             unless( $self->{ _session }->state eq 'opened' ) {
479             $self->call_debug('Session state is ' . $self->{ _session }->state);
480             return undef;
481             }
482             $self->{ _subscriptions }->{ $subscriptionId }->action('get');
483             $parameters = $self->{ _subscriptions }->{ $subscriptionId }->getParameters(@_get_parameters);
484             } else {
485             # setup for query
486             unless(defined($self->{ _query })) {
487             $self->{ _query } = Net::SDEE::Query->new();
488             }
489             $parameters = $self->{ _query }->getParameters(@_get_parameters);
490             }
491              
492             my $LWP = LWP::UserAgent->new();
493             my $result = $LWP->post(
494             $self->{ _session }->getURL,
495             $parameters,
496             %{ $self->{ _session }->getHeader }
497             );
498              
499             if($result->is_success) {
500             #
501             # Response Codes:
502             # - missedEvents - server dropped events since last retrieval
503             # - errNotFound - subscription not open
504             # - errInUse - retrieval already taking place
505             #
506             } else {
507             $self->call_debug('http session failed ' . $result->status_line);
508             $self->{ _session }->state('closed');
509             return undef;
510             }
511             $self->{ _xml }->reset;
512             return $self->returnResults($result->content, $subscriptionId);
513             }
514              
515             #
516             # Cancels a blocked subscription
517             #
518             # Parameters:
519             # - action = cancel
520             #
521             # Response Codes:
522             # - errNotFound - subscription not open
523             #
524             # Return ?? XML document?
525             #
526             sub cancel {
527             my ($self, $subscriptionId) = @_;
528              
529             return undef unless(defined($subscriptionId));
530              
531             $self->call_debug("SubscriptionId: $subscriptionId");
532              
533             my $subscription;
534             unless($subscription = $self->getSubscription( $subscriptionId )) {
535             $self->call_debug("NO subscription $subscriptionId");
536             return undef;
537             }
538              
539             $subscription->action('cancel');
540              
541             my $LWP = LWP::UserAgent->new();
542             my $result = $LWP->post(
543             $self->{ _session }->getURL,
544             $subscription->getParameters(@_cancel_parameters),
545             %{ $self->{ _session }->getHeader }
546             );
547              
548             if($result->is_success) {
549             #
550             # Response Codes:
551             # - errNotFound - subscription not open
552             #
553             } else {
554             $self->call_debug( 'cancel failed: ' . $result->status_line);
555             return undef;
556             }
557             $self->{ _xml }->reset;
558             return $self->returnResults($result->content, $subscriptionId);
559             }
560              
561             #
562             # Closes a subscription
563             #
564             # Parameters:
565             # - action = close
566             #
567             # Response Codes:
568             # - errNotFound - subscription not open
569             #
570             # Return ?? XML document?
571             #
572             sub close {
573             my ($self, $subscriptionId) = @_;
574              
575             return undef unless(defined($subscriptionId));
576              
577             my $subscription;
578             unless($subscription = $self->getSubscription( $subscriptionId )) {
579             $self->call_debug("NO subscription $subscriptionId");
580             return undef;
581             }
582              
583             my $sessionId = $subscription->sessionId;
584             $self->call_debug("SessionId: $sessionId, SubscriptionId: $subscriptionId");
585              
586             $subscription->action('close');
587              
588             my $LWP = LWP::UserAgent->new();
589             my $result = $LWP->post(
590             $self->{ _session }->getURL,
591             $subscription->getParameters(@_close_parameters),
592             %{ $self->{ _session }->getHeader }
593             );
594              
595             $self->deleteSubscription($subscriptionId);
596             if($result->is_success) {
597             #
598             # Response Codes:
599             # - errNotFound - subscription not open
600             #
601             } else {
602             $self->call_debug( 'close failed: ' . $result->status_line);
603             return undef;
604             }
605             $self->{ _xml }->reset;
606             return $self->returnResults($result->content, $subscriptionId);
607             }
608              
609             #
610             # get ALL
611             sub getAll {
612             my $self = shift;
613              
614             my $returnAll = {};
615              
616             foreach my $subscriptionId ( @{ $self->getSubscriptionIds } ) {
617             if(my $return_value =$self->get($subscriptionId)) {
618             $self->call_debug($return_value);
619             }
620             }
621              
622             return $returnAll;
623             }
624              
625             #
626             # close ALL
627             sub closeAll {
628             my $self = shift;
629              
630             my $returnAll = {};
631              
632             # need to close ALL the subscriptions
633             foreach my $subscriptionId ( @{ $self->getSubscriptionIds }) {
634             if(my $return_value =$self->close($subscriptionId)) {
635             $self->call_debug($return_value);
636             }
637             }
638              
639             return $returnAll;
640             }
641              
642             #
643             # Close the session, just in case we forgot...
644             sub DESTROY {
645             my $self = shift;
646              
647             # need to close ALL the subscriptions
648             $self->closeAll();
649             }
650              
651             #
652             ##########################################################################################
653              
654             1;
655             __END__