line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# ============================================================================== |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# Copyright (C) 2000-2008 University of Manchester |
4
|
|
|
|
|
|
|
# WSRF::Lite is free software; you can redistribute it |
5
|
|
|
|
|
|
|
# and/or modify it under the same terms as Perl itself. |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
# version 0.8.2.7 |
8
|
|
|
|
|
|
|
# Author: Mark Mc Keown (mark.mckeown@manchester.ac.uk) |
9
|
|
|
|
|
|
|
# |
10
|
|
|
|
|
|
|
# Stefan Zasada (sjzasada@lycos.co.uk) did most of the work implementing |
11
|
|
|
|
|
|
|
# WS-Security - a big thanks goes to Savas Parastatidis |
12
|
|
|
|
|
|
|
# (http://savas.parastatidis.name/) for helping to get it working with |
13
|
|
|
|
|
|
|
# .NET. |
14
|
|
|
|
|
|
|
# |
15
|
|
|
|
|
|
|
# Contributors: Andrew Porter, Stephen Pickles, |
16
|
|
|
|
|
|
|
# Sven van den Berghe, Jonathan Chin |
17
|
|
|
|
|
|
|
# Jamie Vicary, Bruno Harbulot |
18
|
|
|
|
|
|
|
# Ivan Porro, Ross Nicoll, Luke @ yahoo |
19
|
|
|
|
|
|
|
# Mary Thompson, Alex Peeters, Bjoern A. Zeeb |
20
|
|
|
|
|
|
|
# Glen Fu, John Newman, Doug Claar, Edward Kawas |
21
|
|
|
|
|
|
|
# |
22
|
|
|
|
|
|
|
# Some parts of the this module are taken from SOAP::Lite - |
23
|
|
|
|
|
|
|
# here is the required copyright |
24
|
|
|
|
|
|
|
# |
25
|
|
|
|
|
|
|
# Copyright (C) 2000-2005 Paul Kulchenko (paulclinger@yahoo.com) |
26
|
|
|
|
|
|
|
# |
27
|
|
|
|
|
|
|
#=============================================================================== |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
=pod |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=head1 NAME |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
WSRF::Lite - Implementation of the Web Service Resource Framework |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=head1 VERSION |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
This document refers to version 0.8.3.1 of WSRF::Lite released Feb, 2011 |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=head1 SYNOPSIS |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
This is an implementation of the Web Service Resource Framework (WSRF), |
42
|
|
|
|
|
|
|
which is built on SOAP::Lite. It provides support for WSRF, WS-Addressing |
43
|
|
|
|
|
|
|
and for digitally signing a SOAP messages using an X.509 certificate |
44
|
|
|
|
|
|
|
according to the OASIS WS-Security standard. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=head1 DESCRIPTION |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
WSRF::Lite consists of a number of classes for developing WS-Resources. |
49
|
|
|
|
|
|
|
A WS-Resource is an entity that has a Web service interface defined by |
50
|
|
|
|
|
|
|
the WSRF family of specifications that maintains state between calls |
51
|
|
|
|
|
|
|
to the service. |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
WSRF::Lite provides a number of ways of implementing |
54
|
|
|
|
|
|
|
WS-Resources: one approach uses a process to store the state of the |
55
|
|
|
|
|
|
|
WS-Resource, another approach uses a process to store the state of many |
56
|
|
|
|
|
|
|
WS-Resources and the last approach uses files to store the state of the |
57
|
|
|
|
|
|
|
WS-Resources between calls to the WS-Resource. The different approachs have |
58
|
|
|
|
|
|
|
different benifits, using one process per WS-Resource does not scale very |
59
|
|
|
|
|
|
|
well and isn't very fault tolerant (eg a machine reboot) but is quite |
60
|
|
|
|
|
|
|
easy to develop. The approachs are just examples of how to implement a |
61
|
|
|
|
|
|
|
WS-Resource, it should be possible to use them as a basis to develop |
62
|
|
|
|
|
|
|
tailored solutions for particular applications. For example you could use a |
63
|
|
|
|
|
|
|
relational database to store the state of the WS-Resources. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=cut |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
package WSRF::Lite; |
68
|
|
|
|
|
|
|
|
69
|
1
|
|
|
1
|
|
21387
|
use SOAP::Lite; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
use strict; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
use vars qw{ $VERSION }; |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
BEGIN { |
75
|
|
|
|
|
|
|
$VERSION = '0.8.3.1'; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# WSRF uses WS-Address headers in the SOAP Header - by default |
79
|
|
|
|
|
|
|
# SOAP::Lite will croak on these so we change the default in |
80
|
|
|
|
|
|
|
# SOAP::Lite. The SOAP spec defines the mustUnderstand attribute - |
81
|
|
|
|
|
|
|
# if an element has this attribute then the service must understand |
82
|
|
|
|
|
|
|
# what to do with this element. See |
83
|
|
|
|
|
|
|
# http://www.w3.org/TR/soap12-part1/#soapmu |
84
|
|
|
|
|
|
|
# |
85
|
|
|
|
|
|
|
# BUG - should ony accept headers we really do understand |
86
|
|
|
|
|
|
|
$SOAP::Constants::DO_NOT_CHECK_MUSTUNDERSTAND = 1; |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# A singleton class to hold the external socket if there is one. |
89
|
|
|
|
|
|
|
package WSRF::SocketHolder; |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
my $oneTrueSelf; |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub instance { |
94
|
|
|
|
|
|
|
unless ( defined $oneTrueSelf ) { |
95
|
|
|
|
|
|
|
my ( $type, $extern_socket ) = @_; |
96
|
|
|
|
|
|
|
my $this = { _socket => $extern_socket }; |
97
|
|
|
|
|
|
|
$oneTrueSelf = bless $this, $type; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
return $oneTrueSelf; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
sub close { |
103
|
|
|
|
|
|
|
my $self = shift; |
104
|
|
|
|
|
|
|
if ( defined $oneTrueSelf ) { |
105
|
|
|
|
|
|
|
my $foo = |
106
|
|
|
|
|
|
|
defined( $ENV{SSL} ) |
107
|
|
|
|
|
|
|
? $self->{_socket}->close( SSL_no_shutdown => 1 ) |
108
|
|
|
|
|
|
|
: $self->{_socket}->close; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
undef $oneTrueSelf; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
#=============================================================================== |
114
|
|
|
|
|
|
|
package WSRF::Constants; |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=pod |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=head1 WSRF::Constants |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
Defines the set of namespaces used in WSRF::Lite and the directories used to store |
121
|
|
|
|
|
|
|
the named sockets and data files. |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=over |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=item $WSRF::Constants::SOCKETS_DIRECTORY |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
Directory to contain the named sockets of the process based WS-Resources. |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=item $WSRF::Constants::Data |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
Directory used to store files that hold state of WS-Resoures that use file based storage |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=item $WSRF::Constants::WSA |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
WS-Addressing namespace. |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=item $WSRF::Constants::WSRL |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
WS-ResourceLifetimes namespace. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=item $WSRF::Constants::WSRP |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
WS-ResourceProperties namespace. |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=item $WSRF::Constants::WSSG |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
WS-ServiceGroup namespace. |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=item $WSRF::Constants::WSBF |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
WS-BaseFaults namespace. |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=item $WSRF::Constants::WSU |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
WS-Security untility namespace. |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=item $WSRF::Constants::WSSE |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
WS-Security extension namespace. |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=item $WSRF::Constants::WSA_ANON |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
From the WS-Addressing specification, it is used to indicate |
164
|
|
|
|
|
|
|
an anonymous return address. If you are using a request-response protocol like HTTP |
165
|
|
|
|
|
|
|
which uses the same connection for the request and response you use this as the |
166
|
|
|
|
|
|
|
ReplyTo address in SOAP WS-Addressing header of the request. |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=back |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
=cut |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
# |
173
|
|
|
|
|
|
|
# Where the named Sockets and ResourceProperty files are stored. |
174
|
|
|
|
|
|
|
# User can overide these in the Container script. |
175
|
|
|
|
|
|
|
$WSRF::Constants::SOCKETS_DIRECTORY = "/tmp/wsrf"; |
176
|
|
|
|
|
|
|
$WSRF::Constants::Data = $WSRF::Constants::SOCKETS_DIRECTORY . "/data/"; |
177
|
|
|
|
|
|
|
$WSRF::Constants::ExternSocket = undef; |
178
|
|
|
|
|
|
|
%WSRF::Constants::ModuleNamespaceMap = (); |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
#The set of namespaces used throughout. |
181
|
|
|
|
|
|
|
#$WSRF::Constants::WSA = 'http://www.w3.org/2005/03/addressing'; |
182
|
|
|
|
|
|
|
$WSRF::Constants::WSA = 'http://www.w3.org/2005/08/addressing'; |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
#$WSRF::Constants::WSRL = 'http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceLifetime'; |
185
|
|
|
|
|
|
|
$WSRF::Constants::WSRL = 'http://docs.oasis-open.org/wsrf/rl-2'; |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
#$WSRF::Constants::WSRP = 'http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties'; |
188
|
|
|
|
|
|
|
$WSRF::Constants::WSRP = 'http://docs.oasis-open.org/wsrf/rp-2'; |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
#$WSRF::Constants::WSSG = 'http://www.ibm.com/xmlns/stdwip/web-services/WS-ServiceGroup'; |
191
|
|
|
|
|
|
|
$WSRF::Constants::WSSG = 'http://docs.oasis-open.org/wsrf/sg-2'; |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
#$WSRF::Constants::WSBF = 'http://www.ibm.com/xmlns/stdwip/web-services/WS-BaseFaults'; |
194
|
|
|
|
|
|
|
$WSRF::Constants::WSBF = 'http://docs.oasis-open.org/wsrf/bf-2'; |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
$WSRF::Constants::WSU = |
197
|
|
|
|
|
|
|
'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'; |
198
|
|
|
|
|
|
|
$WSRF::Constants::WSSE = |
199
|
|
|
|
|
|
|
'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'; |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
#$WSRF::Constants::WSA_ANON = $WSRF::Constants::WSA.'/role/anonymous'; |
202
|
|
|
|
|
|
|
$WSRF::Constants::WSA_ANON = $WSRF::Constants::WSA . '/anonymous'; |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
$WSRF::Constants::DS = 'http://www.w3.org/2000/09/xmldsig#'; |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
#=============================================================================== |
207
|
|
|
|
|
|
|
# We override SOAP::SOM to store the raw XML from a SOAP message - this class is |
208
|
|
|
|
|
|
|
# used by the WSRF::Deserializer below. SOAP::Lite does not provide you with |
209
|
|
|
|
|
|
|
# access to the raw XML of a SOAP message (It was on the SOAP::Lite TODO list) |
210
|
|
|
|
|
|
|
# - here we override the SOAP::SOM module to provide access to the raw XML - |
211
|
|
|
|
|
|
|
# we override the SOAP::Deserializer which returns the SOAP::SOM object to |
212
|
|
|
|
|
|
|
# make sure that it actually keeps the XML |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
package WSRF::SOM; |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=pod |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=head1 WSRF::SOM |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
Extends SOAP::SOM with one extra method "raw_xml". |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=head2 METHODS |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=over |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=item raw_xml |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
Returns the raw XML of a message, useful if you want to parse the message using some |
229
|
|
|
|
|
|
|
other tool than provided with SOAP::Lite: |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
my $xml = $som->raw_xml; |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
=back |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=cut |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
use strict; |
238
|
|
|
|
|
|
|
use vars qw(@ISA); |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
@ISA = qw(SOAP::SOM); |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
# function to return raw XML |
243
|
|
|
|
|
|
|
sub raw_xml { |
244
|
|
|
|
|
|
|
my $self = shift; |
245
|
|
|
|
|
|
|
return $self->{_xml}; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
#=============================================================================== |
249
|
|
|
|
|
|
|
# We override the SOAP::Serializer to store the raw XML of the SOAP message. |
250
|
|
|
|
|
|
|
# Normally a SOAP::Lite service cannot access the raw XML of a request - this |
251
|
|
|
|
|
|
|
# is sometimes useful for the Service developer who might want to use |
252
|
|
|
|
|
|
|
# XML DOM instead of SOM. The Deserializer returns a WSRF::SOM object - wich |
253
|
|
|
|
|
|
|
# we have defined above. |
254
|
|
|
|
|
|
|
package WSRF::Deserializer; |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=pod |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
=head1 WSRF::Deserializer |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
Overrides SOAP::Deserializer to return a WSRF::SOM object, which includes the raw XML |
261
|
|
|
|
|
|
|
of the message, from the deserialize method. |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
=head2 METHODS |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
The methods are the same as SOAP::Deserializer. |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
=cut |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
use strict; |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
use vars qw(@ISA); |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
@ISA = qw(SOAP::Deserializer); |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
#This is very similar to the SOAP::Deserializer only a couple of lines are added |
276
|
|
|
|
|
|
|
# Copyright (C) 2000-2005 Paul Kulchenko (paulclinger@yahoo.com) |
277
|
|
|
|
|
|
|
sub deserialize { |
278
|
|
|
|
|
|
|
SOAP::Trace::trace('()'); |
279
|
|
|
|
|
|
|
my $self = shift->new; |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
# initialize |
282
|
|
|
|
|
|
|
$self->hrefs( {} ); |
283
|
|
|
|
|
|
|
$self->ids( {} ); |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
# TBD: find better way to signal parsing errors |
286
|
|
|
|
|
|
|
# This is returning a parsed body, however, if the message was mime |
287
|
|
|
|
|
|
|
# formatted, then the self->ids hash should be populated with mime parts |
288
|
|
|
|
|
|
|
# as will the self->mimeparser->parts array |
289
|
|
|
|
|
|
|
my $parsed = |
290
|
|
|
|
|
|
|
$self->decode( $_[0] ); # TBD: die on possible errors in Parser? |
291
|
|
|
|
|
|
|
# Thought - decode should return an ARRAY which may contain MIME::Entities |
292
|
|
|
|
|
|
|
# then the SOM object that is created and returned from this will know how |
293
|
|
|
|
|
|
|
# to parse them out |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
# Having this code here makes multirefs in the Body work, but multirefs |
296
|
|
|
|
|
|
|
# that reference XML fragments in a MIME part do not work. |
297
|
|
|
|
|
|
|
if ( keys %{ $self->ids() } ) { |
298
|
|
|
|
|
|
|
$self->traverse_ids($parsed); |
299
|
|
|
|
|
|
|
} else { |
300
|
|
|
|
|
|
|
$self->ids($parsed); |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
$self->decode_object($parsed); |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
# these are the changes from SOAP::Deserializer |
305
|
|
|
|
|
|
|
# otherwise the code is the same. We simply add the raw XML to |
306
|
|
|
|
|
|
|
# the som hash |
307
|
|
|
|
|
|
|
my $som = WSRF::SOM->new($parsed); |
308
|
|
|
|
|
|
|
$som->{'_xml'} = $_[0]; |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
# first check if MIME parser has been initialized |
311
|
|
|
|
|
|
|
# simple $self->mimeparser() call doesn't work because of |
312
|
|
|
|
|
|
|
# "lazy initialization" --PK |
313
|
|
|
|
|
|
|
if ( defined $self->{'_mimeparser'} && $self->mimeparser->parts ) { |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
# This seems like an unnecessary copy... does SOAP::SOM have a handle on |
316
|
|
|
|
|
|
|
# the SOAP::Lite->mimeparser instance so that I can skip this? |
317
|
|
|
|
|
|
|
$som->{'_parts'} = $self->mimeparser->parts; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
return $som; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
#=============================================================================== |
323
|
|
|
|
|
|
|
# We override the SOAP::Serializer to add extra namespaces to the SOAP element |
324
|
|
|
|
|
|
|
# - these are namesapace we will use a lot wsrl, wsrp, wsa. These are placed |
325
|
|
|
|
|
|
|
# in any SOAP message we return from the service. The user can use the |
326
|
|
|
|
|
|
|
# prefixs wsrl, wsrp and wsa and not have to worry about defining the |
327
|
|
|
|
|
|
|
# namespaces |
328
|
|
|
|
|
|
|
# |
329
|
|
|
|
|
|
|
# WSRF::WSRFSerializer is were the message is signed - signing is tricky |
330
|
|
|
|
|
|
|
# because we have to create the XML before we sign it, so the process of |
331
|
|
|
|
|
|
|
# signing a SOAP message requires two passes through the serializer. The |
332
|
|
|
|
|
|
|
# first pass (std_envelope) creates the SOAP message, the second actually |
333
|
|
|
|
|
|
|
# signs it. THIS IS NOT EFFICIENT BUT WHO CARES?! |
334
|
|
|
|
|
|
|
package WSRF::WSRFSerializer; |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
=pod |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
=head1 WSRF::WSRFSerializer |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
Overrides SOAP::Serializer. This class extends the SOAP::Serializer class which creates |
341
|
|
|
|
|
|
|
the XML SOAP Enevlope. WSRF::WSRFSerializer overrides the "envelope" method so that it |
342
|
|
|
|
|
|
|
adds the WSRF, WS-Addressing and WS-Security namespaces to the SOAP Envelope, it also |
343
|
|
|
|
|
|
|
where the message signing happens. The XML SOAP message has to be created before it |
344
|
|
|
|
|
|
|
can be signed. |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
=head2 METHODS |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
The methods are the same as SOAP::Serializer, the "envelope" method is overridden to |
349
|
|
|
|
|
|
|
include the extra namespaces and to digitally sign the SOAP message if required. |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=cut |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
use vars qw(@ISA); |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
@ISA = qw(SOAP::Serializer); |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
# This function is the same as SOAP::Serializer::envelope except that |
358
|
|
|
|
|
|
|
# it adds an extra attribute (wsu:Id="myBody") into the Body element - |
359
|
|
|
|
|
|
|
# this is used by WS-Security to identify the bits of a message that |
360
|
|
|
|
|
|
|
# have been signed. |
361
|
|
|
|
|
|
|
# |
362
|
|
|
|
|
|
|
# We also add extra namespaces for WSRF and WSA into the SOAP Envelope |
363
|
|
|
|
|
|
|
# element so we do not need to declare them in the message itself |
364
|
|
|
|
|
|
|
# Copyright (C) 2000-2005 Paul Kulchenko (paulclinger@yahoo.com) |
365
|
|
|
|
|
|
|
sub old_envelope { |
366
|
|
|
|
|
|
|
SOAP::Trace::trace('()'); |
367
|
|
|
|
|
|
|
my $self = shift->new; |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
$self->autotype(0); |
370
|
|
|
|
|
|
|
$self->attr( |
371
|
|
|
|
|
|
|
{ |
372
|
|
|
|
|
|
|
'xmlns:wsa' => $WSRF::Constants::WSA, |
373
|
|
|
|
|
|
|
'xmlns:wsrl' => $WSRF::Constants::WSRL, |
374
|
|
|
|
|
|
|
'xmlns:wsrp' => $WSRF::Constants::WSRP, |
375
|
|
|
|
|
|
|
'xmlns:wsu' => $WSRF::Constants::WSU, |
376
|
|
|
|
|
|
|
'xmlns:wsse' => $WSRF::Constants::WSSE |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
); |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
my $type = shift; |
381
|
|
|
|
|
|
|
my ( @parameters, @header ); |
382
|
|
|
|
|
|
|
for (@_) { |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
# Find all the SOAP Headers |
385
|
|
|
|
|
|
|
if ( defined($_) && ref($_) && UNIVERSAL::isa( $_ => 'SOAP::Header' ) ) |
386
|
|
|
|
|
|
|
{ |
387
|
|
|
|
|
|
|
push( @header, $_ ); |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
# Find all the SOAP Message Parts (attachments) |
390
|
|
|
|
|
|
|
} elsif ( defined($_) |
391
|
|
|
|
|
|
|
&& ref($_) |
392
|
|
|
|
|
|
|
&& $self->context |
393
|
|
|
|
|
|
|
&& $self->context->packager->is_supported_part($_) ) |
394
|
|
|
|
|
|
|
{ |
395
|
|
|
|
|
|
|
$self->context->packager->push_part($_); |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
# Find all the SOAP Body elements |
398
|
|
|
|
|
|
|
} else { |
399
|
|
|
|
|
|
|
push( @parameters, $_ ); |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
my $header = @header ? SOAP::Data->set_value(@header) : undef; |
403
|
|
|
|
|
|
|
my ( $body, $parameters ); |
404
|
|
|
|
|
|
|
if ( $type eq 'method' || $type eq 'response' ) { |
405
|
|
|
|
|
|
|
SOAP::Trace::method(@parameters); |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
my $method = shift(@parameters); |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
# or die "Unspecified method for SOAP call\n"; |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
$parameters = @parameters ? SOAP::Data->set_value(@parameters) : undef; |
412
|
|
|
|
|
|
|
if ( !defined($method) ) { |
413
|
|
|
|
|
|
|
} elsif ( UNIVERSAL::isa( $method => 'SOAP::Data' ) ) { |
414
|
|
|
|
|
|
|
$body = $method; |
415
|
|
|
|
|
|
|
} elsif ( $self->use_prefix ) { |
416
|
|
|
|
|
|
|
$body = SOAP::Data->name($method)->uri( $self->uri ); |
417
|
|
|
|
|
|
|
} else { |
418
|
|
|
|
|
|
|
$body = |
419
|
|
|
|
|
|
|
SOAP::Data->name($method)->attr( { 'xmlns' => $self->uri } ); |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
#$body = SOAP::Data->name($method)->uri($self->uri); # original return before use_prefix |
422
|
|
|
|
|
|
|
} |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
# This is breaking a unit test right now... |
425
|
|
|
|
|
|
|
$body->set_value( |
426
|
|
|
|
|
|
|
SOAP::Utils::encode_data( $parameters ? \$parameters : () ) ) |
427
|
|
|
|
|
|
|
if $body; |
428
|
|
|
|
|
|
|
} elsif ( $type eq 'fault' ) { |
429
|
|
|
|
|
|
|
SOAP::Trace::fault(@parameters); |
430
|
|
|
|
|
|
|
$body = |
431
|
|
|
|
|
|
|
SOAP::Data->name( |
432
|
|
|
|
|
|
|
SOAP::Utils::qualify( $self->envprefix => 'Fault' ) ) |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
# parameters[1] needs to be escaped - thanks to aka_hct at gmx dot de |
435
|
|
|
|
|
|
|
# commented on 2001/03/28 because of failing in ApacheSOAP |
436
|
|
|
|
|
|
|
# need to find out more about it |
437
|
|
|
|
|
|
|
# -> attr({'xmlns' => ''}) |
438
|
|
|
|
|
|
|
->value( |
439
|
|
|
|
|
|
|
\SOAP::Data->set_value( |
440
|
|
|
|
|
|
|
SOAP::Data->name( |
441
|
|
|
|
|
|
|
faultcode => SOAP::Utils::qualify( |
442
|
|
|
|
|
|
|
$self->envprefix => $parameters[0] |
443
|
|
|
|
|
|
|
) |
444
|
|
|
|
|
|
|
)->type(""), |
445
|
|
|
|
|
|
|
SOAP::Data->name( |
446
|
|
|
|
|
|
|
faultstring => SOAP::Utils::encode_data( $parameters[1] ) |
447
|
|
|
|
|
|
|
)->type(""), |
448
|
|
|
|
|
|
|
defined( $parameters[2] ) |
449
|
|
|
|
|
|
|
? SOAP::Data->name( |
450
|
|
|
|
|
|
|
detail => do { |
451
|
|
|
|
|
|
|
my $detail = $parameters[2]; |
452
|
|
|
|
|
|
|
ref $detail ? \$detail : $detail; |
453
|
|
|
|
|
|
|
} |
454
|
|
|
|
|
|
|
) |
455
|
|
|
|
|
|
|
: (), |
456
|
|
|
|
|
|
|
defined( $parameters[3] ) |
457
|
|
|
|
|
|
|
? SOAP::Data->name( faultactor => $parameters[3] )->type("") |
458
|
|
|
|
|
|
|
: (), |
459
|
|
|
|
|
|
|
) |
460
|
|
|
|
|
|
|
); |
461
|
|
|
|
|
|
|
} elsif ( $type eq 'freeform' ) { |
462
|
|
|
|
|
|
|
SOAP::Trace::freeform(@parameters); |
463
|
|
|
|
|
|
|
$body = SOAP::Data->set_value(@parameters); |
464
|
|
|
|
|
|
|
} elsif ( !defined($type) ) { |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
# This occurs when the Body is intended to be null. When no method has been |
467
|
|
|
|
|
|
|
# passed in of any kind. |
468
|
|
|
|
|
|
|
} else { |
469
|
|
|
|
|
|
|
die "Wrong type of envelope ($type) for SOAP call\n"; |
470
|
|
|
|
|
|
|
} |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
$self->seen( {} ); # reinitialize multiref table |
473
|
|
|
|
|
|
|
# Build the envelope |
474
|
|
|
|
|
|
|
# Right now it is possible for $body to be a SOAP::Data element that has not |
475
|
|
|
|
|
|
|
# XML escaped any values. How do you remedy this? |
476
|
|
|
|
|
|
|
my ($encoded) = $self->encode_object( |
477
|
|
|
|
|
|
|
SOAP::Data->name( |
478
|
|
|
|
|
|
|
SOAP::Utils::qualify( $self->envprefix => 'Envelope' ) => |
479
|
|
|
|
|
|
|
\SOAP::Data->value( |
480
|
|
|
|
|
|
|
( |
481
|
|
|
|
|
|
|
$header ? SOAP::Data->name( |
482
|
|
|
|
|
|
|
SOAP::Utils::qualify( $self->envprefix => 'Header' ) => |
483
|
|
|
|
|
|
|
\$header |
484
|
|
|
|
|
|
|
) : () |
485
|
|
|
|
|
|
|
), |
486
|
|
|
|
|
|
|
( |
487
|
|
|
|
|
|
|
$body |
488
|
|
|
|
|
|
|
? SOAP::Data->name( |
489
|
|
|
|
|
|
|
SOAP::Utils::qualify( $self->envprefix => 'Body' ) => |
490
|
|
|
|
|
|
|
\$body |
491
|
|
|
|
|
|
|
)->attr( { 'wsu:Id' => $WSRF::WSS::ID{myBody} } ) |
492
|
|
|
|
|
|
|
: SOAP::Data->name( |
493
|
|
|
|
|
|
|
SOAP::Utils::qualify( $self->envprefix => 'Body' ) |
494
|
|
|
|
|
|
|
)->attr( { 'wsu:Id' => $WSRF::WSS::ID{myBody} } ) |
495
|
|
|
|
|
|
|
), |
496
|
|
|
|
|
|
|
) |
497
|
|
|
|
|
|
|
)->attr( $self->attr ) |
498
|
|
|
|
|
|
|
); |
499
|
|
|
|
|
|
|
$self->signature( $parameters->signature ) if ref $parameters; |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
# IMHO multirefs should be encoded after Body, but only some |
502
|
|
|
|
|
|
|
# toolkits understand this encoding, so we'll keep them for now (04/15/2001) |
503
|
|
|
|
|
|
|
# as the last element inside the Body |
504
|
|
|
|
|
|
|
# v -------------- subelements of Envelope |
505
|
|
|
|
|
|
|
# vv -------- last of them (Body) |
506
|
|
|
|
|
|
|
# v --- subelements |
507
|
|
|
|
|
|
|
push( @{ $encoded->[2]->[-1]->[2] }, $self->encode_multirefs ) |
508
|
|
|
|
|
|
|
if ref $encoded->[2]->[-1]->[2]; |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
# Sometimes SOAP::Serializer is invoked statically when there is no context. |
511
|
|
|
|
|
|
|
# So first check to see if a context exists. |
512
|
|
|
|
|
|
|
# TODO - a context needs to be initialized by a constructor? |
513
|
|
|
|
|
|
|
if ( $self->context && $self->context->packager->parts ) { |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
# TODO - this needs to be called! Calling it though wraps the payload twice! |
516
|
|
|
|
|
|
|
# return $self->context->packager->package($self->xmlize($encoded)); |
517
|
|
|
|
|
|
|
} |
518
|
|
|
|
|
|
|
return $self->xmlize($encoded); |
519
|
|
|
|
|
|
|
} |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
sub std_envelope { |
522
|
|
|
|
|
|
|
SOAP::Trace::trace('()'); |
523
|
|
|
|
|
|
|
my $self = shift->new; |
524
|
|
|
|
|
|
|
my $type = shift; |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
$self->autotype(0); |
527
|
|
|
|
|
|
|
$self->attr( |
528
|
|
|
|
|
|
|
{ |
529
|
|
|
|
|
|
|
'xmlns:wsa' => $WSRF::Constants::WSA, |
530
|
|
|
|
|
|
|
'xmlns:wsrl' => $WSRF::Constants::WSRL, |
531
|
|
|
|
|
|
|
'xmlns:wsrp' => $WSRF::Constants::WSRP, |
532
|
|
|
|
|
|
|
'xmlns:wsu' => $WSRF::Constants::WSU, |
533
|
|
|
|
|
|
|
'xmlns:ds' => $WSRF::Constants::DS, |
534
|
|
|
|
|
|
|
'xmlns:wsse' => $WSRF::Constants::WSSE |
535
|
|
|
|
|
|
|
} |
536
|
|
|
|
|
|
|
); |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
my ( @parameters, @header ); |
539
|
|
|
|
|
|
|
for (@_) { |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
# Find all the SOAP Headers |
542
|
|
|
|
|
|
|
if ( defined($_) && ref($_) && UNIVERSAL::isa( $_ => 'SOAP::Header' ) ) |
543
|
|
|
|
|
|
|
{ |
544
|
|
|
|
|
|
|
push( @header, $_ ); |
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
# Find all the SOAP Message Parts (attachments) |
547
|
|
|
|
|
|
|
} elsif ( defined($_) |
548
|
|
|
|
|
|
|
&& ref($_) |
549
|
|
|
|
|
|
|
&& $self->context |
550
|
|
|
|
|
|
|
&& $self->context->packager->is_supported_part($_) ) |
551
|
|
|
|
|
|
|
{ |
552
|
|
|
|
|
|
|
$self->context->packager->push_part($_); |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
# Find all the SOAP Body elements |
555
|
|
|
|
|
|
|
} else { |
556
|
|
|
|
|
|
|
push( @parameters, SOAP::Utils::encode_data($_) ); |
557
|
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
} |
559
|
|
|
|
|
|
|
my $header = @header ? SOAP::Data->set_value(@header) : undef; |
560
|
|
|
|
|
|
|
my ( $body, $parameters ); |
561
|
|
|
|
|
|
|
if ( $type eq 'method' || $type eq 'response' ) { |
562
|
|
|
|
|
|
|
SOAP::Trace::method(@parameters); |
563
|
|
|
|
|
|
|
|
564
|
|
|
|
|
|
|
my $method = shift(@parameters); |
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
# or die "Unspecified method for SOAP call\n"; |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
$parameters = @parameters ? SOAP::Data->set_value(@parameters) : undef; |
569
|
|
|
|
|
|
|
if ( !defined($method) ) { |
570
|
|
|
|
|
|
|
} elsif ( UNIVERSAL::isa( $method => 'SOAP::Data' ) ) { |
571
|
|
|
|
|
|
|
$body = $method; |
572
|
|
|
|
|
|
|
} elsif ( $self->use_default_ns ) { |
573
|
|
|
|
|
|
|
if ( $self->{'_ns_uri'} ) { |
574
|
|
|
|
|
|
|
$body = |
575
|
|
|
|
|
|
|
SOAP::Data->name($method) |
576
|
|
|
|
|
|
|
->attr( { 'xmlns' => $self->{'_ns_uri'}, } ); |
577
|
|
|
|
|
|
|
} else { |
578
|
|
|
|
|
|
|
$body = SOAP::Data->name($method); |
579
|
|
|
|
|
|
|
} |
580
|
|
|
|
|
|
|
} else { |
581
|
|
|
|
|
|
|
|
582
|
|
|
|
|
|
|
# Commented out by Byrne on 1/4/2006 - to address default namespace problems |
583
|
|
|
|
|
|
|
# $body = SOAP::Data->name($method)->uri($self->{'_ns_uri'}); |
584
|
|
|
|
|
|
|
# $body = $body->prefix($self->{'_ns_prefix'}) if ($self->{'_ns_prefix'}); |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
# Added by Byrne on 1/4/2006 - to avoid the unnecessary creation of a new |
587
|
|
|
|
|
|
|
# namespace |
588
|
|
|
|
|
|
|
# Begin New Code (replaces code commented out above) |
589
|
|
|
|
|
|
|
$body = SOAP::Data->name($method); |
590
|
|
|
|
|
|
|
my $pre = $self->find_prefix( $self->{'_ns_uri'} ); |
591
|
|
|
|
|
|
|
$body = $body->prefix($pre) if ( $self->{'_ns_prefix'} ); |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
# End new code |
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
} |
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
# This is breaking a unit test right now... |
598
|
|
|
|
|
|
|
#$body->set_value(SOAP::Utils::encode_data($parameters ? \$parameters : ())) if $body; |
599
|
|
|
|
|
|
|
$body->set_value( $parameters ? \$parameters : () ) if $body; |
600
|
|
|
|
|
|
|
} elsif ( $type eq 'fault' ) { |
601
|
|
|
|
|
|
|
SOAP::Trace::fault(@parameters); |
602
|
|
|
|
|
|
|
$body = |
603
|
|
|
|
|
|
|
SOAP::Data->name( |
604
|
|
|
|
|
|
|
SOAP::Utils::qualify( $self->envprefix => 'Fault' ) ) |
605
|
|
|
|
|
|
|
|
606
|
|
|
|
|
|
|
# parameters[1] needs to be escaped - thanks to aka_hct at gmx dot de |
607
|
|
|
|
|
|
|
# commented on 2001/03/28 because of failing in ApacheSOAP |
608
|
|
|
|
|
|
|
# need to find out more about it |
609
|
|
|
|
|
|
|
# -> attr({'xmlns' => ''}) |
610
|
|
|
|
|
|
|
->value( |
611
|
|
|
|
|
|
|
\SOAP::Data->set_value( |
612
|
|
|
|
|
|
|
SOAP::Data->name( |
613
|
|
|
|
|
|
|
faultcode => SOAP::Utils::qualify( |
614
|
|
|
|
|
|
|
$self->envprefix => $parameters[0] |
615
|
|
|
|
|
|
|
) |
616
|
|
|
|
|
|
|
)->type(""), |
617
|
|
|
|
|
|
|
SOAP::Data->name( |
618
|
|
|
|
|
|
|
faultstring => SOAP::Utils::encode_data( $parameters[1] ) |
619
|
|
|
|
|
|
|
)->type(""), |
620
|
|
|
|
|
|
|
defined( $parameters[2] ) |
621
|
|
|
|
|
|
|
? SOAP::Data->name( |
622
|
|
|
|
|
|
|
detail => do { |
623
|
|
|
|
|
|
|
my $detail = $parameters[2]; |
624
|
|
|
|
|
|
|
ref $detail ? \$detail : $detail; |
625
|
|
|
|
|
|
|
} |
626
|
|
|
|
|
|
|
) |
627
|
|
|
|
|
|
|
: (), |
628
|
|
|
|
|
|
|
defined( $parameters[3] ) |
629
|
|
|
|
|
|
|
? SOAP::Data->name( faultactor => $parameters[3] )->type("") |
630
|
|
|
|
|
|
|
: (), |
631
|
|
|
|
|
|
|
) |
632
|
|
|
|
|
|
|
); |
633
|
|
|
|
|
|
|
} elsif ( $type eq 'freeform' ) { |
634
|
|
|
|
|
|
|
SOAP::Trace::freeform(@parameters); |
635
|
|
|
|
|
|
|
$body = SOAP::Data->set_value(@parameters); |
636
|
|
|
|
|
|
|
} elsif ( !defined($type) ) { |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
# This occurs when the Body is intended to be null. When no method has been |
639
|
|
|
|
|
|
|
# passed in of any kind. |
640
|
|
|
|
|
|
|
} else { |
641
|
|
|
|
|
|
|
die "Wrong type of envelope ($type) for SOAP call\n"; |
642
|
|
|
|
|
|
|
} |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
$self->seen( {} ); # reinitialize multiref table |
645
|
|
|
|
|
|
|
# Build the envelope |
646
|
|
|
|
|
|
|
# Right now it is possible for $body to be a SOAP::Data element that has not |
647
|
|
|
|
|
|
|
# XML escaped any values. How do you remedy this? |
648
|
|
|
|
|
|
|
my ($encoded) = $self->encode_object( |
649
|
|
|
|
|
|
|
SOAP::Data->name( |
650
|
|
|
|
|
|
|
SOAP::Utils::qualify( $self->envprefix => 'Envelope' ) => |
651
|
|
|
|
|
|
|
\SOAP::Data->value( |
652
|
|
|
|
|
|
|
( |
653
|
|
|
|
|
|
|
$header ? SOAP::Data->name( |
654
|
|
|
|
|
|
|
SOAP::Utils::qualify( $self->envprefix => 'Header' ) => |
655
|
|
|
|
|
|
|
\$header |
656
|
|
|
|
|
|
|
) : () |
657
|
|
|
|
|
|
|
), |
658
|
|
|
|
|
|
|
( |
659
|
|
|
|
|
|
|
$body |
660
|
|
|
|
|
|
|
? SOAP::Data->name( |
661
|
|
|
|
|
|
|
SOAP::Utils::qualify( $self->envprefix => 'Body' ) => |
662
|
|
|
|
|
|
|
\$body |
663
|
|
|
|
|
|
|
)->attr( { 'wsu:Id' => $WSRF::WSS::ID{myBody} } ) |
664
|
|
|
|
|
|
|
: SOAP::Data->name( |
665
|
|
|
|
|
|
|
SOAP::Utils::qualify( $self->envprefix => 'Body' ) |
666
|
|
|
|
|
|
|
)->attr( { 'wsu:Id' => $WSRF::WSS::ID{myBody} } ) |
667
|
|
|
|
|
|
|
), |
668
|
|
|
|
|
|
|
) |
669
|
|
|
|
|
|
|
)->attr( $self->attr ) |
670
|
|
|
|
|
|
|
); |
671
|
|
|
|
|
|
|
$self->signature( $parameters->signature ) if ref $parameters; |
672
|
|
|
|
|
|
|
|
673
|
|
|
|
|
|
|
# IMHO multirefs should be encoded after Body, but only some |
674
|
|
|
|
|
|
|
# toolkits understand this encoding, so we'll keep them for now (04/15/2001) |
675
|
|
|
|
|
|
|
# as the last element inside the Body |
676
|
|
|
|
|
|
|
# v -------------- subelements of Envelope |
677
|
|
|
|
|
|
|
# vv -------- last of them (Body) |
678
|
|
|
|
|
|
|
# v --- subelements |
679
|
|
|
|
|
|
|
push( @{ $encoded->[2]->[-1]->[2] }, $self->encode_multirefs ) |
680
|
|
|
|
|
|
|
if ref $encoded->[2]->[-1]->[2]; |
681
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
# Sometimes SOAP::Serializer is invoked statically when there is no context. |
683
|
|
|
|
|
|
|
# So first check to see if a context exists. |
684
|
|
|
|
|
|
|
# TODO - a context needs to be initialized by a constructor? |
685
|
|
|
|
|
|
|
if ( $self->context && $self->context->packager->parts ) { |
686
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
# TODO - this needs to be called! Calling it though wraps the payload twice! |
688
|
|
|
|
|
|
|
# return $self->context->packager->package($self->xmlize($encoded)); |
689
|
|
|
|
|
|
|
} |
690
|
|
|
|
|
|
|
return $self->xmlize($encoded); |
691
|
|
|
|
|
|
|
} |
692
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
# This function is called whenever a SOAP message is created using the |
694
|
|
|
|
|
|
|
# WSRF::Serializer. First it calls std_envelope to create the SOAP message, |
695
|
|
|
|
|
|
|
# then it takes this message and signs the bits of the message that should |
696
|
|
|
|
|
|
|
# be signed and adds the extra signing information into the message |
697
|
|
|
|
|
|
|
sub envelope { |
698
|
|
|
|
|
|
|
my $self = shift @_; |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
my ($dummy, $method, $params,$orig_header) = @_; |
701
|
|
|
|
|
|
|
#create an envelope - this returns raw XML |
702
|
|
|
|
|
|
|
my $envelope = $self->std_envelope(@_); |
703
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
#if the user has defined these env then he wants the envlope signed - |
705
|
|
|
|
|
|
|
#we take the envelope in the above step and do the necessary |
706
|
|
|
|
|
|
|
if ( defined( $ENV{WSS_SIGN} ) ) { |
707
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
#call the function to sign the envlope - returns the Header and Body |
709
|
|
|
|
|
|
|
#as raw XML |
710
|
|
|
|
|
|
|
my ( $header, $Body ) = WSRF::WSS::sign($envelope); |
711
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
#returns the body and header as XMl - the header does not have its top |
713
|
|
|
|
|
|
|
#and tail ie. the and are missing so we |
714
|
|
|
|
|
|
|
#add them |
715
|
|
|
|
|
|
|
my ($encoded) = $self->encode_object( |
716
|
|
|
|
|
|
|
SOAP::Data->name( |
717
|
|
|
|
|
|
|
SOAP::Utils::qualify( $self->envprefix => 'Envelope' ) => |
718
|
|
|
|
|
|
|
\SOAP::Data->value( |
719
|
|
|
|
|
|
|
SOAP::Data->name( |
720
|
|
|
|
|
|
|
SOAP::Utils::qualify( $self->envprefix => 'Header' ) => |
721
|
|
|
|
|
|
|
($orig_header ? |
722
|
|
|
|
|
|
|
\SOAP::Data->value( $orig_header, SOAP::Data->value($header)->type('xml') ) |
723
|
|
|
|
|
|
|
: |
724
|
|
|
|
|
|
|
\SOAP::Data->value($header)->type('xml') |
725
|
|
|
|
|
|
|
) |
726
|
|
|
|
|
|
|
), |
727
|
|
|
|
|
|
|
SOAP::Data->value($Body)->type('xml') |
728
|
|
|
|
|
|
|
) |
729
|
|
|
|
|
|
|
)->attr( $self->attr ) |
730
|
|
|
|
|
|
|
); |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
#$encoded is a SOAP::data - we convert it to XML |
733
|
|
|
|
|
|
|
$envelope = $self->xmlize($encoded); |
734
|
|
|
|
|
|
|
} |
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
return $envelope; |
737
|
|
|
|
|
|
|
} |
738
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
#=============================================================================== |
740
|
|
|
|
|
|
|
# Take a SOAP::Data object and serialise it - if we are given a SOAP::SOM or |
741
|
|
|
|
|
|
|
# SOAP::Data object and we want to get simple XML without all the SOAP stuff |
742
|
|
|
|
|
|
|
# added we use this class. Useful if the user wants to use DOM instead of |
743
|
|
|
|
|
|
|
# SOM to handle the object. |
744
|
|
|
|
|
|
|
# |
745
|
|
|
|
|
|
|
# This is useful if we have a SOAP::Data or SOAP::SOM object which we want to |
746
|
|
|
|
|
|
|
# convert to XML (e.g. to write to a file) without all the SOAP crap. |
747
|
|
|
|
|
|
|
# Other Perl packages will do this for you (convert a Perl object to XML) |
748
|
|
|
|
|
|
|
# but I want to reuse the SOAP::Lite stuff. |
749
|
|
|
|
|
|
|
# |
750
|
|
|
|
|
|
|
package WSRF::SimpleSerializer; |
751
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
=pod |
753
|
|
|
|
|
|
|
|
754
|
|
|
|
|
|
|
=head1 WSRF::SimpleSerializer |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
Overrides SOAP::Serializer. This is helper class that is based in SOAP::Serializer, |
757
|
|
|
|
|
|
|
it will serialize a SOAP::Data object into XML but without adding the SOAP namespaces |
758
|
|
|
|
|
|
|
etc. It is useful if you want to extra some simple XML from a SOM object, retrieve |
759
|
|
|
|
|
|
|
a SOAP::Data object from the SOM then serialize it to simple XML. |
760
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
my $serializer = WSRF::SimpleSerializer->new(); |
762
|
|
|
|
|
|
|
my $xml = $seriaizer->serialize( $som->dataof('/Envelope/Body/[1]') ); |
763
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
=head2 METHODS |
765
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
All methods are the same as SOAP::Serializer except "serialize". |
767
|
|
|
|
|
|
|
|
768
|
|
|
|
|
|
|
=over |
769
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
=item serialize |
771
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
This method from SOAP::Serializer is overridden so that it does not add the SOAP namepaces |
773
|
|
|
|
|
|
|
to the XML or set the types of the elements in the XML. |
774
|
|
|
|
|
|
|
|
775
|
|
|
|
|
|
|
sub serialize { |
776
|
|
|
|
|
|
|
my $self = shift @_; |
777
|
|
|
|
|
|
|
$self->autotype(0); |
778
|
|
|
|
|
|
|
$self->namespaces({}); |
779
|
|
|
|
|
|
|
$self->encoding(undef); |
780
|
|
|
|
|
|
|
$self->SUPER::serialize(@_); |
781
|
|
|
|
|
|
|
} |
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
=back |
784
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
=cut |
786
|
|
|
|
|
|
|
|
787
|
|
|
|
|
|
|
use strict; |
788
|
|
|
|
|
|
|
use vars qw(@ISA); |
789
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
@ISA = qw(SOAP::Serializer); # derived from the SOAP::Serializer |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
sub typecast { return; } |
793
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
#we override the serialize funtion, switching of lots of stuff |
795
|
|
|
|
|
|
|
sub serialize { |
796
|
|
|
|
|
|
|
my $self = shift @_; |
797
|
|
|
|
|
|
|
$self->autotype(0); |
798
|
|
|
|
|
|
|
$self->namespaces( {} ); |
799
|
|
|
|
|
|
|
$self->encoding(undef); |
800
|
|
|
|
|
|
|
$self->SUPER::serialize(@_); |
801
|
|
|
|
|
|
|
} |
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
#=============================================================================== |
804
|
|
|
|
|
|
|
# The Container that handles all the connections for us. |
805
|
|
|
|
|
|
|
# |
806
|
|
|
|
|
|
|
# All incoming messages arrive at the handle function - |
807
|
|
|
|
|
|
|
# in previous versions of WSRF::Lite function that was |
808
|
|
|
|
|
|
|
# way too big. Now we have a hash which allows use to |
809
|
|
|
|
|
|
|
# map messages to functions depending on the destination |
810
|
|
|
|
|
|
|
# URI. This makes it easy to add handlers for messages. |
811
|
|
|
|
|
|
|
# |
812
|
|
|
|
|
|
|
# BUG - should be Object Orientated |
813
|
|
|
|
|
|
|
# |
814
|
|
|
|
|
|
|
package WSRF::Container; |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
=pod |
817
|
|
|
|
|
|
|
|
818
|
|
|
|
|
|
|
=head1 WSRF::Container |
819
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
WSRF::Container handles incoming messages and dispatchs them to the appropriate |
821
|
|
|
|
|
|
|
WS-Resource. |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
=head2 METHODS |
824
|
|
|
|
|
|
|
|
825
|
|
|
|
|
|
|
=over |
826
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
=item handle |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
Takes a HTTP Request object and dispatchs it to the appropriate WS-Resource, |
830
|
|
|
|
|
|
|
handle returns a HTTP Response object from the WS-Resource which should be |
831
|
|
|
|
|
|
|
returned to the client. |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
=back |
834
|
|
|
|
|
|
|
|
835
|
|
|
|
|
|
|
=cut |
836
|
|
|
|
|
|
|
|
837
|
|
|
|
|
|
|
use IO::Socket; |
838
|
|
|
|
|
|
|
use HTTP::Daemon; |
839
|
|
|
|
|
|
|
use HTTP::Status; |
840
|
|
|
|
|
|
|
use HTTP::Response; |
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
# This hash maps incoming messages to functions - the mapping is done |
843
|
|
|
|
|
|
|
# using the RequestURI in the HTTP Header. It should be very easy to |
844
|
|
|
|
|
|
|
# add a custom handler! |
845
|
|
|
|
|
|
|
# The key in this hash is used in a regular expression - it is matched |
846
|
|
|
|
|
|
|
# to the start of the RequestURI - eg |
847
|
|
|
|
|
|
|
# http://vermont.mvc.mcc.ac.uk/WSRF/foobar -> WSRF |
848
|
|
|
|
|
|
|
# (/WSRF/foobar is the RequestURI) |
849
|
|
|
|
|
|
|
%WSRF::Container::HandlerMap = ( |
850
|
|
|
|
|
|
|
'WSRF' => \&WSRF::Container::WSRFHandler, |
851
|
|
|
|
|
|
|
'Session' => \&WSRF::Container::SessionHandler, |
852
|
|
|
|
|
|
|
'MultiSession' => \&WSRF::Container::MultiSessionHandler |
853
|
|
|
|
|
|
|
); |
854
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
# All messages should pass through this handle function - $r is a |
856
|
|
|
|
|
|
|
# HTTP::Request Object |
857
|
|
|
|
|
|
|
sub handle { |
858
|
|
|
|
|
|
|
my ( $r, $socket ) = @_; |
859
|
|
|
|
|
|
|
|
860
|
|
|
|
|
|
|
#need to record if this process has an open socket with the world |
861
|
|
|
|
|
|
|
#- if we fork we might need to close it |
862
|
|
|
|
|
|
|
$WSRF::Constants::ExternSocket = WSRF::SocketHolder->instance($socket); |
863
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
if ( !$r ) { |
865
|
|
|
|
|
|
|
print STDERR "$$ WSRF::Container HTTP::Request not defined!"; |
866
|
|
|
|
|
|
|
return; |
867
|
|
|
|
|
|
|
} |
868
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
my $Path = $r->uri->path; |
870
|
|
|
|
|
|
|
if ( $Path =~ m/\.{2,}/og ) { |
871
|
|
|
|
|
|
|
print STDERR |
872
|
|
|
|
|
|
|
"$$ WSRF::Container Path $Path contains unacceptable charactors.\n"; |
873
|
|
|
|
|
|
|
my $fail = new HTTP::Response(RC_NOT_FOUND); |
874
|
|
|
|
|
|
|
$fail->header( 'Content-Type' => 'text/xml' ); |
875
|
|
|
|
|
|
|
$fail->content("Path $Path contains unacceptable charactors.\n"); |
876
|
|
|
|
|
|
|
return $fail; |
877
|
|
|
|
|
|
|
} |
878
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
my ($response); |
880
|
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
#walk through the hash until we find a handler for this function - we put |
882
|
|
|
|
|
|
|
#the key between / and / and do a reg expression match |
883
|
|
|
|
|
|
|
my $found = undef; |
884
|
|
|
|
|
|
|
LINE: foreach my $key ( keys %WSRF::Container::HandlerMap ) { |
885
|
|
|
|
|
|
|
if ( $Path =~ m/^\/$key\// ) { |
886
|
|
|
|
|
|
|
$found = "TRUE"; |
887
|
|
|
|
|
|
|
print STDERR "$$ WSRF::Container Using $key Handler\n"; |
888
|
|
|
|
|
|
|
$response = $WSRF::Container::HandlerMap{$key}->($r); |
889
|
|
|
|
|
|
|
last LINE; |
890
|
|
|
|
|
|
|
} |
891
|
|
|
|
|
|
|
} |
892
|
|
|
|
|
|
|
|
893
|
|
|
|
|
|
|
#no handler found - return a 404 HTTP error message |
894
|
|
|
|
|
|
|
if ( !$found ) { |
895
|
|
|
|
|
|
|
$response = HTTP::Response->new(404); |
896
|
|
|
|
|
|
|
} |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
return $response; |
899
|
|
|
|
|
|
|
} |
900
|
|
|
|
|
|
|
|
901
|
|
|
|
|
|
|
# handles messages with URI http://blah.com/WSRF/ |
902
|
|
|
|
|
|
|
# this maps to WS-Resources that use a process to manage the |
903
|
|
|
|
|
|
|
# state of a WS-Resource, one process per WS-Resource. This |
904
|
|
|
|
|
|
|
# functions sends the message down a UNIX socket to the process |
905
|
|
|
|
|
|
|
sub WSRFHandler { |
906
|
|
|
|
|
|
|
my $request = shift @_; |
907
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
#Only Handle GET and POST |
909
|
|
|
|
|
|
|
return HTTP::Response->new(RC_FORBIDDEN) |
910
|
|
|
|
|
|
|
if ( $request->method ne 'POST' |
911
|
|
|
|
|
|
|
&& $request->method ne 'GET' |
912
|
|
|
|
|
|
|
&& $request->method ne 'DELETE' |
913
|
|
|
|
|
|
|
&& $request->method ne 'PUT' ); |
914
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
print STDERR "$$ WSRFHandler called\n"; |
916
|
|
|
|
|
|
|
my $Path = $request->uri->path; |
917
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
#strip extra '/' at start of URL |
919
|
|
|
|
|
|
|
$Path =~ s/^\/+//o; |
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
#remeber the Path - we will put this in our responses so clients |
922
|
|
|
|
|
|
|
#will know who sent them the message - part of WS-Addressing |
923
|
|
|
|
|
|
|
$ENV{FROM} = $ENV{URL} . $Path; |
924
|
|
|
|
|
|
|
|
925
|
|
|
|
|
|
|
#split up Path part of URL - we multiplex on the first part (the base) |
926
|
|
|
|
|
|
|
#the module name is the last part |
927
|
|
|
|
|
|
|
my @PathArray = split( /\//, $Path ); |
928
|
|
|
|
|
|
|
my $ID = pop @PathArray; |
929
|
|
|
|
|
|
|
my $base = $PathArray[0]; |
930
|
|
|
|
|
|
|
my $ModuleName = pop @PathArray; |
931
|
|
|
|
|
|
|
print "$$ ModuleName= $ModuleName\n"; |
932
|
|
|
|
|
|
|
my $Directory = join '/', @PathArray; |
933
|
|
|
|
|
|
|
|
934
|
|
|
|
|
|
|
#this is the absolute path now |
935
|
|
|
|
|
|
|
$Directory = $ENV{WSRF_MODULES} . "/" . $Directory; |
936
|
|
|
|
|
|
|
print STDERR "Directory= $Directory\n"; |
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
$Path = $ENV{WSRF_MODULES} . "/" . $Path; |
939
|
|
|
|
|
|
|
|
940
|
|
|
|
|
|
|
#check the ID is safe - we do not accept dots, |
941
|
|
|
|
|
|
|
#all paths will be relative to $ENV{WRF_MODULES} |
942
|
|
|
|
|
|
|
#only allow alphanumeric, underscore and hyphen |
943
|
|
|
|
|
|
|
if ( $ID !~ m/^([-\w]+)$/ && $ID !~ m/^$ModuleName\.(xsl|js|css|svg)$/ ) { |
944
|
|
|
|
|
|
|
print STDERR "$$ Bad ID $ID\n"; |
945
|
|
|
|
|
|
|
my $fail = new HTTP::Response(RC_BAD_REQUEST); |
946
|
|
|
|
|
|
|
$fail->header( 'Content-Type' => 'text/xml' ); |
947
|
|
|
|
|
|
|
$fail->content( |
948
|
|
|
|
|
|
|
SOAP::Serializer->fault( |
949
|
|
|
|
|
|
|
'Bad WS-Resource Identifier', |
950
|
|
|
|
|
|
|
"WS-Resource identifier contains bad charactors" |
951
|
|
|
|
|
|
|
) |
952
|
|
|
|
|
|
|
); |
953
|
|
|
|
|
|
|
|
954
|
|
|
|
|
|
|
return $fail; |
955
|
|
|
|
|
|
|
} |
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
my ($PUT); |
958
|
|
|
|
|
|
|
if ( $request->method eq 'PUT' ) { |
959
|
|
|
|
|
|
|
$PUT = 1; |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
my $To = $ENV{URL}; |
962
|
|
|
|
|
|
|
chop $To; |
963
|
|
|
|
|
|
|
$To .= $request->uri; |
964
|
|
|
|
|
|
|
my $header = |
965
|
|
|
|
|
|
|
SOAP::Header->value( "" . $To . "" )->type('xml'); |
966
|
|
|
|
|
|
|
my $xml = $request->content; |
967
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
print STDERR "$$ Attempt to PUT\n"; |
969
|
|
|
|
|
|
|
|
970
|
|
|
|
|
|
|
$xml =~ s/^<\?xml[\s\w\.\-].*\?>\n?//o; |
971
|
|
|
|
|
|
|
print STDERR "$$ >>>xml>>>\n$xml\n<<
|
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
my $data = |
974
|
|
|
|
|
|
|
SOAP::Data->name('PutResourcePropertyDocument')->prefix('wsrp') |
975
|
|
|
|
|
|
|
->attr( { 'xmlns:wsrp' => $WSRF::Constants::WSRP } ) |
976
|
|
|
|
|
|
|
->value( \SOAP::Data->value($xml)->type('xml') ); |
977
|
|
|
|
|
|
|
|
978
|
|
|
|
|
|
|
my $envelope = WSRF::WSRFSerializer->new()->freeform( $header, $data ); |
979
|
|
|
|
|
|
|
print "$$ >>>envelope>>>\n$envelope\n<<
|
980
|
|
|
|
|
|
|
$request = HTTP::Request->new(); |
981
|
|
|
|
|
|
|
$request->method('POST'); |
982
|
|
|
|
|
|
|
$request->header( "SOAPAction" => |
983
|
|
|
|
|
|
|
"$WSRF::Constants::WSRP/PutResourcePropertyDocument" ); |
984
|
|
|
|
|
|
|
$request->header( "Content-Length" => length $envelope ); |
985
|
|
|
|
|
|
|
$request->content($envelope); |
986
|
|
|
|
|
|
|
} |
987
|
|
|
|
|
|
|
|
988
|
|
|
|
|
|
|
print "$$ ID= $ID\n"; |
989
|
|
|
|
|
|
|
my ($GET); |
990
|
|
|
|
|
|
|
if ( $request->method eq 'GET' ) { |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
#does the client just want the WSDL/XSL/CSS for service |
993
|
|
|
|
|
|
|
if ( $request->uri->query eq 'WSDL' ) { |
994
|
|
|
|
|
|
|
my $resp = GetWSDL($request); |
995
|
|
|
|
|
|
|
return $resp; |
996
|
|
|
|
|
|
|
} elsif ( $ID =~ m/^$ModuleName\.(xsl|css|js|svg)$/ ) |
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
#looking for xsl or css or js |
999
|
|
|
|
|
|
|
{ |
1000
|
|
|
|
|
|
|
print "$$ Getting $ID file\n"; |
1001
|
|
|
|
|
|
|
my $resp = HTTP::Response->new(); |
1002
|
|
|
|
|
|
|
my $file = $Directory . "/" . $ID; |
1003
|
|
|
|
|
|
|
print "$$ File to open is $file\n"; |
1004
|
|
|
|
|
|
|
if ( !( -f $file ) || !( -r $file ) ) { |
1005
|
|
|
|
|
|
|
$resp->code(404); |
1006
|
|
|
|
|
|
|
return $resp; |
1007
|
|
|
|
|
|
|
} |
1008
|
|
|
|
|
|
|
open FILE, "< $file" or die "$$ Could not open $file"; |
1009
|
|
|
|
|
|
|
my $xsl = join "", ; |
1010
|
|
|
|
|
|
|
close FILE or die "Could not close $file file"; |
1011
|
|
|
|
|
|
|
$resp->header( 'Content-Type' => 'text/xml' ) |
1012
|
|
|
|
|
|
|
if ( $ID =~ m/\.xsl$/ ); |
1013
|
|
|
|
|
|
|
$resp->header( 'Content-Type' => 'text/css' ) |
1014
|
|
|
|
|
|
|
if ( $ID =~ m/\.css$/ ); |
1015
|
|
|
|
|
|
|
$resp->header( 'Content-Type' => 'text/javascript' ) |
1016
|
|
|
|
|
|
|
if ( $ID =~ m/\.js$/ ); |
1017
|
|
|
|
|
|
|
$resp->header( 'Content-Type' => 'text/xml' ) |
1018
|
|
|
|
|
|
|
if ( $ID =~ m/\.svg$/ ); |
1019
|
|
|
|
|
|
|
|
1020
|
|
|
|
|
|
|
$resp->content($xsl); |
1021
|
|
|
|
|
|
|
return $resp; |
1022
|
|
|
|
|
|
|
} |
1023
|
|
|
|
|
|
|
|
1024
|
|
|
|
|
|
|
#wants ResourceProperties |
1025
|
|
|
|
|
|
|
$GET = 1; |
1026
|
|
|
|
|
|
|
my $data = |
1027
|
|
|
|
|
|
|
SOAP::Data->name('GetResourcePropertyDocument')->prefix('wsrp') |
1028
|
|
|
|
|
|
|
->attr( { 'xmlns:wsrp' => $WSRF::Constants::WSRP } ); |
1029
|
|
|
|
|
|
|
my $To = $ENV{URL}; |
1030
|
|
|
|
|
|
|
chop $To; |
1031
|
|
|
|
|
|
|
$To .= $request->uri; |
1032
|
|
|
|
|
|
|
my $header = |
1033
|
|
|
|
|
|
|
SOAP::Header->value( "" . $To . "" )->type('xml'); |
1034
|
|
|
|
|
|
|
my $envelope = WSRF::WSRFSerializer->new()->freeform( $header, $data ); |
1035
|
|
|
|
|
|
|
$request = HTTP::Request->new(); |
1036
|
|
|
|
|
|
|
$request->method('POST'); |
1037
|
|
|
|
|
|
|
$request->header( "SOAPAction" => |
1038
|
|
|
|
|
|
|
"$WSRF::Constants::WSRP/GetResourcePropertyDocument" ); |
1039
|
|
|
|
|
|
|
$request->header( "Content-Length" => length $envelope ); |
1040
|
|
|
|
|
|
|
$request->content($envelope); |
1041
|
|
|
|
|
|
|
} |
1042
|
|
|
|
|
|
|
|
1043
|
|
|
|
|
|
|
if ( $request->method eq 'DELETE' ) { |
1044
|
|
|
|
|
|
|
my $data = |
1045
|
|
|
|
|
|
|
SOAP::Data->name('Destroy')->prefix('wsrl') |
1046
|
|
|
|
|
|
|
->attr( { 'xmlns:wsrl' => $WSRF::Constants::WSRL } ); |
1047
|
|
|
|
|
|
|
my $To = $ENV{URL}; |
1048
|
|
|
|
|
|
|
chop $To; |
1049
|
|
|
|
|
|
|
$To .= $request->uri; |
1050
|
|
|
|
|
|
|
my $header = |
1051
|
|
|
|
|
|
|
SOAP::Header->value( "" . $To . "" )->type('xml'); |
1052
|
|
|
|
|
|
|
my $envelope = WSRF::WSRFSerializer->new()->freeform( $header, $data ); |
1053
|
|
|
|
|
|
|
$request = HTTP::Request->new(); |
1054
|
|
|
|
|
|
|
$request->method('POST'); |
1055
|
|
|
|
|
|
|
$request->header( "SOAPAction" => "$WSRF::Constants::WSRL/Destroy" ); |
1056
|
|
|
|
|
|
|
$request->header( "Content-Length" => length $envelope ); |
1057
|
|
|
|
|
|
|
$request->content($envelope); |
1058
|
|
|
|
|
|
|
} |
1059
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
my $rend = $WSRF::Constants::SOCKETS_DIRECTORY . "/" . $ID; |
1061
|
|
|
|
|
|
|
|
1062
|
|
|
|
|
|
|
#check that the Socket exists for the requested Grid Service |
1063
|
|
|
|
|
|
|
if ( !-S $rend ) { |
1064
|
|
|
|
|
|
|
print STDERR "$$ UNIX Socket $rend does not exist\n"; |
1065
|
|
|
|
|
|
|
my $fail = new HTTP::Response(RC_NOT_FOUND); |
1066
|
|
|
|
|
|
|
$fail->header( 'Content-Type' => 'text/xml' ); |
1067
|
|
|
|
|
|
|
$fail->content( |
1068
|
|
|
|
|
|
|
SOAP::Serializer->fault( |
1069
|
|
|
|
|
|
|
'No such WS-Resource type', |
1070
|
|
|
|
|
|
|
"Check Endpoint of service" |
1071
|
|
|
|
|
|
|
) |
1072
|
|
|
|
|
|
|
); |
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
return $fail; |
1075
|
|
|
|
|
|
|
} |
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
print STDERR "$$ $Path Child $$ Starting Processing\n"; |
1078
|
|
|
|
|
|
|
print STDERR "$$ Client Rendezvous $rend\n"; |
1079
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
#open a socket to the GS |
1081
|
|
|
|
|
|
|
my $MyFH = IO::Socket::UNIX->new( |
1082
|
|
|
|
|
|
|
Peer => "$rend", |
1083
|
|
|
|
|
|
|
Type => SOCK_STREAM, |
1084
|
|
|
|
|
|
|
Timeout => 10 |
1085
|
|
|
|
|
|
|
) |
1086
|
|
|
|
|
|
|
or die SOAP::Fault->faultcode("Container Fault") |
1087
|
|
|
|
|
|
|
->faultstring("Container Failure - Socket problem $!"); |
1088
|
|
|
|
|
|
|
print STDERR "$$ Client Socket $MyFH\n"; |
1089
|
|
|
|
|
|
|
|
1090
|
|
|
|
|
|
|
#if using SSL add the extra information to the HTTP request |
1091
|
|
|
|
|
|
|
# we stick it into the HTTP Header |
1092
|
|
|
|
|
|
|
if ( defined( $ENV{SSL_CLIENT_DN} ) ) { |
1093
|
|
|
|
|
|
|
$request->header( 'Client-SSL-Cert-Subject' => "$ENV{SSL_CLIENT_DN}" ); |
1094
|
|
|
|
|
|
|
$request->header( |
1095
|
|
|
|
|
|
|
'Client-SSL-Cert-Issuer' => "$ENV{SSL_CLIENT_ISSUER}" ); |
1096
|
|
|
|
|
|
|
} |
1097
|
|
|
|
|
|
|
|
1098
|
|
|
|
|
|
|
#send down socket and wait for response |
1099
|
|
|
|
|
|
|
my $out = print $MyFH ( $request->as_string() ); |
1100
|
|
|
|
|
|
|
|
1101
|
|
|
|
|
|
|
if ( !defined($out) ) { print STDERR "$$ Could not write to $MyFH\n" } |
1102
|
|
|
|
|
|
|
|
1103
|
|
|
|
|
|
|
#read the response from the Socket and turn it into a |
1104
|
|
|
|
|
|
|
#HTTP::Response |
1105
|
|
|
|
|
|
|
my $resp = WSRF::Daemon::ResponseHandler($MyFH); |
1106
|
|
|
|
|
|
|
$MyFH->close; |
1107
|
|
|
|
|
|
|
print STDERR "$$ $Path Processing Finished\n"; |
1108
|
|
|
|
|
|
|
|
1109
|
|
|
|
|
|
|
# print STDERR "$$ >>>out>>>\n".$resp->content."\n<<
|
1110
|
|
|
|
|
|
|
|
1111
|
|
|
|
|
|
|
if ( $GET || $PUT ) #Original Request was a GET |
1112
|
|
|
|
|
|
|
{ |
1113
|
|
|
|
|
|
|
$resp = |
1114
|
|
|
|
|
|
|
WSRF::Container::getProperties( $resp, $Directory, $ModuleName ); |
1115
|
|
|
|
|
|
|
$resp->header( "Pragma" => "no-cache" ); |
1116
|
|
|
|
|
|
|
$resp->header( |
1117
|
|
|
|
|
|
|
"Cache-Control" => "no-cache, max-age=1, must-revalidate" ); |
1118
|
|
|
|
|
|
|
} |
1119
|
|
|
|
|
|
|
return $resp; |
1120
|
|
|
|
|
|
|
} |
1121
|
|
|
|
|
|
|
|
1122
|
|
|
|
|
|
|
# This function handles messages that have a URI like |
1123
|
|
|
|
|
|
|
# http://blah.com/Session/stuff |
1124
|
|
|
|
|
|
|
# Session WS-Resources store their state in a DB/filesystem etc... |
1125
|
|
|
|
|
|
|
# this function loads the function that loads the code to access |
1126
|
|
|
|
|
|
|
# the state and process the message |
1127
|
|
|
|
|
|
|
sub SessionHandler { |
1128
|
|
|
|
|
|
|
my $request = shift @_; |
1129
|
|
|
|
|
|
|
print STDERR "$$ SessionHandler called\n"; |
1130
|
|
|
|
|
|
|
|
1131
|
|
|
|
|
|
|
#Only Handle GET and POST |
1132
|
|
|
|
|
|
|
return HTTP::Response->new(RC_FORBIDDEN) |
1133
|
|
|
|
|
|
|
if ( $request->method ne 'POST' |
1134
|
|
|
|
|
|
|
&& $request->method ne 'GET' |
1135
|
|
|
|
|
|
|
&& $request->method ne 'DELETE' |
1136
|
|
|
|
|
|
|
&& $request->method ne 'PUT' ); |
1137
|
|
|
|
|
|
|
|
1138
|
|
|
|
|
|
|
my $Path = $request->uri->path; |
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
#strip extra '/' at start of URL |
1141
|
|
|
|
|
|
|
$Path =~ s/^\/+//o; |
1142
|
|
|
|
|
|
|
|
1143
|
|
|
|
|
|
|
#remeber the Path - we will put this in our responses so clients |
1144
|
|
|
|
|
|
|
#will know who sent them the message - part of WS-Addressing |
1145
|
|
|
|
|
|
|
$ENV{FROM} = $ENV{URL} . $Path; |
1146
|
|
|
|
|
|
|
|
1147
|
|
|
|
|
|
|
#split up Path part of URL - we multiplex on the first part (the base) |
1148
|
|
|
|
|
|
|
#the module name is the last part |
1149
|
|
|
|
|
|
|
my @PathArray = split( /\//, $Path ); |
1150
|
|
|
|
|
|
|
my $ID = pop @PathArray; |
1151
|
|
|
|
|
|
|
my ($module); |
1152
|
|
|
|
|
|
|
if ( $ID =~ /\d+-?d*/o |
1153
|
|
|
|
|
|
|
|| $ID =~ /^\w+\.(js|xsl|css|svg)$/ ) #a resource identifier |
1154
|
|
|
|
|
|
|
{ |
1155
|
|
|
|
|
|
|
$module = pop @PathArray; |
1156
|
|
|
|
|
|
|
} else { |
1157
|
|
|
|
|
|
|
$module = $ID; |
1158
|
|
|
|
|
|
|
} |
1159
|
|
|
|
|
|
|
$ENV{ID} = $ID; |
1160
|
|
|
|
|
|
|
|
1161
|
|
|
|
|
|
|
my $base = $PathArray[0]; |
1162
|
|
|
|
|
|
|
my $RelativeDirectory = join '/', @PathArray; |
1163
|
|
|
|
|
|
|
|
1164
|
|
|
|
|
|
|
#this is the absolute path now |
1165
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
my $Directory = $ENV{WSRF_MODULES} . "/" . $RelativeDirectory; |
1167
|
|
|
|
|
|
|
print STDERR "$$ Directory to modules $Directory\n"; |
1168
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
my $tmpPath = $Directory . '/' . $module . ".pm"; |
1170
|
|
|
|
|
|
|
print STDERR "$$ Path to module $tmpPath\n"; |
1171
|
|
|
|
|
|
|
if ( !-f $tmpPath ) { |
1172
|
|
|
|
|
|
|
print STDERR "$$ ERROR $tmpPath no such file\n"; |
1173
|
|
|
|
|
|
|
my $fail = new HTTP::Response(RC_OK); |
1174
|
|
|
|
|
|
|
$fail->header( 'Content-Type' => 'text/xml' ); |
1175
|
|
|
|
|
|
|
|
1176
|
|
|
|
|
|
|
#$fail->content("GS::$Path No Such service\n"); |
1177
|
|
|
|
|
|
|
$fail->content( |
1178
|
|
|
|
|
|
|
SOAP::Serializer->fault( |
1179
|
|
|
|
|
|
|
'No Service', "Check Endpoint of Service" |
1180
|
|
|
|
|
|
|
) |
1181
|
|
|
|
|
|
|
); |
1182
|
|
|
|
|
|
|
return $fail; |
1183
|
|
|
|
|
|
|
} |
1184
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
my ($PUT); |
1186
|
|
|
|
|
|
|
if ( $request->method eq 'PUT' ) { |
1187
|
|
|
|
|
|
|
$PUT = 1; |
1188
|
|
|
|
|
|
|
|
1189
|
|
|
|
|
|
|
my $To = $ENV{URL}; |
1190
|
|
|
|
|
|
|
chop $To; |
1191
|
|
|
|
|
|
|
$To .= $request->uri; |
1192
|
|
|
|
|
|
|
my $header = |
1193
|
|
|
|
|
|
|
SOAP::Header->value( "" . $To . "" )->type('xml'); |
1194
|
|
|
|
|
|
|
my $xml = $request->content; |
1195
|
|
|
|
|
|
|
|
1196
|
|
|
|
|
|
|
print STDERR "$$ Attempt to PUT\n"; |
1197
|
|
|
|
|
|
|
|
1198
|
|
|
|
|
|
|
$xml =~ s/^<\?xml[\s\w\.\-].*\?>\n?//o; |
1199
|
|
|
|
|
|
|
print STDERR "$$ >>>xml>>>\n$xml\n<<
|
1200
|
|
|
|
|
|
|
|
1201
|
|
|
|
|
|
|
my $data = |
1202
|
|
|
|
|
|
|
SOAP::Data->name('PutResourcePropertyDocument')->prefix('wsrp') |
1203
|
|
|
|
|
|
|
->attr( { 'xmlns:wsrp' => $WSRF::Constants::WSRP } ) |
1204
|
|
|
|
|
|
|
->value( \SOAP::Data->value($xml)->type('xml') ); |
1205
|
|
|
|
|
|
|
|
1206
|
|
|
|
|
|
|
my $envelope = WSRF::WSRFSerializer->new()->freeform( $header, $data ); |
1207
|
|
|
|
|
|
|
print "$$ >>>envelope>>>\n$envelope\n<<
|
1208
|
|
|
|
|
|
|
$request = HTTP::Request->new(); |
1209
|
|
|
|
|
|
|
$request->method('POST'); |
1210
|
|
|
|
|
|
|
$request->header( "SOAPAction" => |
1211
|
|
|
|
|
|
|
"$WSRF::Constants::WSRP/PutResourcePropertyDocument" ); |
1212
|
|
|
|
|
|
|
$request->header( "Content-Length" => length $envelope ); |
1213
|
|
|
|
|
|
|
$request->content($envelope); |
1214
|
|
|
|
|
|
|
} |
1215
|
|
|
|
|
|
|
|
1216
|
|
|
|
|
|
|
my ($GET); |
1217
|
|
|
|
|
|
|
if ( $request->method eq 'GET' ) { |
1218
|
|
|
|
|
|
|
|
1219
|
|
|
|
|
|
|
#does the client just want the WSDL for service |
1220
|
|
|
|
|
|
|
if ( $request->uri->query eq 'WSDL' ) { |
1221
|
|
|
|
|
|
|
my $resp = GetWSDL($request); |
1222
|
|
|
|
|
|
|
return $resp; |
1223
|
|
|
|
|
|
|
} elsif ( $ID =~ m/^$module\.(xsl|css|js|svg)$/ ) |
1224
|
|
|
|
|
|
|
|
1225
|
|
|
|
|
|
|
#looking for xsl or css or js |
1226
|
|
|
|
|
|
|
{ |
1227
|
|
|
|
|
|
|
print "$$ Getting $ID file\n"; |
1228
|
|
|
|
|
|
|
my $resp = HTTP::Response->new(); |
1229
|
|
|
|
|
|
|
my $file = $Directory . "/" . $ID; |
1230
|
|
|
|
|
|
|
print "$$ File to open is $file\n"; |
1231
|
|
|
|
|
|
|
if ( !( -f $file ) || !( -r $file ) ) { |
1232
|
|
|
|
|
|
|
$resp->code(404); |
1233
|
|
|
|
|
|
|
return $resp; |
1234
|
|
|
|
|
|
|
} |
1235
|
|
|
|
|
|
|
print "$$ File to open is $file\n"; |
1236
|
|
|
|
|
|
|
open FILE, "< $file" or die "$$ Could not open $file"; |
1237
|
|
|
|
|
|
|
my $xsl = join "", ; |
1238
|
|
|
|
|
|
|
close FILE or die "Could not close WSDL file"; |
1239
|
|
|
|
|
|
|
$resp->header( 'Content-Type' => 'text/xml' ) |
1240
|
|
|
|
|
|
|
if ( $ID =~ m/\.xsl$/ ); |
1241
|
|
|
|
|
|
|
$resp->header( 'Content-Type' => 'text/css' ) |
1242
|
|
|
|
|
|
|
if ( $ID =~ m/\.css$/ ); |
1243
|
|
|
|
|
|
|
$resp->header( 'Content-Type' => 'text/javascript' ) |
1244
|
|
|
|
|
|
|
if ( $ID =~ m/\.js$/ ); |
1245
|
|
|
|
|
|
|
$resp->header( 'Content-Type' => 'text/xml' ) |
1246
|
|
|
|
|
|
|
if ( $ID =~ m/\.svg$/ ); |
1247
|
|
|
|
|
|
|
|
1248
|
|
|
|
|
|
|
$resp->content($xsl); |
1249
|
|
|
|
|
|
|
return $resp; |
1250
|
|
|
|
|
|
|
} |
1251
|
|
|
|
|
|
|
|
1252
|
|
|
|
|
|
|
$GET = 1; |
1253
|
|
|
|
|
|
|
my $data = |
1254
|
|
|
|
|
|
|
SOAP::Data->name('GetResourcePropertyDocument')->prefix('wsrp') |
1255
|
|
|
|
|
|
|
->attr( { 'xmlns:wsrp' => $WSRF::Constants::WSRP } ); |
1256
|
|
|
|
|
|
|
my $To = $ENV{URL}; |
1257
|
|
|
|
|
|
|
chop $To; |
1258
|
|
|
|
|
|
|
$To .= $request->uri; |
1259
|
|
|
|
|
|
|
my $header = |
1260
|
|
|
|
|
|
|
SOAP::Header->value( "" . $To . "" )->type('xml'); |
1261
|
|
|
|
|
|
|
my $envelope = WSRF::WSRFSerializer->new()->freeform( $header, $data ); |
1262
|
|
|
|
|
|
|
$request = HTTP::Request->new(); |
1263
|
|
|
|
|
|
|
$request->method('POST'); |
1264
|
|
|
|
|
|
|
$request->header( "SOAPAction" => |
1265
|
|
|
|
|
|
|
"$WSRF::Constants::WSRP/GetResourcePropertyDocument" ); |
1266
|
|
|
|
|
|
|
$request->header( "Content-Length" => length $envelope ); |
1267
|
|
|
|
|
|
|
$request->content($envelope); |
1268
|
|
|
|
|
|
|
} |
1269
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
if ( $request->method eq 'DELETE' ) { |
1271
|
|
|
|
|
|
|
my $data = |
1272
|
|
|
|
|
|
|
SOAP::Data->name('Destroy')->prefix('wsrl') |
1273
|
|
|
|
|
|
|
->attr( { 'xmlns:wsrl' => $WSRF::Constants::WSRL } ); |
1274
|
|
|
|
|
|
|
my $To = $ENV{URL}; |
1275
|
|
|
|
|
|
|
chop $To; |
1276
|
|
|
|
|
|
|
$To .= $request->uri; |
1277
|
|
|
|
|
|
|
my $header = |
1278
|
|
|
|
|
|
|
SOAP::Header->value( "" . $To . "" )->type('xml'); |
1279
|
|
|
|
|
|
|
my $envelope = WSRF::WSRFSerializer->new()->freeform( $header, $data ); |
1280
|
|
|
|
|
|
|
$request = HTTP::Request->new(); |
1281
|
|
|
|
|
|
|
$request->method('POST'); |
1282
|
|
|
|
|
|
|
$request->header( "SOAPAction" => "$WSRF::Constants::WSRL/Destroy" ); |
1283
|
|
|
|
|
|
|
$request->header( "Content-Length" => length $envelope ); |
1284
|
|
|
|
|
|
|
$request->content($envelope); |
1285
|
|
|
|
|
|
|
} |
1286
|
|
|
|
|
|
|
|
1287
|
|
|
|
|
|
|
print STDERR "$$ Dispatch path $Directory\n"; |
1288
|
|
|
|
|
|
|
my %namespacemap = ( |
1289
|
|
|
|
|
|
|
$WSRF::Constants::WSRL => "$module", |
1290
|
|
|
|
|
|
|
$WSRF::Constants::WSRP => "$module", |
1291
|
|
|
|
|
|
|
$WSRF::Constants::WSSG => "$module" |
1292
|
|
|
|
|
|
|
); |
1293
|
|
|
|
|
|
|
%namespacemap = ( %namespacemap, %WSRF::Constants::ModuleNamespaceMap ); |
1294
|
|
|
|
|
|
|
|
1295
|
|
|
|
|
|
|
#this loads the module to handle this function, the module |
1296
|
|
|
|
|
|
|
#will retrieve the state for the WS-Resource from a DB or |
1297
|
|
|
|
|
|
|
#some other stable storage, process the message and return the |
1298
|
|
|
|
|
|
|
#state to the stable storage |
1299
|
|
|
|
|
|
|
my $resp = |
1300
|
|
|
|
|
|
|
WSRF::Session->dispatch_to($Directory)->dispatch_with( \%namespacemap ) |
1301
|
|
|
|
|
|
|
->serializer( WSRF::WSRFSerializer->new ) |
1302
|
|
|
|
|
|
|
->deserializer( WSRF::Deserializer->new )->handle($request); |
1303
|
|
|
|
|
|
|
|
1304
|
|
|
|
|
|
|
print STDERR "$$ >>>out>>>\n" . $resp->content . "\n<<
|
1305
|
|
|
|
|
|
|
if ( $GET || $PUT ) #Original Request was a GET |
1306
|
|
|
|
|
|
|
{ |
1307
|
|
|
|
|
|
|
$resp = WSRF::Container::getProperties( $resp, $Directory, $module ); |
1308
|
|
|
|
|
|
|
} |
1309
|
|
|
|
|
|
|
|
1310
|
|
|
|
|
|
|
return $resp; |
1311
|
|
|
|
|
|
|
} |
1312
|
|
|
|
|
|
|
|
1313
|
|
|
|
|
|
|
sub getProperties { |
1314
|
|
|
|
|
|
|
my $resp = shift @_; |
1315
|
|
|
|
|
|
|
my $Dir = shift @_; |
1316
|
|
|
|
|
|
|
my $Module = shift @_; |
1317
|
|
|
|
|
|
|
my $xml = $resp->content; |
1318
|
|
|
|
|
|
|
eval { require XML::LibXML }; |
1319
|
|
|
|
|
|
|
if ( !$@ ) #we have XML::LibXML, so we can strip the SOAP stuff |
1320
|
|
|
|
|
|
|
{ |
1321
|
|
|
|
|
|
|
#my $xpath = '
1322
|
|
|
|
|
|
|
# . $WSRF::Constants::WSRP |
1323
|
|
|
|
|
|
|
# . '">(//. | //@* | //namespace::*)[ancestor-or-self::wsrp:ResourceProperties]'; |
1324
|
|
|
|
|
|
|
my $xpath = '(//. | //@* | //namespace::*)[ancestor-or-self::wsrp:ResourceProperties]'; |
1325
|
|
|
|
|
|
|
|
1326
|
|
|
|
|
|
|
my $canon = '' . "\n"; |
1327
|
|
|
|
|
|
|
$canon = $canon |
1328
|
|
|
|
|
|
|
. '
|
1329
|
|
|
|
|
|
|
. $Module |
1330
|
|
|
|
|
|
|
. '.xsl"?>' . "\n" |
1331
|
|
|
|
|
|
|
if ( -f $Dir . "/$Module.xsl" && -r $Dir . "/$Module.xsl" ); |
1332
|
|
|
|
|
|
|
my $parser = XML::LibXML->new(); |
1333
|
|
|
|
|
|
|
my $doc = $parser->parse_string($xml); |
1334
|
|
|
|
|
|
|
$canon .= $doc->toStringEC14N( 0, $xpath, [''] ); |
1335
|
|
|
|
|
|
|
$resp->header( "Content-Length" => length $canon ); |
1336
|
|
|
|
|
|
|
$resp->content($canon); |
1337
|
|
|
|
|
|
|
} |
1338
|
|
|
|
|
|
|
return $resp; |
1339
|
|
|
|
|
|
|
} |
1340
|
|
|
|
|
|
|
|
1341
|
|
|
|
|
|
|
# This fuction handles message with URIs like |
1342
|
|
|
|
|
|
|
# http://blah.com/MultiSession/foe |
1343
|
|
|
|
|
|
|
# WS-Resources for this use a single process to store the state of multiple |
1344
|
|
|
|
|
|
|
# WS-Resources. The function passes the message onto the process that handles |
1345
|
|
|
|
|
|
|
# messages for all the WS-Resources of a particular type - if the process |
1346
|
|
|
|
|
|
|
# has not been created ie if this is the first call to this type of |
1347
|
|
|
|
|
|
|
# WS-Resource then this function will create the process |
1348
|
|
|
|
|
|
|
sub MultiSessionHandler { |
1349
|
|
|
|
|
|
|
my $request = shift @_; |
1350
|
|
|
|
|
|
|
print STDERR "$$ MultiSessionHandler called\n"; |
1351
|
|
|
|
|
|
|
|
1352
|
|
|
|
|
|
|
#Only Handle GET and POST |
1353
|
|
|
|
|
|
|
return HTTP::Response->new(RC_FORBIDDEN) |
1354
|
|
|
|
|
|
|
if ( $request->method ne 'POST' |
1355
|
|
|
|
|
|
|
&& $request->method ne 'GET' |
1356
|
|
|
|
|
|
|
&& $request->method ne 'DELETE' |
1357
|
|
|
|
|
|
|
&& $request->method ne 'PUT' ); |
1358
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
my $Path = $request->uri->path; |
1360
|
|
|
|
|
|
|
|
1361
|
|
|
|
|
|
|
#strip extra '/' at start of URL |
1362
|
|
|
|
|
|
|
$Path =~ s/^\/+//o; |
1363
|
|
|
|
|
|
|
|
1364
|
|
|
|
|
|
|
#remeber the Path - we will put this in our responses so clients |
1365
|
|
|
|
|
|
|
#will know who sent them the message - part of WS-Addressing |
1366
|
|
|
|
|
|
|
$ENV{FROM} = $ENV{URL} . $Path; |
1367
|
|
|
|
|
|
|
|
1368
|
|
|
|
|
|
|
#split up Path part of URL - we multiplex on the first part (the base) |
1369
|
|
|
|
|
|
|
#the module name is the last part |
1370
|
|
|
|
|
|
|
my @PathArray = split( /\//, $Path ); |
1371
|
|
|
|
|
|
|
my $ID = pop @PathArray; |
1372
|
|
|
|
|
|
|
my ($module); |
1373
|
|
|
|
|
|
|
|
1374
|
|
|
|
|
|
|
if ( $ID =~ /\d+-?d*/o |
1375
|
|
|
|
|
|
|
|| $ID =~ /^\w+\.(xsl|js|css|svg)$/o ) #a resource identifier |
1376
|
|
|
|
|
|
|
{ |
1377
|
|
|
|
|
|
|
$module = pop @PathArray; |
1378
|
|
|
|
|
|
|
} else { |
1379
|
|
|
|
|
|
|
$module = $ID; |
1380
|
|
|
|
|
|
|
} |
1381
|
|
|
|
|
|
|
$ENV{ID} = $ID; |
1382
|
|
|
|
|
|
|
my $base = $PathArray[0]; |
1383
|
|
|
|
|
|
|
my $RelativeDirectory = join '/', @PathArray; |
1384
|
|
|
|
|
|
|
|
1385
|
|
|
|
|
|
|
#this is the absolute path now |
1386
|
|
|
|
|
|
|
my $Directory = $ENV{WSRF_MODULES} . "/" . $RelativeDirectory; |
1387
|
|
|
|
|
|
|
|
1388
|
|
|
|
|
|
|
#check the message actually maps to a module |
1389
|
|
|
|
|
|
|
my $tmpPath = $Directory . '/' . $module . ".pm"; |
1390
|
|
|
|
|
|
|
print STDERR "$$ Path to module $tmpPath\n"; |
1391
|
|
|
|
|
|
|
if ( !-f $tmpPath ) { |
1392
|
|
|
|
|
|
|
print STDERR "$$ ERROR:: $tmpPath No Such File\n"; |
1393
|
|
|
|
|
|
|
my $fail = new HTTP::Response(RC_OK); |
1394
|
|
|
|
|
|
|
$fail->header( 'Content-Type' => 'text/xml' ); |
1395
|
|
|
|
|
|
|
$fail->content( |
1396
|
|
|
|
|
|
|
SOAP::Serializer->fault( |
1397
|
|
|
|
|
|
|
'No Service', "Check Endpoint of Service" |
1398
|
|
|
|
|
|
|
) |
1399
|
|
|
|
|
|
|
); |
1400
|
|
|
|
|
|
|
return $fail; |
1401
|
|
|
|
|
|
|
} |
1402
|
|
|
|
|
|
|
|
1403
|
|
|
|
|
|
|
my ($PUT); |
1404
|
|
|
|
|
|
|
if ( $request->method eq 'PUT' ) { |
1405
|
|
|
|
|
|
|
$PUT = 1; |
1406
|
|
|
|
|
|
|
|
1407
|
|
|
|
|
|
|
my $To = $ENV{URL}; |
1408
|
|
|
|
|
|
|
chop $To; |
1409
|
|
|
|
|
|
|
$To .= $request->uri; |
1410
|
|
|
|
|
|
|
my $header = |
1411
|
|
|
|
|
|
|
SOAP::Header->value( "" . $To . "" )->type('xml'); |
1412
|
|
|
|
|
|
|
my $xml = $request->content; |
1413
|
|
|
|
|
|
|
|
1414
|
|
|
|
|
|
|
print STDERR "$$ Attempt to PUT\n"; |
1415
|
|
|
|
|
|
|
|
1416
|
|
|
|
|
|
|
$xml =~ s/^<\?xml[\s\w\.\-].*\?>\n?//o; |
1417
|
|
|
|
|
|
|
print STDERR "$$ >>>xml>>>\n$xml\n<<
|
1418
|
|
|
|
|
|
|
|
1419
|
|
|
|
|
|
|
my $data = |
1420
|
|
|
|
|
|
|
SOAP::Data->name('PutResourcePropertyDocument')->prefix('wsrp') |
1421
|
|
|
|
|
|
|
->attr( { 'xmlns:wsrp' => $WSRF::Constants::WSRP } ) |
1422
|
|
|
|
|
|
|
->value( \SOAP::Data->value($xml)->type('xml') ); |
1423
|
|
|
|
|
|
|
|
1424
|
|
|
|
|
|
|
my $envelope = WSRF::WSRFSerializer->new()->freeform( $header, $data ); |
1425
|
|
|
|
|
|
|
print "$$ >>>envelope>>>\n$envelope\n<<
|
1426
|
|
|
|
|
|
|
$request = HTTP::Request->new(); |
1427
|
|
|
|
|
|
|
$request->method('POST'); |
1428
|
|
|
|
|
|
|
$request->header( "SOAPAction" => |
1429
|
|
|
|
|
|
|
"$WSRF::Constants::WSRP/PutResourcePropertyDocument" ); |
1430
|
|
|
|
|
|
|
$request->header( "Content-Length" => length $envelope ); |
1431
|
|
|
|
|
|
|
$request->content($envelope); |
1432
|
|
|
|
|
|
|
} |
1433
|
|
|
|
|
|
|
|
1434
|
|
|
|
|
|
|
my ($GET); |
1435
|
|
|
|
|
|
|
if ( $request->method eq 'GET' ) { |
1436
|
|
|
|
|
|
|
|
1437
|
|
|
|
|
|
|
#does the client just want the WSDL for service |
1438
|
|
|
|
|
|
|
if ( $request->uri->query eq 'WSDL' ) { |
1439
|
|
|
|
|
|
|
my $resp = GetWSDL($request); |
1440
|
|
|
|
|
|
|
return $resp; |
1441
|
|
|
|
|
|
|
} elsif ( $ID =~ m/^$module\.(xsl|css|js|svg)$/ ) |
1442
|
|
|
|
|
|
|
|
1443
|
|
|
|
|
|
|
#looking for xsl or css or js |
1444
|
|
|
|
|
|
|
{ |
1445
|
|
|
|
|
|
|
print "$$ Getting $ID file\n"; |
1446
|
|
|
|
|
|
|
my $resp = HTTP::Response->new(); |
1447
|
|
|
|
|
|
|
my $file = $Directory . "/" . $ID; |
1448
|
|
|
|
|
|
|
print "$$ File to open is $file\n"; |
1449
|
|
|
|
|
|
|
if ( !( -f $file ) || !( -r $file ) ) { |
1450
|
|
|
|
|
|
|
$resp->code(404); |
1451
|
|
|
|
|
|
|
return $resp; |
1452
|
|
|
|
|
|
|
} |
1453
|
|
|
|
|
|
|
open FILE, "< $file" or die "$$ Could not open $file"; |
1454
|
|
|
|
|
|
|
my $xsl = join "", ; |
1455
|
|
|
|
|
|
|
close FILE or die "Could not close $file file"; |
1456
|
|
|
|
|
|
|
$resp->header( 'Content-Type' => 'text/xml' ) |
1457
|
|
|
|
|
|
|
if ( $ID =~ m/\.xsl$/ ); |
1458
|
|
|
|
|
|
|
$resp->header( 'Content-Type' => 'text/css' ) |
1459
|
|
|
|
|
|
|
if ( $ID =~ m/\.css$/ ); |
1460
|
|
|
|
|
|
|
$resp->header( 'Content-Type' => 'text/javascript' ) |
1461
|
|
|
|
|
|
|
if ( $ID =~ m/\.js$/ ); |
1462
|
|
|
|
|
|
|
$resp->header( 'Content-Type' => 'text/xml' ) |
1463
|
|
|
|
|
|
|
if ( $ID =~ m/\.svg$/ ); |
1464
|
|
|
|
|
|
|
|
1465
|
|
|
|
|
|
|
$resp->content($xsl); |
1466
|
|
|
|
|
|
|
return $resp; |
1467
|
|
|
|
|
|
|
} |
1468
|
|
|
|
|
|
|
|
1469
|
|
|
|
|
|
|
$GET = 1; |
1470
|
|
|
|
|
|
|
my $data = |
1471
|
|
|
|
|
|
|
SOAP::Data->name('GetResourcePropertyDocument')->prefix('wsrp') |
1472
|
|
|
|
|
|
|
->attr( { 'xmlns:wsrp' => $WSRF::Constants::WSRP } ); |
1473
|
|
|
|
|
|
|
my $To = $ENV{URL}; |
1474
|
|
|
|
|
|
|
chop $To; |
1475
|
|
|
|
|
|
|
$To .= $request->uri; |
1476
|
|
|
|
|
|
|
my $header = |
1477
|
|
|
|
|
|
|
SOAP::Header->value( "" . $To . "" )->type('xml'); |
1478
|
|
|
|
|
|
|
my $envelope = WSRF::WSRFSerializer->new()->freeform( $header, $data ); |
1479
|
|
|
|
|
|
|
$request = HTTP::Request->new(); |
1480
|
|
|
|
|
|
|
$request->method('POST'); |
1481
|
|
|
|
|
|
|
$request->header( "SOAPAction" => |
1482
|
|
|
|
|
|
|
"$WSRF::Constants::WSRP/GetResourcePropertyDocument" ); |
1483
|
|
|
|
|
|
|
$request->header( "Content-Length" => length $envelope ); |
1484
|
|
|
|
|
|
|
$request->content($envelope); |
1485
|
|
|
|
|
|
|
} |
1486
|
|
|
|
|
|
|
|
1487
|
|
|
|
|
|
|
if ( $request->method eq 'DELETE' ) { |
1488
|
|
|
|
|
|
|
my $data = |
1489
|
|
|
|
|
|
|
SOAP::Data->name('Destroy')->prefix('wsrl') |
1490
|
|
|
|
|
|
|
->attr( { 'xmlns:wsrl' => $WSRF::Constants::WSRL } ); |
1491
|
|
|
|
|
|
|
my $To = $ENV{URL}; |
1492
|
|
|
|
|
|
|
chop $To; |
1493
|
|
|
|
|
|
|
$To .= $request->uri; |
1494
|
|
|
|
|
|
|
my $header = |
1495
|
|
|
|
|
|
|
SOAP::Header->value( "" . $To . "" )->type('xml'); |
1496
|
|
|
|
|
|
|
my $envelope = WSRF::WSRFSerializer->new()->freeform( $header, $data ); |
1497
|
|
|
|
|
|
|
$request = HTTP::Request->new(); |
1498
|
|
|
|
|
|
|
$request->method('POST'); |
1499
|
|
|
|
|
|
|
$request->header( "SOAPAction" => "$WSRF::Constants::WSRL/Destroy" ); |
1500
|
|
|
|
|
|
|
$request->header( "Content-Length" => length $envelope ); |
1501
|
|
|
|
|
|
|
$request->content($envelope); |
1502
|
|
|
|
|
|
|
} |
1503
|
|
|
|
|
|
|
|
1504
|
|
|
|
|
|
|
#check if a process to handle this message has been created |
1505
|
|
|
|
|
|
|
my $SockPath = $WSRF::Constants::SOCKETS_DIRECTORY . '/' . $module; |
1506
|
|
|
|
|
|
|
my ($resp); |
1507
|
|
|
|
|
|
|
if ( !-S $SockPath ) { |
1508
|
|
|
|
|
|
|
|
1509
|
|
|
|
|
|
|
#create the file and fork the process |
1510
|
|
|
|
|
|
|
print STDERR "$$ Creating a new Service $module\n"; |
1511
|
|
|
|
|
|
|
my $service = WSRF::Resource->new( |
1512
|
|
|
|
|
|
|
module => $module, |
1513
|
|
|
|
|
|
|
path => $RelativeDirectory, |
1514
|
|
|
|
|
|
|
ID => $module |
1515
|
|
|
|
|
|
|
); |
1516
|
|
|
|
|
|
|
print STDERR "$$ Calling handle() on service\n"; |
1517
|
|
|
|
|
|
|
$service->handle(""); |
1518
|
|
|
|
|
|
|
print STDERR "$$ Connecting to Socket $SockPath\n"; |
1519
|
|
|
|
|
|
|
my $MyFH = IO::Socket::UNIX->new( |
1520
|
|
|
|
|
|
|
Peer => $SockPath, |
1521
|
|
|
|
|
|
|
Type => SOCK_STREAM, |
1522
|
|
|
|
|
|
|
Timeout => 10 |
1523
|
|
|
|
|
|
|
) |
1524
|
|
|
|
|
|
|
or die SOAP::Fault->faultcode("Container Fault") |
1525
|
|
|
|
|
|
|
->faultstring("Container Failure - Socket problem $!"); |
1526
|
|
|
|
|
|
|
|
1527
|
|
|
|
|
|
|
#if using SSL add the extra information to the HTTP request |
1528
|
|
|
|
|
|
|
if ( defined( $ENV{SSL_CLIENT_DN} ) ) { |
1529
|
|
|
|
|
|
|
$request->header( |
1530
|
|
|
|
|
|
|
'Client-SSL-Cert-Subject' => "$ENV{SSL_CLIENT_DN}" ); |
1531
|
|
|
|
|
|
|
$request->header( |
1532
|
|
|
|
|
|
|
'Client-SSL-Cert-Issuer' => "$ENV{SSL_CLIENT_ISSUER}" ); |
1533
|
|
|
|
|
|
|
} |
1534
|
|
|
|
|
|
|
|
1535
|
|
|
|
|
|
|
#print "Ingoing HTTP>>>\n".$r->as_string()."\n<<
|
1536
|
|
|
|
|
|
|
my $out = print $MyFH ( $request->as_string() ); |
1537
|
|
|
|
|
|
|
if ( !defined($out) ) { |
1538
|
|
|
|
|
|
|
print STDERR "$$ ERROR could not write to $MyFH\n"; |
1539
|
|
|
|
|
|
|
} |
1540
|
|
|
|
|
|
|
|
1541
|
|
|
|
|
|
|
#read the response from the Socket and turn it into a |
1542
|
|
|
|
|
|
|
#HTTP::Response |
1543
|
|
|
|
|
|
|
$resp = WSRF::Daemon::ResponseHandler($MyFH); |
1544
|
|
|
|
|
|
|
$MyFH->close; |
1545
|
|
|
|
|
|
|
print STDERR "$$ $Path Processing Finished\n"; |
1546
|
|
|
|
|
|
|
} else #no process to handle this message - we need to create one |
1547
|
|
|
|
|
|
|
{ |
1548
|
|
|
|
|
|
|
|
1549
|
|
|
|
|
|
|
#check the socket is up - send SOAP to socket |
1550
|
|
|
|
|
|
|
my $MyFH = IO::Socket::UNIX->new( |
1551
|
|
|
|
|
|
|
Peer => $SockPath, |
1552
|
|
|
|
|
|
|
Type => SOCK_STREAM, |
1553
|
|
|
|
|
|
|
Timeout => 10 |
1554
|
|
|
|
|
|
|
); |
1555
|
|
|
|
|
|
|
if ( !$MyFH ) { |
1556
|
|
|
|
|
|
|
|
1557
|
|
|
|
|
|
|
#create the file and fork the process |
1558
|
|
|
|
|
|
|
my $service = WSRF::Resource->new( |
1559
|
|
|
|
|
|
|
module => $module, |
1560
|
|
|
|
|
|
|
path => $RelativeDirectory, |
1561
|
|
|
|
|
|
|
ID => $module |
1562
|
|
|
|
|
|
|
); |
1563
|
|
|
|
|
|
|
$service->handle(); |
1564
|
|
|
|
|
|
|
|
1565
|
|
|
|
|
|
|
$MyFH = IO::Socket::UNIX->new( |
1566
|
|
|
|
|
|
|
Peer => $SockPath, |
1567
|
|
|
|
|
|
|
Type => SOCK_STREAM, |
1568
|
|
|
|
|
|
|
Timeout => 10 |
1569
|
|
|
|
|
|
|
) |
1570
|
|
|
|
|
|
|
or die SOAP::Fault->faultcode("Container Fault") |
1571
|
|
|
|
|
|
|
->faultstring("Container Failure - Socket problem $!"); |
1572
|
|
|
|
|
|
|
} |
1573
|
|
|
|
|
|
|
|
1574
|
|
|
|
|
|
|
#if using SSL add the extra information to the HTTP request |
1575
|
|
|
|
|
|
|
if ( defined( $ENV{SSL_CLIENT_DN} ) ) { |
1576
|
|
|
|
|
|
|
$request->header( |
1577
|
|
|
|
|
|
|
'Client-SSL-Cert-Subject' => "$ENV{SSL_CLIENT_DN}" ); |
1578
|
|
|
|
|
|
|
$request->header( |
1579
|
|
|
|
|
|
|
'Client-SSL-Cert-Issuer' => "$ENV{SSL_CLIENT_ISSUER}" ); |
1580
|
|
|
|
|
|
|
} |
1581
|
|
|
|
|
|
|
|
1582
|
|
|
|
|
|
|
my $out = print $MyFH ( $request->as_string() ); |
1583
|
|
|
|
|
|
|
if ( !defined($out) ) { print STDERR "ERROR\n" } |
1584
|
|
|
|
|
|
|
|
1585
|
|
|
|
|
|
|
#read the response from the Socket and turn it into a |
1586
|
|
|
|
|
|
|
#HTTP::Response |
1587
|
|
|
|
|
|
|
$resp = WSRF::Daemon::ResponseHandler($MyFH); |
1588
|
|
|
|
|
|
|
$MyFH->close; |
1589
|
|
|
|
|
|
|
print STDERR "$$ $Path Processing Finished\n"; |
1590
|
|
|
|
|
|
|
} |
1591
|
|
|
|
|
|
|
|
1592
|
|
|
|
|
|
|
# print STDERR "$$ >>>out>>>\n".$resp->content."\n<<
|
1593
|
|
|
|
|
|
|
if ( $GET || $PUT ) #Original Request was a GET |
1594
|
|
|
|
|
|
|
{ |
1595
|
|
|
|
|
|
|
$resp = WSRF::Container::getProperties( $resp, $Directory, $module ); |
1596
|
|
|
|
|
|
|
} |
1597
|
|
|
|
|
|
|
|
1598
|
|
|
|
|
|
|
return $resp; |
1599
|
|
|
|
|
|
|
} |
1600
|
|
|
|
|
|
|
|
1601
|
|
|
|
|
|
|
sub GetWSDL { |
1602
|
|
|
|
|
|
|
my ($request) = @_; |
1603
|
|
|
|
|
|
|
|
1604
|
|
|
|
|
|
|
#get the path from the HTTP::Request |
1605
|
|
|
|
|
|
|
my $uri = $request->uri; |
1606
|
|
|
|
|
|
|
my $path = $request->uri->path; |
1607
|
|
|
|
|
|
|
$path =~ s/^\/+//o; |
1608
|
|
|
|
|
|
|
my $endpoint = $ENV{URL} . $path; |
1609
|
|
|
|
|
|
|
|
1610
|
|
|
|
|
|
|
#strip extra '/' at start of URL |
1611
|
|
|
|
|
|
|
#$path =~ s/^\/+//o; |
1612
|
|
|
|
|
|
|
|
1613
|
|
|
|
|
|
|
#we only allow certain types of Path |
1614
|
|
|
|
|
|
|
#alphanumeric, hypen, and forward-slash |
1615
|
|
|
|
|
|
|
#BUG - this pattern is too restrictive |
1616
|
|
|
|
|
|
|
if ( $path =~ /^([-\/\w]+)$/ ) { |
1617
|
|
|
|
|
|
|
$path = $1; |
1618
|
|
|
|
|
|
|
} else { #Bad Path |
1619
|
|
|
|
|
|
|
return HTTP::Response->new(RC_FORBIDDEN); |
1620
|
|
|
|
|
|
|
} |
1621
|
|
|
|
|
|
|
|
1622
|
|
|
|
|
|
|
my $LongPATH = $ENV{WSRF_MODULES} . "/" . $path . ".WSDL"; |
1623
|
|
|
|
|
|
|
|
1624
|
|
|
|
|
|
|
# print STDERR "WSRF::Container::GetWSDL LongPATH=\"$LongPATH\"\n"; |
1625
|
|
|
|
|
|
|
|
1626
|
|
|
|
|
|
|
#BUG - this could be done with reg-ex |
1627
|
|
|
|
|
|
|
#split up path |
1628
|
|
|
|
|
|
|
my @patharray = split( /\//, $path ); |
1629
|
|
|
|
|
|
|
|
1630
|
|
|
|
|
|
|
#sometimes the path will have an ID at the end - pop it of |
1631
|
|
|
|
|
|
|
pop @patharray; |
1632
|
|
|
|
|
|
|
|
1633
|
|
|
|
|
|
|
#rebuild path |
1634
|
|
|
|
|
|
|
$path = join '/', @patharray; |
1635
|
|
|
|
|
|
|
my $ShortPATH = $ENV{WSRF_MODULES} . "/" . $path . ".WSDL"; |
1636
|
|
|
|
|
|
|
|
1637
|
|
|
|
|
|
|
# print STDERR "WSRF::Container::GetWSDL ShortPATH=\"$ShortPATH\"\n"; |
1638
|
|
|
|
|
|
|
|
1639
|
|
|
|
|
|
|
# resp will be a HTTP::Response object |
1640
|
|
|
|
|
|
|
# ReturnWSDL can throw exceptions, so we catch them |
1641
|
|
|
|
|
|
|
my ($resp); |
1642
|
|
|
|
|
|
|
|
1643
|
|
|
|
|
|
|
#check if I can read the file |
1644
|
|
|
|
|
|
|
if ( -r $LongPATH ) { |
1645
|
|
|
|
|
|
|
eval { $resp = WSRF::WSDL::ReturnWSDL( $LongPATH, $endpoint ); }; |
1646
|
|
|
|
|
|
|
if ($@) { |
1647
|
|
|
|
|
|
|
print STDERR |
1648
|
|
|
|
|
|
|
"$$ WSRF::Container::GetWSDL could not retrieve WSDL from $LongPATH"; |
1649
|
|
|
|
|
|
|
$resp = HTTP::Response->new(RC_INTERNAL_SERVER_ERROR); |
1650
|
|
|
|
|
|
|
} |
1651
|
|
|
|
|
|
|
} elsif ( -r $ShortPATH ) { |
1652
|
|
|
|
|
|
|
eval { $resp = WSRF::WSDL::ReturnWSDL( $ShortPATH, $endpoint ); }; |
1653
|
|
|
|
|
|
|
if ($@) { |
1654
|
|
|
|
|
|
|
print STDERR |
1655
|
|
|
|
|
|
|
"$$ WSRF::Container::GetWSDL could not retrieve WSDL from $ShortPATH"; |
1656
|
|
|
|
|
|
|
$resp = HTTP::Response->new(RC_INTERNAL_SERVER_ERROR); |
1657
|
|
|
|
|
|
|
} |
1658
|
|
|
|
|
|
|
} else { |
1659
|
|
|
|
|
|
|
$resp = HTTP::Response->new(RC_NOT_FOUND); |
1660
|
|
|
|
|
|
|
} |
1661
|
|
|
|
|
|
|
|
1662
|
|
|
|
|
|
|
return $resp; |
1663
|
|
|
|
|
|
|
} |
1664
|
|
|
|
|
|
|
|
1665
|
|
|
|
|
|
|
#=============================================================================== |
1666
|
|
|
|
|
|
|
# WS_Address |
1667
|
|
|
|
|
|
|
# |
1668
|
|
|
|
|
|
|
# A class for holding and handling WS-Addressing EPRs |
1669
|
|
|
|
|
|
|
# |
1670
|
|
|
|
|
|
|
package WSRF::WS_Address; |
1671
|
|
|
|
|
|
|
|
1672
|
|
|
|
|
|
|
=pod |
1673
|
|
|
|
|
|
|
|
1674
|
|
|
|
|
|
|
=head1 WSRF::WS_Address |
1675
|
|
|
|
|
|
|
|
1676
|
|
|
|
|
|
|
Class to provide support for WS-Addressing |
1677
|
|
|
|
|
|
|
|
1678
|
|
|
|
|
|
|
=head2 METHODS |
1679
|
|
|
|
|
|
|
|
1680
|
|
|
|
|
|
|
=over |
1681
|
|
|
|
|
|
|
|
1682
|
|
|
|
|
|
|
=item new |
1683
|
|
|
|
|
|
|
|
1684
|
|
|
|
|
|
|
Creates a new WSRF::WS_Address object, takes either a SOM object or raw XML that |
1685
|
|
|
|
|
|
|
contains a WS-Addressing Endpoint Reference and creates a WSRF::WS_Addressing |
1686
|
|
|
|
|
|
|
object. |
1687
|
|
|
|
|
|
|
|
1688
|
|
|
|
|
|
|
=item from_envelope |
1689
|
|
|
|
|
|
|
|
1690
|
|
|
|
|
|
|
Creates a new WSRF::WS_Address object from a SOM representation of a SOAP Envelope |
1691
|
|
|
|
|
|
|
that contains a WS-Addressing Endpoint Reference. |
1692
|
|
|
|
|
|
|
|
1693
|
|
|
|
|
|
|
=item MessageID |
1694
|
|
|
|
|
|
|
|
1695
|
|
|
|
|
|
|
If the WSRF::WS_Address is used to send a message to a service to client this function |
1696
|
|
|
|
|
|
|
is used to create a unique identifier for the message. The identifier goes into |
1697
|
|
|
|
|
|
|
the WS-Addressing SOAP Header MessageID. |
1698
|
|
|
|
|
|
|
|
1699
|
|
|
|
|
|
|
=item XML |
1700
|
|
|
|
|
|
|
|
1701
|
|
|
|
|
|
|
Returns the WS-Addressing Endpoint Reference as a string. |
1702
|
|
|
|
|
|
|
|
1703
|
|
|
|
|
|
|
=item serializeReferenceParameters |
1704
|
|
|
|
|
|
|
|
1705
|
|
|
|
|
|
|
Outputs the ReferenceParameters of the WS-Addressing Endpoint Reference. |
1706
|
|
|
|
|
|
|
|
1707
|
|
|
|
|
|
|
=back |
1708
|
|
|
|
|
|
|
|
1709
|
|
|
|
|
|
|
=cut |
1710
|
|
|
|
|
|
|
|
1711
|
|
|
|
|
|
|
sub new { |
1712
|
|
|
|
|
|
|
my ( $self, $stuff ) = @_; |
1713
|
|
|
|
|
|
|
|
1714
|
|
|
|
|
|
|
my ( $address, $ref_params, $meta_data, $XML ); |
1715
|
|
|
|
|
|
|
if ( defined($stuff) ) { |
1716
|
|
|
|
|
|
|
|
1717
|
|
|
|
|
|
|
# we accept either a SOM or XML |
1718
|
|
|
|
|
|
|
my $som = |
1719
|
|
|
|
|
|
|
UNIVERSAL::isa( $stuff => 'SOAP::SOM' ) |
1720
|
|
|
|
|
|
|
? $stuff |
1721
|
|
|
|
|
|
|
: SOAP::Deserializer->new->deserialize($stuff); |
1722
|
|
|
|
|
|
|
|
1723
|
|
|
|
|
|
|
# $XML = WSRF::SimpleSerializer->new->serialize( $som->dataof("//{$WSRF::Constants::WSA}EndpointReference")); |
1724
|
|
|
|
|
|
|
|
1725
|
|
|
|
|
|
|
$address = $som->valueof("//{$WSRF::Constants::WSA}Address"); |
1726
|
|
|
|
|
|
|
|
1727
|
|
|
|
|
|
|
#print STDERR "address= $address\n"; |
1728
|
|
|
|
|
|
|
|
1729
|
|
|
|
|
|
|
if ( $som->match("//{$WSRF::Constants::WSA}ReferenceParameters") ) { |
1730
|
|
|
|
|
|
|
my $i = 1; |
1731
|
|
|
|
|
|
|
while ( |
1732
|
|
|
|
|
|
|
$som->match( |
1733
|
|
|
|
|
|
|
"//{$WSRF::Constants::WSA}ReferenceParameters/[$i]") |
1734
|
|
|
|
|
|
|
) |
1735
|
|
|
|
|
|
|
{ |
1736
|
|
|
|
|
|
|
$ref_params .= WSRF::SimpleSerializer->new->serialize( |
1737
|
|
|
|
|
|
|
$som->dataof( |
1738
|
|
|
|
|
|
|
"//{$WSRF::Constants::WSA}ReferenceParameters/[$i]") |
1739
|
|
|
|
|
|
|
); |
1740
|
|
|
|
|
|
|
$i++; |
1741
|
|
|
|
|
|
|
} |
1742
|
|
|
|
|
|
|
} |
1743
|
|
|
|
|
|
|
|
1744
|
|
|
|
|
|
|
if ( $som->match("//{$WSRF::Constants::WSA}Metadata") ) { |
1745
|
|
|
|
|
|
|
my $i = 1; |
1746
|
|
|
|
|
|
|
while ( $som->match("//{$WSRF::Constants::WSA}Metadata/[$i]") ) { |
1747
|
|
|
|
|
|
|
$meta_data .= |
1748
|
|
|
|
|
|
|
WSRF::SimpleSerializer->new->serialize( |
1749
|
|
|
|
|
|
|
$som->dataof("//{$WSRF::Constants::WSA}Metadata/[$i]") ); |
1750
|
|
|
|
|
|
|
$i++; |
1751
|
|
|
|
|
|
|
} |
1752
|
|
|
|
|
|
|
} |
1753
|
|
|
|
|
|
|
|
1754
|
|
|
|
|
|
|
} |
1755
|
|
|
|
|
|
|
|
1756
|
|
|
|
|
|
|
bless { |
1757
|
|
|
|
|
|
|
_Address => $address, |
1758
|
|
|
|
|
|
|
_ReferenceParameters => $ref_params, |
1759
|
|
|
|
|
|
|
_Metadata => $meta_data, |
1760
|
|
|
|
|
|
|
_XML => $XML |
1761
|
|
|
|
|
|
|
}, $self; |
1762
|
|
|
|
|
|
|
|
1763
|
|
|
|
|
|
|
} |
1764
|
|
|
|
|
|
|
|
1765
|
|
|
|
|
|
|
sub from_envelope { |
1766
|
|
|
|
|
|
|
my ( $self, $stuff ) = @_; |
1767
|
|
|
|
|
|
|
|
1768
|
|
|
|
|
|
|
return $self unless defined $stuff; |
1769
|
|
|
|
|
|
|
|
1770
|
|
|
|
|
|
|
my ( $address, $ref_params, $meta_data, $XML ); |
1771
|
|
|
|
|
|
|
my $som = |
1772
|
|
|
|
|
|
|
UNIVERSAL::isa( $stuff => 'SOAP::SOM' ) |
1773
|
|
|
|
|
|
|
? $stuff |
1774
|
|
|
|
|
|
|
: SOAP::Deserializer->new->deserialize($stuff); |
1775
|
|
|
|
|
|
|
|
1776
|
|
|
|
|
|
|
$address = |
1777
|
|
|
|
|
|
|
$som->match("//Body//EndpointReference/{$WSRF::Constants::WSA}Address") |
1778
|
|
|
|
|
|
|
? $som->valueof( |
1779
|
|
|
|
|
|
|
"//Body//EndpointReference/{$WSRF::Constants::WSA}Address") |
1780
|
|
|
|
|
|
|
: die |
1781
|
|
|
|
|
|
|
"WS_Address::from_envlope No wsa:EndpointReference in Envelope Body\n"; |
1782
|
|
|
|
|
|
|
|
1783
|
|
|
|
|
|
|
# print STDERR "address= $address\n"; |
1784
|
|
|
|
|
|
|
|
1785
|
|
|
|
|
|
|
if ( |
1786
|
|
|
|
|
|
|
$som->match( |
1787
|
|
|
|
|
|
|
"//Body//EndpointReference/{$WSRF::Constants::WSA}ReferenceParameters" ) |
1788
|
|
|
|
|
|
|
) |
1789
|
|
|
|
|
|
|
{ |
1790
|
|
|
|
|
|
|
my $i = 1; |
1791
|
|
|
|
|
|
|
while ( |
1792
|
|
|
|
|
|
|
$som->match( "//Body//EndpointReference/{$WSRF::Constants::WSA}ReferenceParameters/[$i]" |
1793
|
|
|
|
|
|
|
) |
1794
|
|
|
|
|
|
|
) |
1795
|
|
|
|
|
|
|
{ |
1796
|
|
|
|
|
|
|
$ref_params .= WSRF::SimpleSerializer->new->serialize( |
1797
|
|
|
|
|
|
|
$som->dataof( |
1798
|
|
|
|
|
|
|
"//Body//EndpointReference/{$WSRF::Constants::WSA}ReferenceParameters/[$i]" |
1799
|
|
|
|
|
|
|
) |
1800
|
|
|
|
|
|
|
); |
1801
|
|
|
|
|
|
|
$i++; |
1802
|
|
|
|
|
|
|
} |
1803
|
|
|
|
|
|
|
} |
1804
|
|
|
|
|
|
|
|
1805
|
|
|
|
|
|
|
if ( |
1806
|
|
|
|
|
|
|
$som->match( |
1807
|
|
|
|
|
|
|
"//Body//EndpointReference/{$WSRF::Constants::WSA}Metadata") |
1808
|
|
|
|
|
|
|
) |
1809
|
|
|
|
|
|
|
{ |
1810
|
|
|
|
|
|
|
my $i = 1; |
1811
|
|
|
|
|
|
|
while ( |
1812
|
|
|
|
|
|
|
$som->match( |
1813
|
|
|
|
|
|
|
"//Body//EndpointReference{$WSRF::Constants::WSA}Metadata/[$i]") |
1814
|
|
|
|
|
|
|
) |
1815
|
|
|
|
|
|
|
{ |
1816
|
|
|
|
|
|
|
$meta_data .= WSRF::SimpleSerializer->new->serialize( |
1817
|
|
|
|
|
|
|
$som->dataof( |
1818
|
|
|
|
|
|
|
"//Body//EndpointRefernce/{$WSRF::Constants::WSA}Metadata/[$i]" |
1819
|
|
|
|
|
|
|
) |
1820
|
|
|
|
|
|
|
); |
1821
|
|
|
|
|
|
|
$i++; |
1822
|
|
|
|
|
|
|
} |
1823
|
|
|
|
|
|
|
} |
1824
|
|
|
|
|
|
|
|
1825
|
|
|
|
|
|
|
bless { |
1826
|
|
|
|
|
|
|
_Address => $address, |
1827
|
|
|
|
|
|
|
_ReferenceParameters => $ref_params, |
1828
|
|
|
|
|
|
|
_Metadata => $meta_data, |
1829
|
|
|
|
|
|
|
_XML => $XML |
1830
|
|
|
|
|
|
|
}, $self; |
1831
|
|
|
|
|
|
|
} |
1832
|
|
|
|
|
|
|
|
1833
|
|
|
|
|
|
|
sub BEGIN { |
1834
|
|
|
|
|
|
|
no strict 'refs'; |
1835
|
|
|
|
|
|
|
|
1836
|
|
|
|
|
|
|
for my $method (qw(Address ReferenceParameters Metadata )) { |
1837
|
|
|
|
|
|
|
my $field = '_' . $method; |
1838
|
|
|
|
|
|
|
*$method = sub { |
1839
|
|
|
|
|
|
|
my $self = shift; |
1840
|
|
|
|
|
|
|
@_ |
1841
|
|
|
|
|
|
|
? ( $self->{$field} = shift, return $self ) |
1842
|
|
|
|
|
|
|
: return $self->{$field}; |
1843
|
|
|
|
|
|
|
} |
1844
|
|
|
|
|
|
|
} |
1845
|
|
|
|
|
|
|
} |
1846
|
|
|
|
|
|
|
|
1847
|
|
|
|
|
|
|
sub MessageID { |
1848
|
|
|
|
|
|
|
return join '', 'urn:www.sve.man.ac.uk-', int( rand 100000000000 ) + 1, |
1849
|
|
|
|
|
|
|
gmtime; |
1850
|
|
|
|
|
|
|
} |
1851
|
|
|
|
|
|
|
|
1852
|
|
|
|
|
|
|
sub XML { |
1853
|
|
|
|
|
|
|
my $self = shift; |
1854
|
|
|
|
|
|
|
|
1855
|
|
|
|
|
|
|
if ( !defined $self->{_XML} ) { |
1856
|
|
|
|
|
|
|
my $XML = ''; |
1857
|
|
|
|
|
|
|
$XML .= " "; |
1858
|
|
|
|
|
|
|
$XML .= '' . $self->{_Address} . ''; |
1859
|
|
|
|
|
|
|
$XML .= |
1860
|
|
|
|
|
|
|
$self->{_ReferenceParameters} ? $self->{_ReferenceParameters} : ''; |
1861
|
|
|
|
|
|
|
$XML .= $self->{_Metadata} ? $self->{_Metadata} : ''; |
1862
|
|
|
|
|
|
|
$XML .= ''; |
1863
|
|
|
|
|
|
|
$self->{_XML} = $XML; |
1864
|
|
|
|
|
|
|
} |
1865
|
|
|
|
|
|
|
|
1866
|
|
|
|
|
|
|
return $self->{_XML}; |
1867
|
|
|
|
|
|
|
} |
1868
|
|
|
|
|
|
|
|
1869
|
|
|
|
|
|
|
sub serializeReferenceParameters { |
1870
|
|
|
|
|
|
|
my $self = shift; |
1871
|
|
|
|
|
|
|
|
1872
|
|
|
|
|
|
|
if ( !defined( $self->{_ReferenceParameters} ) ) { |
1873
|
|
|
|
|
|
|
return undef; |
1874
|
|
|
|
|
|
|
} |
1875
|
|
|
|
|
|
|
|
1876
|
|
|
|
|
|
|
#need to wrap the ReferenceParameters to parse |
1877
|
|
|
|
|
|
|
my $som = |
1878
|
|
|
|
|
|
|
SOAP::Deserializer->new->deserialize( |
1879
|
|
|
|
|
|
|
'<_foo>' . $self->{_ReferenceParameters} . '' ); |
1880
|
|
|
|
|
|
|
|
1881
|
|
|
|
|
|
|
my $ans = ""; |
1882
|
|
|
|
|
|
|
my $i = 1; |
1883
|
|
|
|
|
|
|
while ( $som->match("/[1]/[$i]") ) { |
1884
|
|
|
|
|
|
|
my $data = $som->dataof("/[1]/[$i]"); |
1885
|
|
|
|
|
|
|
my %attr = %{ $data->attr }; |
1886
|
|
|
|
|
|
|
$attr{'wsa:isReferenceParameter'} = 'true'; |
1887
|
|
|
|
|
|
|
$data->attr( \%attr ); |
1888
|
|
|
|
|
|
|
$ans .= WSRF::SimpleSerializer->new->serialize($data); |
1889
|
|
|
|
|
|
|
$i++; |
1890
|
|
|
|
|
|
|
} |
1891
|
|
|
|
|
|
|
|
1892
|
|
|
|
|
|
|
return $ans; |
1893
|
|
|
|
|
|
|
|
1894
|
|
|
|
|
|
|
} |
1895
|
|
|
|
|
|
|
|
1896
|
|
|
|
|
|
|
#=============================================================================== |
1897
|
|
|
|
|
|
|
# WS-BaseFaults |
1898
|
|
|
|
|
|
|
# |
1899
|
|
|
|
|
|
|
# This function allows you to return a WS-BaseFault. |
1900
|
|
|
|
|
|
|
# Simply call die_with_Fault to case your service to |
1901
|
|
|
|
|
|
|
# through an exception. |
1902
|
|
|
|
|
|
|
# |
1903
|
|
|
|
|
|
|
# The function takes hash with the following: |
1904
|
|
|
|
|
|
|
# OriginatorReference (where did the fault originally originate) |
1905
|
|
|
|
|
|
|
# ErrorCode (some code number) |
1906
|
|
|
|
|
|
|
# dialect (?) |
1907
|
|
|
|
|
|
|
# Description (a description of the fault) |
1908
|
|
|
|
|
|
|
# FaultCause (?) |
1909
|
|
|
|
|
|
|
# For details check out the BasFault spec. |
1910
|
|
|
|
|
|
|
# |
1911
|
|
|
|
|
|
|
# I am not sure when you should throw a SOAP fault or a BaseFault |
1912
|
|
|
|
|
|
|
|
1913
|
|
|
|
|
|
|
package WSRF::BaseFaults; |
1914
|
|
|
|
|
|
|
|
1915
|
|
|
|
|
|
|
=pod |
1916
|
|
|
|
|
|
|
|
1917
|
|
|
|
|
|
|
=head1 WSRF::BaseFaults |
1918
|
|
|
|
|
|
|
|
1919
|
|
|
|
|
|
|
Class to support the WSRF BaseFaults specification |
1920
|
|
|
|
|
|
|
|
1921
|
|
|
|
|
|
|
=head2 METHODS |
1922
|
|
|
|
|
|
|
|
1923
|
|
|
|
|
|
|
=over |
1924
|
|
|
|
|
|
|
|
1925
|
|
|
|
|
|
|
=item die_with_Fault |
1926
|
|
|
|
|
|
|
|
1927
|
|
|
|
|
|
|
To return a WSRF BaseFault call die_with_Fault. die_with_Fault creates a SOAP fault |
1928
|
|
|
|
|
|
|
then dies. |
1929
|
|
|
|
|
|
|
|
1930
|
|
|
|
|
|
|
die_with_Fault( |
1931
|
|
|
|
|
|
|
OriginatorReference => $EPR, |
1932
|
|
|
|
|
|
|
ErrorCode => $errorcode, |
1933
|
|
|
|
|
|
|
dialect => $dialect, |
1934
|
|
|
|
|
|
|
Description => $Description, |
1935
|
|
|
|
|
|
|
FaultCause => $FaultCause |
1936
|
|
|
|
|
|
|
); |
1937
|
|
|
|
|
|
|
|
1938
|
|
|
|
|
|
|
OriginatorReference is the WS-Addressing Endpoint Reference of the WS-Resource that the |
1939
|
|
|
|
|
|
|
fault orignially came from. ErrorCode allows the WS-Resource to pass an error code |
1940
|
|
|
|
|
|
|
back to the client. dialect is the dialect that the error code belongs to. Description |
1941
|
|
|
|
|
|
|
provides a description of the fault and FaultCause provides the reason for the fault. |
1942
|
|
|
|
|
|
|
|
1943
|
|
|
|
|
|
|
=back |
1944
|
|
|
|
|
|
|
|
1945
|
|
|
|
|
|
|
=cut |
1946
|
|
|
|
|
|
|
|
1947
|
|
|
|
|
|
|
sub die_with_Fault { |
1948
|
|
|
|
|
|
|
my %args = @_; |
1949
|
|
|
|
|
|
|
|
1950
|
|
|
|
|
|
|
my $fault = ""; |
1951
|
|
|
|
|
|
|
$fault .= |
1952
|
|
|
|
|
|
|
"" |
1953
|
|
|
|
|
|
|
. WSRF::Time::ConvertEpochTimeToString(time) |
1954
|
|
|
|
|
|
|
. ""; |
1955
|
|
|
|
|
|
|
|
1956
|
|
|
|
|
|
|
if ( defined( $args{OriginatorReference} ) ) { |
1957
|
|
|
|
|
|
|
$fault .= |
1958
|
|
|
|
|
|
|
"" |
1959
|
|
|
|
|
|
|
. $args{OriginatorReference} |
1960
|
|
|
|
|
|
|
. ""; |
1961
|
|
|
|
|
|
|
} |
1962
|
|
|
|
|
|
|
|
1963
|
|
|
|
|
|
|
#has the client defined an error code & dialect |
1964
|
|
|
|
|
|
|
if ( defined( $args{ErrorCode} ) ) { |
1965
|
|
|
|
|
|
|
if ( defined( $args{dialect} ) ) { |
1966
|
|
|
|
|
|
|
$fault .= |
1967
|
|
|
|
|
|
|
"
|
1968
|
|
|
|
|
|
|
. $args{dialect} . "\">" |
1969
|
|
|
|
|
|
|
. $args{ErrorCode} |
1970
|
|
|
|
|
|
|
. ""; |
1971
|
|
|
|
|
|
|
} else { |
1972
|
|
|
|
|
|
|
$fault .= |
1973
|
|
|
|
|
|
|
"" . $args{ErrorCode} . ""; |
1974
|
|
|
|
|
|
|
} |
1975
|
|
|
|
|
|
|
} |
1976
|
|
|
|
|
|
|
|
1977
|
|
|
|
|
|
|
#has the client defined a Description |
1978
|
|
|
|
|
|
|
if ( defined( $args{Description} ) ) { |
1979
|
|
|
|
|
|
|
$fault .= |
1980
|
|
|
|
|
|
|
"" . $args{Description} . ""; |
1981
|
|
|
|
|
|
|
} |
1982
|
|
|
|
|
|
|
|
1983
|
|
|
|
|
|
|
#has the client defined a BaseCause |
1984
|
|
|
|
|
|
|
if ( defined( $args{FaultCause} ) ) { |
1985
|
|
|
|
|
|
|
$fault .= |
1986
|
|
|
|
|
|
|
"" . $args{FaultCause} . ""; |
1987
|
|
|
|
|
|
|
} |
1988
|
|
|
|
|
|
|
|
1989
|
|
|
|
|
|
|
$fault .= ""; |
1990
|
|
|
|
|
|
|
|
1991
|
|
|
|
|
|
|
die SOAP::Fault->faultdetail($fault); |
1992
|
|
|
|
|
|
|
} |
1993
|
|
|
|
|
|
|
|
1994
|
|
|
|
|
|
|
#=============================================================================== |
1995
|
|
|
|
|
|
|
# For WSRF services that are Session based - the process that calls |
1996
|
|
|
|
|
|
|
# this function does all the work - it loads the module, does the operation |
1997
|
|
|
|
|
|
|
# and returns the result. |
1998
|
|
|
|
|
|
|
# |
1999
|
|
|
|
|
|
|
package WSRF::Session; |
2000
|
|
|
|
|
|
|
|
2001
|
|
|
|
|
|
|
use SOAP::Transport::HTTP; |
2002
|
|
|
|
|
|
|
|
2003
|
|
|
|
|
|
|
use vars qw(@ISA); |
2004
|
|
|
|
|
|
|
|
2005
|
|
|
|
|
|
|
@ISA = qw(SOAP::Transport::HTTP::Server); |
2006
|
|
|
|
|
|
|
|
2007
|
|
|
|
|
|
|
sub DESTROY { SOAP::Trace::objects('()') } |
2008
|
|
|
|
|
|
|
|
2009
|
|
|
|
|
|
|
# constructor for the WSRF::Deamon object |
2010
|
|
|
|
|
|
|
sub new { |
2011
|
|
|
|
|
|
|
my $self = shift; |
2012
|
|
|
|
|
|
|
|
2013
|
|
|
|
|
|
|
unless ( ref $self ) { |
2014
|
|
|
|
|
|
|
my $class = ref($self) || $self; |
2015
|
|
|
|
|
|
|
$self = $class->SUPER::new(@_); |
2016
|
|
|
|
|
|
|
SOAP::Trace::objects('()'); |
2017
|
|
|
|
|
|
|
} |
2018
|
|
|
|
|
|
|
return $self; |
2019
|
|
|
|
|
|
|
} |
2020
|
|
|
|
|
|
|
|
2021
|
|
|
|
|
|
|
sub handle { |
2022
|
|
|
|
|
|
|
my $self = shift->new; |
2023
|
|
|
|
|
|
|
$self->request( shift @_ ); |
2024
|
|
|
|
|
|
|
$self->SUPER::handle; |
2025
|
|
|
|
|
|
|
return $self->response; |
2026
|
|
|
|
|
|
|
} |
2027
|
|
|
|
|
|
|
|
2028
|
|
|
|
|
|
|
#=============================================================================== |
2029
|
|
|
|
|
|
|
# Similar to the SOAP::Transport::Daemon module except it listens to a UNIX |
2030
|
|
|
|
|
|
|
# Domain Socket rather than an INET port |
2031
|
|
|
|
|
|
|
# |
2032
|
|
|
|
|
|
|
package WSRF::Daemon; |
2033
|
|
|
|
|
|
|
|
2034
|
|
|
|
|
|
|
use vars qw(@ISA); |
2035
|
|
|
|
|
|
|
|
2036
|
|
|
|
|
|
|
use HTTP::Status; |
2037
|
|
|
|
|
|
|
use SOAP::Transport::HTTP; |
2038
|
|
|
|
|
|
|
|
2039
|
|
|
|
|
|
|
@ISA = qw(SOAP::Transport::HTTP::Server); |
2040
|
|
|
|
|
|
|
|
2041
|
|
|
|
|
|
|
sub DESTROY { SOAP::Trace::objects('()') } |
2042
|
|
|
|
|
|
|
|
2043
|
|
|
|
|
|
|
# constructor for the WSRF::Deamon object |
2044
|
|
|
|
|
|
|
sub new { |
2045
|
|
|
|
|
|
|
my $self = shift; |
2046
|
|
|
|
|
|
|
|
2047
|
|
|
|
|
|
|
unless ( ref $self ) { |
2048
|
|
|
|
|
|
|
my $class = ref($self) || $self; |
2049
|
|
|
|
|
|
|
$self = $class->SUPER::new(@_); |
2050
|
|
|
|
|
|
|
SOAP::Trace::objects('()'); |
2051
|
|
|
|
|
|
|
} |
2052
|
|
|
|
|
|
|
return $self; |
2053
|
|
|
|
|
|
|
} |
2054
|
|
|
|
|
|
|
|
2055
|
|
|
|
|
|
|
# takes a socket and handles the info coming out of |
2056
|
|
|
|
|
|
|
# it, passes it to the SOAP handler and then returns |
2057
|
|
|
|
|
|
|
# the answer. |
2058
|
|
|
|
|
|
|
sub handle { |
2059
|
|
|
|
|
|
|
my $self = shift->new; |
2060
|
|
|
|
|
|
|
my $Hdle = shift; |
2061
|
|
|
|
|
|
|
|
2062
|
|
|
|
|
|
|
while ( my $new_c = $Hdle->accept ) { |
2063
|
|
|
|
|
|
|
my $req = $self->Requesthandler($new_c); |
2064
|
|
|
|
|
|
|
|
2065
|
|
|
|
|
|
|
#print "CHILD START::\n",$req->as_string, "CHILD END\n"; |
2066
|
|
|
|
|
|
|
$self->request($req); |
2067
|
|
|
|
|
|
|
$self->SUPER::handle; |
2068
|
|
|
|
|
|
|
my $resp = $self->response; |
2069
|
|
|
|
|
|
|
|
2070
|
|
|
|
|
|
|
#print "Return>>>\n".$resp->as_string."\n<<
|
2071
|
|
|
|
|
|
|
print $new_c ( $resp->as_string ); |
2072
|
|
|
|
|
|
|
} |
2073
|
|
|
|
|
|
|
close($Hdle); |
2074
|
|
|
|
|
|
|
} |
2075
|
|
|
|
|
|
|
|
2076
|
|
|
|
|
|
|
# A function that takes a HTTP message from a socket $Handle |
2077
|
|
|
|
|
|
|
# and converts it to a HTTP::Request object |
2078
|
|
|
|
|
|
|
# This HTTP handler is not very sophisticated but we know the |
2079
|
|
|
|
|
|
|
# message has already been parsed in the pipeline |
2080
|
|
|
|
|
|
|
sub Requesthandler { |
2081
|
|
|
|
|
|
|
my ( $self, $Handle ) = @_; |
2082
|
|
|
|
|
|
|
my $request = HTTP::Request->new(); |
2083
|
|
|
|
|
|
|
chomp( my $method = <$Handle> ); |
2084
|
|
|
|
|
|
|
my ( $Met, $URI, @blah ) = split( / /, $method ); |
2085
|
|
|
|
|
|
|
$request->method($Met); |
2086
|
|
|
|
|
|
|
$request->uri($URI); |
2087
|
|
|
|
|
|
|
my $SIZE = 0; |
2088
|
|
|
|
|
|
|
LINE: while ( my $line = <$Handle> ) { |
2089
|
|
|
|
|
|
|
last LINE if $line eq "\n"; |
2090
|
|
|
|
|
|
|
my ( $TAG, $VAL ) = split( /: /, $line, 2 ); |
2091
|
|
|
|
|
|
|
if ( $TAG eq "Content-Length" ) { |
2092
|
|
|
|
|
|
|
$SIZE = $VAL; |
2093
|
|
|
|
|
|
|
} elsif ( $TAG eq 'Client-SSL-Cert-Subject' ) { |
2094
|
|
|
|
|
|
|
$ENV{SSL_CLIENT_DN} = $VAL; |
2095
|
|
|
|
|
|
|
} elsif ( $TAG eq 'Client-SSL-Cert-Issuer' ) { |
2096
|
|
|
|
|
|
|
$ENV{SSL_CLIENT_ISSUER} = $VAL; |
2097
|
|
|
|
|
|
|
} |
2098
|
|
|
|
|
|
|
$request->header( $TAG, $VAL ); |
2099
|
|
|
|
|
|
|
} |
2100
|
|
|
|
|
|
|
$request->remove_header( 'TE', 'Connection', 'SOAPAction' ); |
2101
|
|
|
|
|
|
|
my $content = ""; |
2102
|
|
|
|
|
|
|
|
2103
|
|
|
|
|
|
|
if ( $SIZE != 0 ) { |
2104
|
|
|
|
|
|
|
|
2105
|
|
|
|
|
|
|
FULL: while ( my $line = <$Handle> ) { |
2106
|
|
|
|
|
|
|
$content .= $line; |
2107
|
|
|
|
|
|
|
last FULL if length($content) >= $SIZE; |
2108
|
|
|
|
|
|
|
} |
2109
|
|
|
|
|
|
|
$request->content($content); |
2110
|
|
|
|
|
|
|
} |
2111
|
|
|
|
|
|
|
|
2112
|
|
|
|
|
|
|
return $request; |
2113
|
|
|
|
|
|
|
} |
2114
|
|
|
|
|
|
|
|
2115
|
|
|
|
|
|
|
#parses a HTTP message that comes from a Socket called $Handler |
2116
|
|
|
|
|
|
|
#and returns a HTTP::Response object. |
2117
|
|
|
|
|
|
|
#not much error checking but we know the response should be |
2118
|
|
|
|
|
|
|
#good since we created it. |
2119
|
|
|
|
|
|
|
sub ResponseHandler { |
2120
|
|
|
|
|
|
|
my ($Handler) = @_; |
2121
|
|
|
|
|
|
|
my $SIZE = 0; |
2122
|
|
|
|
|
|
|
my $resp = HTTP::Response->new(RC_OK); |
2123
|
|
|
|
|
|
|
chomp( my $result = <$Handler> ); |
2124
|
|
|
|
|
|
|
|
2125
|
|
|
|
|
|
|
# $resp->message($result); |
2126
|
|
|
|
|
|
|
LINE: while ( my $line = <$Handler> ) { |
2127
|
|
|
|
|
|
|
last LINE if $line eq "\n"; |
2128
|
|
|
|
|
|
|
my ( $TAG, $VAL ) = split( /:/, $line, 2 ); |
2129
|
|
|
|
|
|
|
my $headers .= $TAG . " " . $VAL; |
2130
|
|
|
|
|
|
|
if ( $TAG eq "Content-Length" ) { |
2131
|
|
|
|
|
|
|
$SIZE = $VAL; |
2132
|
|
|
|
|
|
|
} |
2133
|
|
|
|
|
|
|
$resp->header( $TAG, $VAL ); |
2134
|
|
|
|
|
|
|
} |
2135
|
|
|
|
|
|
|
my $content = ""; |
2136
|
|
|
|
|
|
|
FULL: while ( my $line = <$Handler> ) { |
2137
|
|
|
|
|
|
|
$content .= $line; |
2138
|
|
|
|
|
|
|
last FULL if length($content) >= $SIZE; |
2139
|
|
|
|
|
|
|
} |
2140
|
|
|
|
|
|
|
$resp->content($content); |
2141
|
|
|
|
|
|
|
return $resp; |
2142
|
|
|
|
|
|
|
} |
2143
|
|
|
|
|
|
|
|
2144
|
|
|
|
|
|
|
#=============================================================================== |
2145
|
|
|
|
|
|
|
# This class takes a WSDL file and changes the endpoint to match the |
2146
|
|
|
|
|
|
|
# proper endpoint of the service |
2147
|
|
|
|
|
|
|
# |
2148
|
|
|
|
|
|
|
# BUG(FIXED) - "soap:address" is hardcoded, problem with XML::DOM not |
2149
|
|
|
|
|
|
|
# understanding namespaces - FIXED |
2150
|
|
|
|
|
|
|
|
2151
|
|
|
|
|
|
|
package WSRF::WSDL; |
2152
|
|
|
|
|
|
|
|
2153
|
|
|
|
|
|
|
use XML::DOM; |
2154
|
|
|
|
|
|
|
use HTTP::Status; |
2155
|
|
|
|
|
|
|
|
2156
|
|
|
|
|
|
|
sub ReturnWSDL { |
2157
|
|
|
|
|
|
|
my ( $FILEPATH, $endpoint ) = @_; |
2158
|
|
|
|
|
|
|
|
2159
|
|
|
|
|
|
|
# print STDERR "WSDL File Path = $FILEPATH\n"; |
2160
|
|
|
|
|
|
|
|
2161
|
|
|
|
|
|
|
if ( !-r $FILEPATH ) { |
2162
|
|
|
|
|
|
|
print STDERR "ERROR WSDL file does not exist\n"; |
2163
|
|
|
|
|
|
|
return HTTP::Response->new(RC_NOT_FOUND); |
2164
|
|
|
|
|
|
|
} |
2165
|
|
|
|
|
|
|
|
2166
|
|
|
|
|
|
|
#open file and read contents |
2167
|
|
|
|
|
|
|
#print "Creating Response Object\n"; |
2168
|
|
|
|
|
|
|
#if we cannot open file we do NOT throw a SOAP fault |
2169
|
|
|
|
|
|
|
#because we are not answering a SOAP request but a HTTP |
2170
|
|
|
|
|
|
|
#GET request for the WSDL. This exception should be caught |
2171
|
|
|
|
|
|
|
#by however has called this function. |
2172
|
|
|
|
|
|
|
open FILE, "< $FILEPATH" or die "Could not open WSDL file"; |
2173
|
|
|
|
|
|
|
|
2174
|
|
|
|
|
|
|
#read file |
2175
|
|
|
|
|
|
|
my $wsdl = join "", ; |
2176
|
|
|
|
|
|
|
|
2177
|
|
|
|
|
|
|
#close file |
2178
|
|
|
|
|
|
|
close FILE or die "Could not close WSDL file"; |
2179
|
|
|
|
|
|
|
|
2180
|
|
|
|
|
|
|
#take a copy of the WSDL |
2181
|
|
|
|
|
|
|
my $soap = $wsdl; |
2182
|
|
|
|
|
|
|
|
2183
|
|
|
|
|
|
|
#get the prefix for the http://schemas.xmlsoap.org/wsdl/soap/ |
2184
|
|
|
|
|
|
|
#namespace - hacky because XML::DOM does not like namespaces |
2185
|
|
|
|
|
|
|
$soap =~ s/="http:\/\/schemas\.xmlsoap\.org\/wsdl\/soap\/"(.|\n)*//o; |
2186
|
|
|
|
|
|
|
$soap =~ s/(.|\n)*xmlns://o; |
2187
|
|
|
|
|
|
|
|
2188
|
|
|
|
|
|
|
# print STDERR "Soap Namespace= ".$soap."\n"; |
2189
|
|
|
|
|
|
|
|
2190
|
|
|
|
|
|
|
my $parser = new XML::DOM::Parser; |
2191
|
|
|
|
|
|
|
|
2192
|
|
|
|
|
|
|
# we used to just parse the file but the above hack screwed that |
2193
|
|
|
|
|
|
|
# up - we just parse the string. |
2194
|
|
|
|
|
|
|
# my $doc = $parser->parsefile($FILEPATH); |
2195
|
|
|
|
|
|
|
my $doc = $parser->parse($wsdl); |
2196
|
|
|
|
|
|
|
my $node = $doc->getElementsByTagName( $soap . ":address" ); |
2197
|
|
|
|
|
|
|
|
2198
|
|
|
|
|
|
|
if ( !defined $node->item(0) ) { |
2199
|
|
|
|
|
|
|
print STDERR "$$ ERROR in WSDL file - no " . $soap |
2200
|
|
|
|
|
|
|
. ":address element\n"; |
2201
|
|
|
|
|
|
|
return HTTP::Response->new(RC_INTERNAL_SERVER_ERROR); |
2202
|
|
|
|
|
|
|
} |
2203
|
|
|
|
|
|
|
|
2204
|
|
|
|
|
|
|
#These methods can throw exceptions - please catch them |
2205
|
|
|
|
|
|
|
$node->item(0)->getAttributeNode("location")->setValue(); |
2206
|
|
|
|
|
|
|
$node->item(0)->getAttributeNode("location")->setValue($endpoint); |
2207
|
|
|
|
|
|
|
|
2208
|
|
|
|
|
|
|
my $ans = $doc->toString; |
2209
|
|
|
|
|
|
|
$doc->dispose; |
2210
|
|
|
|
|
|
|
|
2211
|
|
|
|
|
|
|
my $resp = HTTP::Response->new(RC_OK); |
2212
|
|
|
|
|
|
|
$resp->header( 'Content-Type' => 'text/xml' ); |
2213
|
|
|
|
|
|
|
$resp->content($ans); |
2214
|
|
|
|
|
|
|
return $resp; |
2215
|
|
|
|
|
|
|
} |
2216
|
|
|
|
|
|
|
|
2217
|
|
|
|
|
|
|
#=============================================================================== |
2218
|
|
|
|
|
|
|
# |
2219
|
|
|
|
|
|
|
# Some helper functions that have been bundled together |
2220
|
|
|
|
|
|
|
# |
2221
|
|
|
|
|
|
|
package WSRF::GSutil; |
2222
|
|
|
|
|
|
|
|
2223
|
|
|
|
|
|
|
use IO::Socket; |
2224
|
|
|
|
|
|
|
|
2225
|
|
|
|
|
|
|
# function to generate a unique handle for the resource. |
2226
|
|
|
|
|
|
|
# BUG - the name is misleading, GSH is a hangover from OGSI |
2227
|
|
|
|
|
|
|
sub CalGSH_ID { |
2228
|
|
|
|
|
|
|
my $num = int( rand 100000 ) + 1; |
2229
|
|
|
|
|
|
|
my $gsh_id = join( '', gmtime ) . $num; |
2230
|
|
|
|
|
|
|
return $gsh_id; |
2231
|
|
|
|
|
|
|
|
2232
|
|
|
|
|
|
|
} |
2233
|
|
|
|
|
|
|
|
2234
|
|
|
|
|
|
|
# create a WS-Address |
2235
|
|
|
|
|
|
|
# BUG - we die without throwing proper SOAP faults |
2236
|
|
|
|
|
|
|
# function takes a HASH with the following |
2237
|
|
|
|
|
|
|
# path = relative path to module directory (relative to $ENV{WSRF_MODULES}) |
2238
|
|
|
|
|
|
|
# module = name of module file |
2239
|
|
|
|
|
|
|
# ID = the WS-Resource identifier (can be created with CalGSH_ID above) |
2240
|
|
|
|
|
|
|
sub createWSAddress { |
2241
|
|
|
|
|
|
|
my %args = @_; |
2242
|
|
|
|
|
|
|
|
2243
|
|
|
|
|
|
|
my $URL = $ENV{'URL'}; |
2244
|
|
|
|
|
|
|
my $path = $args{path} || die "createWSAddress:: No Module Path\n"; |
2245
|
|
|
|
|
|
|
my $module = $args{module} || die "createWSAddress:: No Module\n"; |
2246
|
|
|
|
|
|
|
my $ID = $args{ID} || die "createWSAddress:: No ID\n"; |
2247
|
|
|
|
|
|
|
|
2248
|
|
|
|
|
|
|
#strip .pm from module name if it is there |
2249
|
|
|
|
|
|
|
$module =~ s/\.pm$//o; |
2250
|
|
|
|
|
|
|
|
2251
|
|
|
|
|
|
|
#strip leading / |
2252
|
|
|
|
|
|
|
$path =~ s/^\/+//o; |
2253
|
|
|
|
|
|
|
|
2254
|
|
|
|
|
|
|
#strip trailing / |
2255
|
|
|
|
|
|
|
$path =~ s/\/+$//o; |
2256
|
|
|
|
|
|
|
|
2257
|
|
|
|
|
|
|
#actual endpoint of service |
2258
|
|
|
|
|
|
|
my $endpoint = $ENV{'URL'} . $path . '/' . $module . '/' . $ID; |
2259
|
|
|
|
|
|
|
|
2260
|
|
|
|
|
|
|
#here we create the WS-Addressing string |
2261
|
|
|
|
|
|
|
my $response = |
2262
|
|
|
|
|
|
|
""; |
2263
|
|
|
|
|
|
|
$response .= "" . $endpoint . ""; |
2264
|
|
|
|
|
|
|
$response .= ""; |
2265
|
|
|
|
|
|
|
|
2266
|
|
|
|
|
|
|
return $response; |
2267
|
|
|
|
|
|
|
} |
2268
|
|
|
|
|
|
|
|
2269
|
|
|
|
|
|
|
# send some SOAP down the UNIX socket to the Resource, returns a SOM object |
2270
|
|
|
|
|
|
|
sub SendSOAPToSocket { |
2271
|
|
|
|
|
|
|
my ( $SocketAddress, $URI, $method, @params ) = @_; |
2272
|
|
|
|
|
|
|
|
2273
|
|
|
|
|
|
|
#print "SendSOAPToSocket: SocketAddress= $SocketAddress\n"; |
2274
|
|
|
|
|
|
|
#print "SendSOAPToSocket: URI= $URI\n"; |
2275
|
|
|
|
|
|
|
#print "SendSOAPToSocket: method= $method\n"; |
2276
|
|
|
|
|
|
|
#foreach my $param ( @params ) |
2277
|
|
|
|
|
|
|
#{ |
2278
|
|
|
|
|
|
|
# print "SendSOAPToSocket: params= $param\n"; |
2279
|
|
|
|
|
|
|
#} |
2280
|
|
|
|
|
|
|
|
2281
|
|
|
|
|
|
|
#create a SOAP message |
2282
|
|
|
|
|
|
|
my $my_soap = |
2283
|
|
|
|
|
|
|
SOAP::Lite->serializer->uri($URI)->envelope( method => $method, @params ); |
2284
|
|
|
|
|
|
|
|
2285
|
|
|
|
|
|
|
#print "SendSOAPToSocket: my_soap= \n".$my_soap."\n"; |
2286
|
|
|
|
|
|
|
|
2287
|
|
|
|
|
|
|
#create a HTTP message and put the SOAP into it |
2288
|
|
|
|
|
|
|
my $request = HTTP::Request->new(); |
2289
|
|
|
|
|
|
|
$request->method('POST'); |
2290
|
|
|
|
|
|
|
$request->uri($URI); |
2291
|
|
|
|
|
|
|
$request->push_header( 'Content_Length' => length($my_soap) ); |
2292
|
|
|
|
|
|
|
$request->push_header( 'Content-Type' => 'text/xml; charset=utf-8' ); |
2293
|
|
|
|
|
|
|
$request->content($my_soap); |
2294
|
|
|
|
|
|
|
|
2295
|
|
|
|
|
|
|
#BUG - have we actually checked the socket exists? |
2296
|
|
|
|
|
|
|
#open the sockect |
2297
|
|
|
|
|
|
|
my $rendev = $SocketAddress; |
2298
|
|
|
|
|
|
|
my $MyFH = IO::Socket::UNIX->new( |
2299
|
|
|
|
|
|
|
Peer => "$rendev", |
2300
|
|
|
|
|
|
|
Type => SOCK_STREAM, |
2301
|
|
|
|
|
|
|
Timeout => 10 |
2302
|
|
|
|
|
|
|
) |
2303
|
|
|
|
|
|
|
or die SOAP::Fault->faultcode("Container Fault") |
2304
|
|
|
|
|
|
|
->faultstring("Container Failure - Socket problem $!"); |
2305
|
|
|
|
|
|
|
|
2306
|
|
|
|
|
|
|
#print "SendSOAPToSocket sending \n".$request->as_string()."\n to $rendev\n"; |
2307
|
|
|
|
|
|
|
#send HTTP request with SOAP messgae down sockect |
2308
|
|
|
|
|
|
|
my $out = print $MyFH ( $request->as_string() ) |
2309
|
|
|
|
|
|
|
or die SOAP::Fault->faultcode("Container Fault") |
2310
|
|
|
|
|
|
|
->faultstring("Container Failure - Socket problem $!"); |
2311
|
|
|
|
|
|
|
|
2312
|
|
|
|
|
|
|
if ( !defined($out) ) { |
2313
|
|
|
|
|
|
|
print STDERR |
2314
|
|
|
|
|
|
|
"$$ ERROR - WSRF::GSutil::SendSOAPToSocket did not get response from Socket\n"; |
2315
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("Container Fault") |
2316
|
|
|
|
|
|
|
->faultstring("Container Failure - Socket problem"); |
2317
|
|
|
|
|
|
|
} |
2318
|
|
|
|
|
|
|
|
2319
|
|
|
|
|
|
|
#resp is a HTTP::Response Object |
2320
|
|
|
|
|
|
|
my $resp = WSRF::Daemon::ResponseHandler($MyFH); |
2321
|
|
|
|
|
|
|
|
2322
|
|
|
|
|
|
|
#$som is a WSRF::SOM object |
2323
|
|
|
|
|
|
|
my $som = WSRF::Deserializer->deserialize( $resp->content ); |
2324
|
|
|
|
|
|
|
|
2325
|
|
|
|
|
|
|
return $som; |
2326
|
|
|
|
|
|
|
} |
2327
|
|
|
|
|
|
|
|
2328
|
|
|
|
|
|
|
#=============================================================================== |
2329
|
|
|
|
|
|
|
# Some functions to handle time - convert to/from epoch time/W3C time. |
2330
|
|
|
|
|
|
|
# To handle times and compare them we convert all times in W3C format to |
2331
|
|
|
|
|
|
|
# seconds since the epoch (ie. the number of seconds since 1970) |
2332
|
|
|
|
|
|
|
# |
2333
|
|
|
|
|
|
|
# This module provides some helper classes for doing this |
2334
|
|
|
|
|
|
|
# |
2335
|
|
|
|
|
|
|
package WSRF::Time; |
2336
|
|
|
|
|
|
|
|
2337
|
|
|
|
|
|
|
=pod |
2338
|
|
|
|
|
|
|
|
2339
|
|
|
|
|
|
|
=head1 WSRF::Time |
2340
|
|
|
|
|
|
|
|
2341
|
|
|
|
|
|
|
WSRF::Time provides two helper sub routines for converting a W3C time |
2342
|
|
|
|
|
|
|
to seconds since the Epoch and vice versa. |
2343
|
|
|
|
|
|
|
|
2344
|
|
|
|
|
|
|
=head2 METHODS |
2345
|
|
|
|
|
|
|
|
2346
|
|
|
|
|
|
|
=over |
2347
|
|
|
|
|
|
|
|
2348
|
|
|
|
|
|
|
=item ConvertStringToEpochTime |
2349
|
|
|
|
|
|
|
|
2350
|
|
|
|
|
|
|
Converts a W3C date time string to the number of seconds since the UNIX Epoch. |
2351
|
|
|
|
|
|
|
|
2352
|
|
|
|
|
|
|
=item ConvertEpochTimeToString |
2353
|
|
|
|
|
|
|
|
2354
|
|
|
|
|
|
|
Converts a time in seconds since the UNIX Epoch to a W3C date time string. |
2355
|
|
|
|
|
|
|
|
2356
|
|
|
|
|
|
|
=back |
2357
|
|
|
|
|
|
|
|
2358
|
|
|
|
|
|
|
=cut |
2359
|
|
|
|
|
|
|
|
2360
|
|
|
|
|
|
|
=head2 VARIABLES |
2361
|
|
|
|
|
|
|
|
2362
|
|
|
|
|
|
|
=over |
2363
|
|
|
|
|
|
|
|
2364
|
|
|
|
|
|
|
=item EXPIRES_IN |
2365
|
|
|
|
|
|
|
|
2366
|
|
|
|
|
|
|
You can specify how long until an item expires with $WSRF::TIME::EXPIRES_IN. This variable defaults to 60 seconds. |
2367
|
|
|
|
|
|
|
|
2368
|
|
|
|
|
|
|
=back |
2369
|
|
|
|
|
|
|
|
2370
|
|
|
|
|
|
|
=cut |
2371
|
|
|
|
|
|
|
|
2372
|
|
|
|
|
|
|
|
2373
|
|
|
|
|
|
|
use DateTime::Format::W3CDTF; |
2374
|
|
|
|
|
|
|
use DateTime::Format::Epoch; |
2375
|
|
|
|
|
|
|
|
2376
|
|
|
|
|
|
|
# THE EXPIRES_IN variable, rather than hard code 60*60 seconds |
2377
|
|
|
|
|
|
|
$WSRF::TIME::EXPIRES_IN = 60; |
2378
|
|
|
|
|
|
|
|
2379
|
|
|
|
|
|
|
# convert XML format Time string to time in seconds since epoch |
2380
|
|
|
|
|
|
|
sub ConvertStringToEpochTime { |
2381
|
|
|
|
|
|
|
my ($StringTime) = @_; |
2382
|
|
|
|
|
|
|
|
2383
|
|
|
|
|
|
|
#print "StringTime = $StringTime\n"; |
2384
|
|
|
|
|
|
|
#$f object used to convert W3CDTF TimeString to DateTime object |
2385
|
|
|
|
|
|
|
my $f = DateTime::Format::W3CDTF->new; |
2386
|
|
|
|
|
|
|
|
2387
|
|
|
|
|
|
|
#$formatter used to convert DateTime object to seconds from epoch |
2388
|
|
|
|
|
|
|
#we use the unix epoch here |
2389
|
|
|
|
|
|
|
my $dt = DateTime->new( year => '1970', month => '1', day => '1' ); |
2390
|
|
|
|
|
|
|
my $formatter = DateTime::Format::Epoch->new( epoch => $dt ); |
2391
|
|
|
|
|
|
|
|
2392
|
|
|
|
|
|
|
#convert $StringTime to a DateTime object |
2393
|
|
|
|
|
|
|
#This will throw an exception if StringTime is not in the correct W3C format |
2394
|
|
|
|
|
|
|
#BUG(fixed) with DateTime::Format::W3CDTF - does not |
2395
|
|
|
|
|
|
|
#like subseconds - should patch DateTime::Format::W3CDTF |
2396
|
|
|
|
|
|
|
#strip of the crap that DateTime::Format::W3CDTF does not understand |
2397
|
|
|
|
|
|
|
$StringTime =~ s/\.\d+//; |
2398
|
|
|
|
|
|
|
|
2399
|
|
|
|
|
|
|
my $DateTimeObject = $f->parse_datetime($StringTime); |
2400
|
|
|
|
|
|
|
|
2401
|
|
|
|
|
|
|
#calc time in sec from epoch of $DateTimeObject |
2402
|
|
|
|
|
|
|
my $EpochTime = $formatter->format_datetime($DateTimeObject); |
2403
|
|
|
|
|
|
|
|
2404
|
|
|
|
|
|
|
return $EpochTime; |
2405
|
|
|
|
|
|
|
} |
2406
|
|
|
|
|
|
|
|
2407
|
|
|
|
|
|
|
# convert time in secs since Epoch to suitable XML format string |
2408
|
|
|
|
|
|
|
sub ConvertEpochTimeToString { |
2409
|
|
|
|
|
|
|
my ($EpochTime) = @_; |
2410
|
|
|
|
|
|
|
|
2411
|
|
|
|
|
|
|
#if no input time use now |
2412
|
|
|
|
|
|
|
if ( !defined($EpochTime) ) { |
2413
|
|
|
|
|
|
|
$EpochTime = time; |
2414
|
|
|
|
|
|
|
} |
2415
|
|
|
|
|
|
|
|
2416
|
|
|
|
|
|
|
#use formatter to convert epoch time to W3CDTF TimeString |
2417
|
|
|
|
|
|
|
my $dt = DateTime->new( year => 1970, month => 1, day => 1 ); |
2418
|
|
|
|
|
|
|
my $formatter = DateTime::Format::Epoch->new( epoch => $dt ); |
2419
|
|
|
|
|
|
|
|
2420
|
|
|
|
|
|
|
my $DateTimeObject = $formatter->parse_datetime($EpochTime); |
2421
|
|
|
|
|
|
|
|
2422
|
|
|
|
|
|
|
my $f = DateTime::Format::W3CDTF->new; |
2423
|
|
|
|
|
|
|
|
2424
|
|
|
|
|
|
|
my $TimeString = $f->format_datetime($DateTimeObject); |
2425
|
|
|
|
|
|
|
|
2426
|
|
|
|
|
|
|
return $TimeString; |
2427
|
|
|
|
|
|
|
} |
2428
|
|
|
|
|
|
|
|
2429
|
|
|
|
|
|
|
#=============================================================================== |
2430
|
|
|
|
|
|
|
# Class that allows us to create a new WSRF reource - uses a process to hold |
2431
|
|
|
|
|
|
|
# the state of the resource. The handle function actually forks the process |
2432
|
|
|
|
|
|
|
# to manage and hold the state of the Resource. |
2433
|
|
|
|
|
|
|
# |
2434
|
|
|
|
|
|
|
package WSRF::Resource; |
2435
|
|
|
|
|
|
|
|
2436
|
|
|
|
|
|
|
=pod |
2437
|
|
|
|
|
|
|
|
2438
|
|
|
|
|
|
|
=head1 WSRF::Resource |
2439
|
|
|
|
|
|
|
|
2440
|
|
|
|
|
|
|
A process based WS-Resource. The state of the WS-Resource is held in a |
2441
|
|
|
|
|
|
|
process, the WSRF::Lite Container talks to the WS-Resource via a named UNIX |
2442
|
|
|
|
|
|
|
socket. |
2443
|
|
|
|
|
|
|
|
2444
|
|
|
|
|
|
|
=head2 METHODS |
2445
|
|
|
|
|
|
|
|
2446
|
|
|
|
|
|
|
=over |
2447
|
|
|
|
|
|
|
|
2448
|
|
|
|
|
|
|
=item new |
2449
|
|
|
|
|
|
|
|
2450
|
|
|
|
|
|
|
Creates a new WSRF::Resource. |
2451
|
|
|
|
|
|
|
|
2452
|
|
|
|
|
|
|
my $resource = WSRF::Resource->new( |
2453
|
|
|
|
|
|
|
module => Counter, |
2454
|
|
|
|
|
|
|
path => /WSRF/Counter/Counter.pm, |
2455
|
|
|
|
|
|
|
ID => M4325324563456, |
2456
|
|
|
|
|
|
|
namespace => Counter |
2457
|
|
|
|
|
|
|
); |
2458
|
|
|
|
|
|
|
|
2459
|
|
|
|
|
|
|
B is the name of the module that implements the WS-Resource, |
2460
|
|
|
|
|
|
|
B is the path to the module relative to $ENV{WSRF_MODULES}, |
2461
|
|
|
|
|
|
|
B is the identifier for your WS-Resource, it will used as part of |
2462
|
|
|
|
|
|
|
the URI in the WS-Addressing EPR. If you do not include the B one |
2463
|
|
|
|
|
|
|
will be assigned for you. B is the namespace of the WSDL |
2464
|
|
|
|
|
|
|
port for any non WSRF operations the WS-Resource supports, if no namespace |
2465
|
|
|
|
|
|
|
is provided the name of the module will be used |
2466
|
|
|
|
|
|
|
|
2467
|
|
|
|
|
|
|
=item handle |
2468
|
|
|
|
|
|
|
|
2469
|
|
|
|
|
|
|
This subroutine should be called after B. It forks the process |
2470
|
|
|
|
|
|
|
that is the WS-Resource. Anything passed to B is sent to the |
2471
|
|
|
|
|
|
|
B method of the WS-Resource after it is created. The WS-Addressing |
2472
|
|
|
|
|
|
|
EPR of the WS-Resource is available to the WS-Resource through $ENV{WSA}. |
2473
|
|
|
|
|
|
|
B returns the WSRF identifier for the WS-Resource, this is used |
2474
|
|
|
|
|
|
|
to form the URI used in the WS-Addressing EPR. |
2475
|
|
|
|
|
|
|
|
2476
|
|
|
|
|
|
|
=item ID |
2477
|
|
|
|
|
|
|
|
2478
|
|
|
|
|
|
|
ID returns the WSRF identifier for the WS-Resource. |
2479
|
|
|
|
|
|
|
|
2480
|
|
|
|
|
|
|
=back |
2481
|
|
|
|
|
|
|
|
2482
|
|
|
|
|
|
|
=cut |
2483
|
|
|
|
|
|
|
|
2484
|
|
|
|
|
|
|
use IO::Socket; |
2485
|
|
|
|
|
|
|
|
2486
|
|
|
|
|
|
|
use vars qw($AUTOLOAD); |
2487
|
|
|
|
|
|
|
|
2488
|
|
|
|
|
|
|
# new takes a HASH with |
2489
|
|
|
|
|
|
|
# module - name of module |
2490
|
|
|
|
|
|
|
# path - relative path to module (relative to $ENV{WSRF_MODULES} |
2491
|
|
|
|
|
|
|
# ID - idnetifier for resource (if non is provided then it is calc'd |
2492
|
|
|
|
|
|
|
# for you) |
2493
|
|
|
|
|
|
|
# namepsace - for your service |
2494
|
|
|
|
|
|
|
sub new { |
2495
|
|
|
|
|
|
|
my ( $class, %args ) = @_; |
2496
|
|
|
|
|
|
|
|
2497
|
|
|
|
|
|
|
bless { |
2498
|
|
|
|
|
|
|
_module => $args{module} || die("missing module name\n"), |
2499
|
|
|
|
|
|
|
_path => $args{path} || die("missing module path\n"), |
2500
|
|
|
|
|
|
|
_ID => $args{ID} || WSRF::GSutil::CalGSH_ID(), |
2501
|
|
|
|
|
|
|
_namespace => $args{namespace} |
2502
|
|
|
|
|
|
|
|| "" |
2503
|
|
|
|
|
|
|
|
2504
|
|
|
|
|
|
|
}, $class; |
2505
|
|
|
|
|
|
|
} |
2506
|
|
|
|
|
|
|
|
2507
|
|
|
|
|
|
|
sub ID { |
2508
|
|
|
|
|
|
|
my ($self) = @_; |
2509
|
|
|
|
|
|
|
return $self->{_ID}; |
2510
|
|
|
|
|
|
|
} |
2511
|
|
|
|
|
|
|
|
2512
|
|
|
|
|
|
|
# function that forks the process that manages the Resource - after |
2513
|
|
|
|
|
|
|
# forking the init function is called on the Service. Allows user to |
2514
|
|
|
|
|
|
|
# put an init funtion into their module which they know will be |
2515
|
|
|
|
|
|
|
# called when the service is first created. |
2516
|
|
|
|
|
|
|
sub handle { |
2517
|
|
|
|
|
|
|
my ( $self, @Params ) = @_; |
2518
|
|
|
|
|
|
|
|
2519
|
|
|
|
|
|
|
my $ModulePath = $self->{_path}; |
2520
|
|
|
|
|
|
|
my $resourceID = $self->{_ID}; |
2521
|
|
|
|
|
|
|
my $ModuleName = $self->{_module}; |
2522
|
|
|
|
|
|
|
my $Namespace = $self->{_namespace}; |
2523
|
|
|
|
|
|
|
|
2524
|
|
|
|
|
|
|
#strip .pm from end of module if is there |
2525
|
|
|
|
|
|
|
$ModuleName =~ s/\.pm$//o; |
2526
|
|
|
|
|
|
|
|
2527
|
|
|
|
|
|
|
#print "handle Namespace = $Namespace\n"; |
2528
|
|
|
|
|
|
|
#$SIG{CHLD} = 'IGNORE'; |
2529
|
|
|
|
|
|
|
|
2530
|
|
|
|
|
|
|
#my $URL = $ENV{'URL'}; |
2531
|
|
|
|
|
|
|
#chop $URL; |
2532
|
|
|
|
|
|
|
my $location = $ENV{'URL'} . "$ModulePath"; |
2533
|
|
|
|
|
|
|
|
2534
|
|
|
|
|
|
|
#fork the service off here |
2535
|
|
|
|
|
|
|
if ( my $pid = fork ) { |
2536
|
|
|
|
|
|
|
|
2537
|
|
|
|
|
|
|
#parent process |
2538
|
|
|
|
|
|
|
} elsif ( defined $pid ) { #child |
2539
|
|
|
|
|
|
|
$SIG{ALRM} = sub { die "Alarm went off\n"; }; |
2540
|
|
|
|
|
|
|
|
2541
|
|
|
|
|
|
|
#There may be an open connection to the world - need to close it |
2542
|
|
|
|
|
|
|
if ( defined($WSRF::Constants::ExternSocket) ) { |
2543
|
|
|
|
|
|
|
$WSRF::Constants::ExternSocket->close; |
2544
|
|
|
|
|
|
|
undef $WSRF::Constants::ExternSocket; |
2545
|
|
|
|
|
|
|
} |
2546
|
|
|
|
|
|
|
|
2547
|
|
|
|
|
|
|
#Store the WSA addres in a ENV variable so the |
2548
|
|
|
|
|
|
|
#service can know its own EPR |
2549
|
|
|
|
|
|
|
$ENV{WSA} = |
2550
|
|
|
|
|
|
|
WSRF::GSutil::createWSAddress( |
2551
|
|
|
|
|
|
|
module => $ModuleName, |
2552
|
|
|
|
|
|
|
path => $ModulePath, |
2553
|
|
|
|
|
|
|
ID => $resourceID |
2554
|
|
|
|
|
|
|
); |
2555
|
|
|
|
|
|
|
|
2556
|
|
|
|
|
|
|
#the address of the socket were this resource is going to live |
2557
|
|
|
|
|
|
|
my $rendivous = $WSRF::Constants::SOCKETS_DIRECTORY . "/" . $resourceID; |
2558
|
|
|
|
|
|
|
|
2559
|
|
|
|
|
|
|
#remove any file that is already there... |
2560
|
|
|
|
|
|
|
if ( -e $rendivous ) { |
2561
|
|
|
|
|
|
|
unlink "$rendivous" |
2562
|
|
|
|
|
|
|
or die SOAP::Fault->faultcode("Container Fault") |
2563
|
|
|
|
|
|
|
->faultstring("Container Failure - Could not remove file"); |
2564
|
|
|
|
|
|
|
} |
2565
|
|
|
|
|
|
|
|
2566
|
|
|
|
|
|
|
print STDERR "$$ Created $resourceID rendezvous:: $rendivous\n"; |
2567
|
|
|
|
|
|
|
my $Handle = IO::Socket::UNIX->new( |
2568
|
|
|
|
|
|
|
Local => "$rendivous", |
2569
|
|
|
|
|
|
|
Type => SOCK_STREAM, |
2570
|
|
|
|
|
|
|
Listen => SOMAXCONN |
2571
|
|
|
|
|
|
|
) |
2572
|
|
|
|
|
|
|
or die SOAP::Fault->faultcode("Container Fault") |
2573
|
|
|
|
|
|
|
->faultstring("Container Failure - Socket problem $!"); |
2574
|
|
|
|
|
|
|
print STDERR "$$ $resourceID Socket: $Handle\n"; |
2575
|
|
|
|
|
|
|
|
2576
|
|
|
|
|
|
|
# redirect stderr/stdout to log directory |
2577
|
|
|
|
|
|
|
open( STDOUT, "> " . $ENV{WSRF_MODULES} . "/logs/$resourceID.log" ) |
2578
|
|
|
|
|
|
|
or print STDERR "$$ WARNING: Could not open log file " |
2579
|
|
|
|
|
|
|
. $ENV{WSRF_MODULES} |
2580
|
|
|
|
|
|
|
. "/logs/$resourceID.log in WSRF::Resource::handle\n"; |
2581
|
|
|
|
|
|
|
open( STDERR, ">&STDOUT" ); |
2582
|
|
|
|
|
|
|
|
2583
|
|
|
|
|
|
|
#my %namespaces = { 'http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceLifetime' |
2584
|
|
|
|
|
|
|
# => "$ModuleName", |
2585
|
|
|
|
|
|
|
# 'http://www.ibm.com/xmlns/stdwip/web-services/WS-ResourceProperties' |
2586
|
|
|
|
|
|
|
# => "$ModuleName" |
2587
|
|
|
|
|
|
|
# }; |
2588
|
|
|
|
|
|
|
|
2589
|
|
|
|
|
|
|
#if ($Namespace ne "" ) |
2590
|
|
|
|
|
|
|
#{ |
2591
|
|
|
|
|
|
|
# $namespaces{$Namespace} = $ModuleName; |
2592
|
|
|
|
|
|
|
#} |
2593
|
|
|
|
|
|
|
|
2594
|
|
|
|
|
|
|
#print "handle set $Namespace = ".$namespaces{$Namespace}."\n"; |
2595
|
|
|
|
|
|
|
|
2596
|
|
|
|
|
|
|
#create a new service |
2597
|
|
|
|
|
|
|
|
2598
|
|
|
|
|
|
|
# BUG - if Namespace is not set |
2599
|
|
|
|
|
|
|
# Now start the Resource in the process we have just created. |
2600
|
|
|
|
|
|
|
%WSRF::WSRP::ResourceProperties = (); |
2601
|
|
|
|
|
|
|
%WSRF::WSRP::PropertyNamespaceMap = (); |
2602
|
|
|
|
|
|
|
%WSRF::WSRP::NotDeletable = (); |
2603
|
|
|
|
|
|
|
%WSRF::WSRP::NotModifiable = (); |
2604
|
|
|
|
|
|
|
%WSRF::WSRP::NotInsert = (); |
2605
|
|
|
|
|
|
|
%WSRF::WSRP::Private = (); |
2606
|
|
|
|
|
|
|
|
2607
|
|
|
|
|
|
|
my $daemon = |
2608
|
|
|
|
|
|
|
WSRF::Daemon->new()->serializer( WSRF::WSRFSerializer->new ) |
2609
|
|
|
|
|
|
|
->deserializer( WSRF::Deserializer->new ) |
2610
|
|
|
|
|
|
|
->dispatch_to( "$ENV{WSRF_MODULES}" . "/" |
2611
|
|
|
|
|
|
|
. "$ModulePath" )->dispatch_with( |
2612
|
|
|
|
|
|
|
{ |
2613
|
|
|
|
|
|
|
$WSRF::Constants::WSRL => "$ModuleName", |
2614
|
|
|
|
|
|
|
$WSRF::Constants::WSRP => "$ModuleName", |
2615
|
|
|
|
|
|
|
$WSRF::Constants::WSSG => "$ModuleName", |
2616
|
|
|
|
|
|
|
$Namespace => $ModuleName |
2617
|
|
|
|
|
|
|
} |
2618
|
|
|
|
|
|
|
); |
2619
|
|
|
|
|
|
|
|
2620
|
|
|
|
|
|
|
#use eval to handle any time out |
2621
|
|
|
|
|
|
|
eval { $daemon->handle($Handle); }; |
2622
|
|
|
|
|
|
|
print STDERR |
2623
|
|
|
|
|
|
|
"$$ WSRF::Resource::handle caught exception: $@ - if it is \"Alarm went off\" then the WS-Resource's lifetime has expired"; |
2624
|
|
|
|
|
|
|
unlink($rendivous) |
2625
|
|
|
|
|
|
|
or print STDERR |
2626
|
|
|
|
|
|
|
"$$ WARNING: Could not remove $rendivous in WSRF::Resource::handle\n"; |
2627
|
|
|
|
|
|
|
print STDERR "$$ Resource Shutting Down\n"; |
2628
|
|
|
|
|
|
|
|
2629
|
|
|
|
|
|
|
exit; #should never get here!! |
2630
|
|
|
|
|
|
|
} else { #problem forking |
2631
|
|
|
|
|
|
|
print STDERR |
2632
|
|
|
|
|
|
|
"$$ ERROR: Could perform fork it start Resource in WSRF::Resource::handle\n"; |
2633
|
|
|
|
|
|
|
return "FAILURE"; |
2634
|
|
|
|
|
|
|
} |
2635
|
|
|
|
|
|
|
|
2636
|
|
|
|
|
|
|
#Parent Process Takes Over Here. |
2637
|
|
|
|
|
|
|
# by default the factory will call init on the service it just |
2638
|
|
|
|
|
|
|
# created - select is called to allow the child time to set up socket |
2639
|
|
|
|
|
|
|
my $rend = $WSRF::Constants::SOCKETS_DIRECTORY . "/" . $resourceID; |
2640
|
|
|
|
|
|
|
|
2641
|
|
|
|
|
|
|
#sleep for 0.2 seconds |
2642
|
|
|
|
|
|
|
select( undef, undef, undef, 0.2 ); |
2643
|
|
|
|
|
|
|
|
2644
|
|
|
|
|
|
|
#resp from SendSOAPToSocket is a WSRF::SOM object - here we call init method |
2645
|
|
|
|
|
|
|
my $resp = |
2646
|
|
|
|
|
|
|
WSRF::GSutil::SendSOAPToSocket( $rend, $ModuleName, "init", @Params ); |
2647
|
|
|
|
|
|
|
|
2648
|
|
|
|
|
|
|
#Check for a fault from the init method |
2649
|
|
|
|
|
|
|
if ( $resp->fault ) { |
2650
|
|
|
|
|
|
|
print STDERR "$$ ERROR: SOAP fault from init: " |
2651
|
|
|
|
|
|
|
. $resp->faultstring |
2652
|
|
|
|
|
|
|
. "\n in WSRF::Resource::handle\n"; |
2653
|
|
|
|
|
|
|
} |
2654
|
|
|
|
|
|
|
|
2655
|
|
|
|
|
|
|
return ( $resourceID, $resp ); |
2656
|
|
|
|
|
|
|
} |
2657
|
|
|
|
|
|
|
|
2658
|
|
|
|
|
|
|
# Once a WSRF::Resource is created with new and started using handle |
2659
|
|
|
|
|
|
|
# method we can call operations on the Service using AUTOLOAD |
2660
|
|
|
|
|
|
|
sub AUTOLOAD { |
2661
|
|
|
|
|
|
|
my ( $self, @params ) = @_; |
2662
|
|
|
|
|
|
|
|
2663
|
|
|
|
|
|
|
#strip class name from method name (Conway p56) |
2664
|
|
|
|
|
|
|
$AUTOLOAD =~ s/.*:://; |
2665
|
|
|
|
|
|
|
|
2666
|
|
|
|
|
|
|
my $rend = $WSRF::Constants::SOCKETS_DIRECTORY . "/" . $self->ID(); |
2667
|
|
|
|
|
|
|
|
2668
|
|
|
|
|
|
|
if ( $AUTOLOAD eq "DESTROY" ) { |
2669
|
|
|
|
|
|
|
|
2670
|
|
|
|
|
|
|
# print STDERR "Attempt to DESTROY ".$self->ID()."\n"; |
2671
|
|
|
|
|
|
|
return; |
2672
|
|
|
|
|
|
|
} |
2673
|
|
|
|
|
|
|
|
2674
|
|
|
|
|
|
|
#$resp is WSRF::SOM object |
2675
|
|
|
|
|
|
|
my $resp = |
2676
|
|
|
|
|
|
|
WSRF::GSutil::SendSOAPToSocket( $rend, $self->{_module}, $AUTOLOAD, |
2677
|
|
|
|
|
|
|
@params ); |
2678
|
|
|
|
|
|
|
|
2679
|
|
|
|
|
|
|
return $resp; |
2680
|
|
|
|
|
|
|
} |
2681
|
|
|
|
|
|
|
|
2682
|
|
|
|
|
|
|
#=============================================================================== |
2683
|
|
|
|
|
|
|
# This is the module that provides file locking for us - when an object of this |
2684
|
|
|
|
|
|
|
# class is created a lock file is created. The lock file is automatically |
2685
|
|
|
|
|
|
|
# removed when the object is destroyed. We could use fcntl to do this - I |
2686
|
|
|
|
|
|
|
# decided to actually create lock files so a user could manually create and |
2687
|
|
|
|
|
|
|
# remove lock files themselves. |
2688
|
|
|
|
|
|
|
# |
2689
|
|
|
|
|
|
|
# This`works by creating/checking for/removing a directory |
2690
|
|
|
|
|
|
|
# |
2691
|
|
|
|
|
|
|
# BUG - This is not very sophistcated. We use this class in WSRF::File |
2692
|
|
|
|
|
|
|
|
2693
|
|
|
|
|
|
|
=pod |
2694
|
|
|
|
|
|
|
|
2695
|
|
|
|
|
|
|
=head1 WSRF::FileLock |
2696
|
|
|
|
|
|
|
|
2697
|
|
|
|
|
|
|
Simple class to provide file locking. It is possible to use fcntl to |
2698
|
|
|
|
|
|
|
do file locking but some file systems don't support it. WSRF::FileLock is |
2699
|
|
|
|
|
|
|
used to by the file based WS-Resources in WSRF::Lite to prevent concurrent |
2700
|
|
|
|
|
|
|
access to the WS-Resource by more than one client. |
2701
|
|
|
|
|
|
|
|
2702
|
|
|
|
|
|
|
=head2 METHODS |
2703
|
|
|
|
|
|
|
|
2704
|
|
|
|
|
|
|
=over |
2705
|
|
|
|
|
|
|
|
2706
|
|
|
|
|
|
|
=item new |
2707
|
|
|
|
|
|
|
|
2708
|
|
|
|
|
|
|
B takes a name and tries to create a directory with that name, |
2709
|
|
|
|
|
|
|
if there is already a directory with that name it will sleep for half |
2710
|
|
|
|
|
|
|
a second and retry. When the directory is created a new WSRF::FileLock |
2711
|
|
|
|
|
|
|
object is returned, then the object goes out of scope the directory is |
2712
|
|
|
|
|
|
|
removed. |
2713
|
|
|
|
|
|
|
|
2714
|
|
|
|
|
|
|
my $lock = WSRF::FileLock->new($somefilelocation); |
2715
|
|
|
|
|
|
|
|
2716
|
|
|
|
|
|
|
=back |
2717
|
|
|
|
|
|
|
|
2718
|
|
|
|
|
|
|
=cut |
2719
|
|
|
|
|
|
|
|
2720
|
|
|
|
|
|
|
package WSRF::FileLock; |
2721
|
|
|
|
|
|
|
|
2722
|
|
|
|
|
|
|
#Provides a simple locking tool - |
2723
|
|
|
|
|
|
|
|
2724
|
|
|
|
|
|
|
sub new { |
2725
|
|
|
|
|
|
|
my ( $self, $file ) = @_; |
2726
|
|
|
|
|
|
|
|
2727
|
|
|
|
|
|
|
#$file is the name of the directory to make - the lock |
2728
|
|
|
|
|
|
|
until ( mkdir $file ) { |
2729
|
|
|
|
|
|
|
select( undef, undef, undef, 0.5 ); |
2730
|
|
|
|
|
|
|
print STDERR "$$ Lock on $file\n"; |
2731
|
|
|
|
|
|
|
} |
2732
|
|
|
|
|
|
|
|
2733
|
|
|
|
|
|
|
bless { _file => $file }, $self; |
2734
|
|
|
|
|
|
|
} |
2735
|
|
|
|
|
|
|
|
2736
|
|
|
|
|
|
|
sub DESTROY { |
2737
|
|
|
|
|
|
|
my ($self) = @_; |
2738
|
|
|
|
|
|
|
print STDERR "$$ Removing Lock File "; |
2739
|
|
|
|
|
|
|
print STDERR $self->{_file} . "\n"; |
2740
|
|
|
|
|
|
|
if ( -d $self->{_file} ) { |
2741
|
|
|
|
|
|
|
rmdir $self->{_file} |
2742
|
|
|
|
|
|
|
or die SOAP::Fault->faultcode("Container Fault") |
2743
|
|
|
|
|
|
|
->faultstring( "Could not remove lock file " . $self->{_file} ); |
2744
|
|
|
|
|
|
|
} |
2745
|
|
|
|
|
|
|
print STDERR "$$ Lock file " . $self->{_file} . " removed\n"; |
2746
|
|
|
|
|
|
|
} |
2747
|
|
|
|
|
|
|
|
2748
|
|
|
|
|
|
|
#=============================================================================== |
2749
|
|
|
|
|
|
|
# This module supports writing all the resource properties of a Resource to a |
2750
|
|
|
|
|
|
|
# file. Allows the state of the resource to be stored in a file between calls |
2751
|
|
|
|
|
|
|
# to the Resource. Relies on the Serialisers provided by SOAP::Lite to do the |
2752
|
|
|
|
|
|
|
# work |
2753
|
|
|
|
|
|
|
# |
2754
|
|
|
|
|
|
|
# We could use other Perl modules to do this (eg. the Dumper module) - I |
2755
|
|
|
|
|
|
|
# decided to reuse stuff from SOAP::Lite |
2756
|
|
|
|
|
|
|
# |
2757
|
|
|
|
|
|
|
package WSRF::File; |
2758
|
|
|
|
|
|
|
use Storable qw(lock_store lock_nstore lock_retrieve); |
2759
|
|
|
|
|
|
|
use Safe; |
2760
|
|
|
|
|
|
|
|
2761
|
|
|
|
|
|
|
=pod |
2762
|
|
|
|
|
|
|
|
2763
|
|
|
|
|
|
|
=head1 WSRF::File |
2764
|
|
|
|
|
|
|
|
2765
|
|
|
|
|
|
|
This class provides support for serializing the state of a WS-Resource to |
2766
|
|
|
|
|
|
|
a file. |
2767
|
|
|
|
|
|
|
|
2768
|
|
|
|
|
|
|
=head2 METHODS |
2769
|
|
|
|
|
|
|
|
2770
|
|
|
|
|
|
|
=over |
2771
|
|
|
|
|
|
|
|
2772
|
|
|
|
|
|
|
=item new |
2773
|
|
|
|
|
|
|
|
2774
|
|
|
|
|
|
|
Takes a WSRF::SOM envelope, gets the ID of the WS-Resource and then loads |
2775
|
|
|
|
|
|
|
the properties of the WS-Resource into the WSRF::WSRP::ResourceProperties |
2776
|
|
|
|
|
|
|
hash. B locks the WS-Resource so that no other client can access |
2777
|
|
|
|
|
|
|
the WS-Resource while this clients request is being processed. When the |
2778
|
|
|
|
|
|
|
WSRF::File object runs out of scope and is destroyed the lock is removed. |
2779
|
|
|
|
|
|
|
|
2780
|
|
|
|
|
|
|
=item ID |
2781
|
|
|
|
|
|
|
|
2782
|
|
|
|
|
|
|
Returns the WSRF::Lite indentifier of the WS-Resource. |
2783
|
|
|
|
|
|
|
|
2784
|
|
|
|
|
|
|
=item path |
2785
|
|
|
|
|
|
|
|
2786
|
|
|
|
|
|
|
Filename of the file that holds the state of the WS-Resource. |
2787
|
|
|
|
|
|
|
|
2788
|
|
|
|
|
|
|
|
2789
|
|
|
|
|
|
|
=item toFile |
2790
|
|
|
|
|
|
|
|
2791
|
|
|
|
|
|
|
Serializes the WSRF::WSRP::ResourceProperties hash back to the file. If the |
2792
|
|
|
|
|
|
|
properties of the WS-Resource have been modified this should be called before |
2793
|
|
|
|
|
|
|
the WSRF::File object goes out of scope. |
2794
|
|
|
|
|
|
|
|
2795
|
|
|
|
|
|
|
=back |
2796
|
|
|
|
|
|
|
|
2797
|
|
|
|
|
|
|
=cut |
2798
|
|
|
|
|
|
|
|
2799
|
|
|
|
|
|
|
# this is made a private function - Resources use files to store their state |
2800
|
|
|
|
|
|
|
# inherit this module along the way, we do not want remote clients to be |
2801
|
|
|
|
|
|
|
# able to invoke this function so we make it private. (SOAP::Lite will not |
2802
|
|
|
|
|
|
|
# allow you to invoke private functions in a module remotely) |
2803
|
|
|
|
|
|
|
# This function takes a SOM object and puts the data from the SOM object |
2804
|
|
|
|
|
|
|
# into the ResourceProperty HASH of the Resource, the resource developer |
2805
|
|
|
|
|
|
|
# only has to program using the hash. |
2806
|
|
|
|
|
|
|
# |
2807
|
|
|
|
|
|
|
my $Insert = sub { |
2808
|
|
|
|
|
|
|
my ($b) = @_; |
2809
|
|
|
|
|
|
|
|
2810
|
|
|
|
|
|
|
#get the name of the property |
2811
|
|
|
|
|
|
|
my $name = $b->dataof()->name; |
2812
|
|
|
|
|
|
|
|
2813
|
|
|
|
|
|
|
#print "insert name= ".$name."\n"; |
2814
|
|
|
|
|
|
|
|
2815
|
|
|
|
|
|
|
#check there is no user defined function |
2816
|
|
|
|
|
|
|
#for inserting this property |
2817
|
|
|
|
|
|
|
if ( defined( $WSRF::WSRP::InsertMap{$name} ) ) { |
2818
|
|
|
|
|
|
|
$WSRF::WSRP::InsertMap{$name}->($b); |
2819
|
|
|
|
|
|
|
return; |
2820
|
|
|
|
|
|
|
} |
2821
|
|
|
|
|
|
|
|
2822
|
|
|
|
|
|
|
#get the value of the property |
2823
|
|
|
|
|
|
|
my $value = $b->dataof()->value; |
2824
|
|
|
|
|
|
|
|
2825
|
|
|
|
|
|
|
#print "insert $name value= $value\n"; |
2826
|
|
|
|
|
|
|
|
2827
|
|
|
|
|
|
|
#check the property actually exists |
2828
|
|
|
|
|
|
|
if ( defined( $WSRF::WSRP::ResourceProperties{$name} ) ) { |
2829
|
|
|
|
|
|
|
|
2830
|
|
|
|
|
|
|
#check the type of the property (scalar|array) |
2831
|
|
|
|
|
|
|
my $type = ref( $WSRF::WSRP::ResourceProperties{$name} ); |
2832
|
|
|
|
|
|
|
if ( $type eq "" ) #scalar |
2833
|
|
|
|
|
|
|
{ |
2834
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{$name} = $value; |
2835
|
|
|
|
|
|
|
} elsif ( $type eq "ARRAY" ) #array |
2836
|
|
|
|
|
|
|
{ |
2837
|
|
|
|
|
|
|
|
2838
|
|
|
|
|
|
|
#add property to array |
2839
|
|
|
|
|
|
|
push( @{ $WSRF::WSRP::ResourceProperties{$name} }, $value ); |
2840
|
|
|
|
|
|
|
} elsif ( $type ne "CODE" ) { |
2841
|
|
|
|
|
|
|
print STDERR |
2842
|
|
|
|
|
|
|
"$$ ERROR: Property $name is a $type, only ARRAY,SCALAR and CODE are supported in WSRF::File::Insert\n"; |
2843
|
|
|
|
|
|
|
} |
2844
|
|
|
|
|
|
|
} else { |
2845
|
|
|
|
|
|
|
print STDERR |
2846
|
|
|
|
|
|
|
"$$ ERROR: Attempting to load property from file that has not been declared in WSRF::File::Insert\n"; |
2847
|
|
|
|
|
|
|
} |
2848
|
|
|
|
|
|
|
|
2849
|
|
|
|
|
|
|
return; |
2850
|
|
|
|
|
|
|
}; |
2851
|
|
|
|
|
|
|
|
2852
|
|
|
|
|
|
|
# Takes a SOAP::SOM envelope, gets the ID of the Resource and then loads the |
2853
|
|
|
|
|
|
|
# properties into the WSRF::WSRP::ResouceProperties hash for the service. Uses |
2854
|
|
|
|
|
|
|
# the Insert function to load the properties into the hash. Also creates a |
2855
|
|
|
|
|
|
|
# lock file - lock file is removed in the DESTROY operation when the |
2856
|
|
|
|
|
|
|
# WSRF::File object is destroyed |
2857
|
|
|
|
|
|
|
# |
2858
|
|
|
|
|
|
|
sub new { |
2859
|
|
|
|
|
|
|
my ( $class, $envelope ) = @_; |
2860
|
|
|
|
|
|
|
|
2861
|
|
|
|
|
|
|
my $address = $envelope->headerof("//{$WSRF::Constants::WSA}To"); |
2862
|
|
|
|
|
|
|
if ( defined $address ) { |
2863
|
|
|
|
|
|
|
$address = $envelope->headerof("//{$WSRF::Constants::WSA}To")->value; |
2864
|
|
|
|
|
|
|
} else { |
2865
|
|
|
|
|
|
|
print STDERR "ERROR: No ResourceID in the SOAP Header\n"; |
2866
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("No WS-Resource Identifier") |
2867
|
|
|
|
|
|
|
->faultstring("No WS-Resource identifier in SOAP Header"); |
2868
|
|
|
|
|
|
|
} |
2869
|
|
|
|
|
|
|
|
2870
|
|
|
|
|
|
|
my @PathArray = split( /\//, $address ); |
2871
|
|
|
|
|
|
|
my $ID = pop @PathArray; |
2872
|
|
|
|
|
|
|
|
2873
|
|
|
|
|
|
|
#my $ID = $ENV{ID}; |
2874
|
|
|
|
|
|
|
|
2875
|
|
|
|
|
|
|
#check the ID is safe - we do not accept dots, |
2876
|
|
|
|
|
|
|
#all paths will be relative to $ENV{WRF_MODULES} |
2877
|
|
|
|
|
|
|
#only allow alphanumeric, underscore and hyphen |
2878
|
|
|
|
|
|
|
if ( $ID =~ /^([-\w]+)$/ ) { |
2879
|
|
|
|
|
|
|
$ID = $1; |
2880
|
|
|
|
|
|
|
} else { |
2881
|
|
|
|
|
|
|
print STDERR "$$ WSRF::File ERROR: Bad $ID for WS-Resource\n"; |
2882
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("Badly formed WS-Resource Identifier") |
2883
|
|
|
|
|
|
|
->faultstring("Badly formed WS-Resource Identifier: $ID"); |
2884
|
|
|
|
|
|
|
} |
2885
|
|
|
|
|
|
|
|
2886
|
|
|
|
|
|
|
my $ID_clipped = $ID; |
2887
|
|
|
|
|
|
|
|
2888
|
|
|
|
|
|
|
#ID can be of the form 1341-4565, we use this form to all multiple |
2889
|
|
|
|
|
|
|
#WS-Resources to share the same state, the state is in the file |
2890
|
|
|
|
|
|
|
#1341 - we use this with ServiceGroup/ServiceGroupEntry |
2891
|
|
|
|
|
|
|
$ID_clipped =~ s/-\w*//o; |
2892
|
|
|
|
|
|
|
|
2893
|
|
|
|
|
|
|
my $path = $WSRF::Constants::Data . $ID_clipped; |
2894
|
|
|
|
|
|
|
|
2895
|
|
|
|
|
|
|
if ( !( -e $path ) ) { |
2896
|
|
|
|
|
|
|
print STDERR "$$ ERROR: No Resource $path\n"; |
2897
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("No WS-Resource") |
2898
|
|
|
|
|
|
|
->faultstring("No WS-Resource with Identifer $ID"); |
2899
|
|
|
|
|
|
|
} |
2900
|
|
|
|
|
|
|
|
2901
|
|
|
|
|
|
|
#The address of the lock file |
2902
|
|
|
|
|
|
|
my $lock = $path . ".lock"; |
2903
|
|
|
|
|
|
|
|
2904
|
|
|
|
|
|
|
#Acquire a lock for the file |
2905
|
|
|
|
|
|
|
my $Lock = WSRF::FileLock->new($lock); |
2906
|
|
|
|
|
|
|
|
2907
|
|
|
|
|
|
|
# open FILE, "$path" or die SOAP::Fault->faultcode("Container Failure") |
2908
|
|
|
|
|
|
|
# ->faultstring("Container Failure: Could not open WS-Resource file"); |
2909
|
|
|
|
|
|
|
# #read the XML from the file |
2910
|
|
|
|
|
|
|
# my $XML = join "", ; |
2911
|
|
|
|
|
|
|
|
2912
|
|
|
|
|
|
|
# close FILE or die SOAP::Fault->faultcode("Container Failure") |
2913
|
|
|
|
|
|
|
# ->faultstring("Container Failure: Could not close WS-Resource file"); |
2914
|
|
|
|
|
|
|
|
2915
|
|
|
|
|
|
|
# convert the XML into a SOM object. (the SOM object will still allow access |
2916
|
|
|
|
|
|
|
# to the raw XML) |
2917
|
|
|
|
|
|
|
# my $som = WSRF::Deserializer->deserialize($XML); |
2918
|
|
|
|
|
|
|
|
2919
|
|
|
|
|
|
|
#iterate through the ResourceProperties and call insert for each one |
2920
|
|
|
|
|
|
|
# my $k = 1; |
2921
|
|
|
|
|
|
|
# while( $som->match("//ResourceProperties/[$k]") ) |
2922
|
|
|
|
|
|
|
# { |
2923
|
|
|
|
|
|
|
#print "SOM name= ".$som->dataof("//ResourceProperties/[$k]")->name()."\n"; |
2924
|
|
|
|
|
|
|
# $Insert->( $som->match("//ResourceProperties/[$k]") ); |
2925
|
|
|
|
|
|
|
# $k++; |
2926
|
|
|
|
|
|
|
# } |
2927
|
|
|
|
|
|
|
|
2928
|
|
|
|
|
|
|
# my $safe = new Safe; |
2929
|
|
|
|
|
|
|
# $safe->permit(qw(:default require)); |
2930
|
|
|
|
|
|
|
# local $Storable::Eval = sub { $safe->reval($_[0]) }; |
2931
|
|
|
|
|
|
|
my $hashref = Storable::lock_retrieve($path); |
2932
|
|
|
|
|
|
|
|
2933
|
|
|
|
|
|
|
# print "Thawing...\n"; |
2934
|
|
|
|
|
|
|
# foreach my $key (keys %$hashref) |
2935
|
|
|
|
|
|
|
# { |
2936
|
|
|
|
|
|
|
# $WSRF::WSRP::ResourceProperties{$key} = $hashref->{$key}; |
2937
|
|
|
|
|
|
|
# print $key.": ".$hashref->{$key}."\n"; |
2938
|
|
|
|
|
|
|
# } |
2939
|
|
|
|
|
|
|
#print "CurrentTime = ".${$hashref->{CurrentTime}}."\n"; |
2940
|
|
|
|
|
|
|
|
2941
|
|
|
|
|
|
|
%WSRF::WSRP::ResourceProperties = |
2942
|
|
|
|
|
|
|
( %WSRF::WSRP::ResourceProperties, %{ $hashref->{Properties} } ); |
2943
|
|
|
|
|
|
|
|
2944
|
|
|
|
|
|
|
%WSRF::WSRP::Private = ( %WSRF::WSRP::Private, %{ $hashref->{Private} } ); |
2945
|
|
|
|
|
|
|
|
2946
|
|
|
|
|
|
|
#check that the resource is still alive - if TT time is not |
2947
|
|
|
|
|
|
|
#set then TT is infinity |
2948
|
|
|
|
|
|
|
if ( defined( $WSRF::WSRP::ResourceProperties{'TerminationTime'} ) |
2949
|
|
|
|
|
|
|
&& ( $WSRF::WSRP::ResourceProperties{'TerminationTime'} ne "" ) ) |
2950
|
|
|
|
|
|
|
{ |
2951
|
|
|
|
|
|
|
if ( |
2952
|
|
|
|
|
|
|
WSRF::Time::ConvertStringToEpochTime( |
2953
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{'TerminationTime'} |
2954
|
|
|
|
|
|
|
) < time |
2955
|
|
|
|
|
|
|
) |
2956
|
|
|
|
|
|
|
{ |
2957
|
|
|
|
|
|
|
print STDERR "$$ Resource $ID expired\n"; |
2958
|
|
|
|
|
|
|
unlink $path |
2959
|
|
|
|
|
|
|
or die SOAP::Fault->faultcode("Container Failure") |
2960
|
|
|
|
|
|
|
->faultstring("Container Failure: Could not remove file"); |
2961
|
|
|
|
|
|
|
rmdir $lock |
2962
|
|
|
|
|
|
|
or die SOAP::Fault->faultcode("Container Failure") |
2963
|
|
|
|
|
|
|
->faultstring("Container Failure: Could not remove lock file"); |
2964
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("No such Resource") |
2965
|
|
|
|
|
|
|
->faultstring("No such Resource $ID - Lifetime expired"); |
2966
|
|
|
|
|
|
|
} |
2967
|
|
|
|
|
|
|
} |
2968
|
|
|
|
|
|
|
|
2969
|
|
|
|
|
|
|
bless { |
2970
|
|
|
|
|
|
|
_ID => $ID, |
2971
|
|
|
|
|
|
|
_path => $path, |
2972
|
|
|
|
|
|
|
_lock => $Lock |
2973
|
|
|
|
|
|
|
}, $class; |
2974
|
|
|
|
|
|
|
} |
2975
|
|
|
|
|
|
|
|
2976
|
|
|
|
|
|
|
sub ID { |
2977
|
|
|
|
|
|
|
my ($self) = @_; |
2978
|
|
|
|
|
|
|
return $self->{_ID}; |
2979
|
|
|
|
|
|
|
} |
2980
|
|
|
|
|
|
|
|
2981
|
|
|
|
|
|
|
sub path { |
2982
|
|
|
|
|
|
|
my ($self) = @_; |
2983
|
|
|
|
|
|
|
return $self->{_path}; |
2984
|
|
|
|
|
|
|
} |
2985
|
|
|
|
|
|
|
|
2986
|
|
|
|
|
|
|
# Send the ResourceProperties to a file |
2987
|
|
|
|
|
|
|
sub toFile { |
2988
|
|
|
|
|
|
|
my $class = shift; |
2989
|
|
|
|
|
|
|
|
2990
|
|
|
|
|
|
|
my $filename = |
2991
|
|
|
|
|
|
|
ref($class) |
2992
|
|
|
|
|
|
|
? $class->{_path} |
2993
|
|
|
|
|
|
|
: $WSRF::Constants::Data . $class; |
2994
|
|
|
|
|
|
|
|
2995
|
|
|
|
|
|
|
# open FILE, ">$filename" or die SOAP::Fault->faultcode("Container Failure") |
2996
|
|
|
|
|
|
|
# ->faultstring("Container Failure: Could open file"); |
2997
|
|
|
|
|
|
|
|
2998
|
|
|
|
|
|
|
# print ">>>>AFTER>>>>\n".WSRF::WSRP::xmlizeProperties()."\n<<<<<<<<<<<<\n\n"; |
2999
|
|
|
|
|
|
|
|
3000
|
|
|
|
|
|
|
# print FILE WSRF::WSRP::xmlizeProperties(); |
3001
|
|
|
|
|
|
|
|
3002
|
|
|
|
|
|
|
# close FILE or die SOAP::Fault->faultcode("Container Failure") |
3003
|
|
|
|
|
|
|
# ->faultstring("Container Failure: Could close file"); |
3004
|
|
|
|
|
|
|
# my $safe = new Safe; |
3005
|
|
|
|
|
|
|
# $safe->permit(qw(:default require)); |
3006
|
|
|
|
|
|
|
# local $Storable::Eval = sub { $safe->reval($_[0]) }; |
3007
|
|
|
|
|
|
|
# local $Storable::Deparse = 1; |
3008
|
|
|
|
|
|
|
|
3009
|
|
|
|
|
|
|
my %tmpPrivate = (%WSRF::WSRP::Private); |
3010
|
|
|
|
|
|
|
|
3011
|
|
|
|
|
|
|
#should use map? |
3012
|
|
|
|
|
|
|
foreach my $key ( keys %tmpPrivate ) { |
3013
|
|
|
|
|
|
|
if ( ref( $tmpPrivate{$key} ) eq "CODE" ) { |
3014
|
|
|
|
|
|
|
delete $tmpPrivate{$key}; |
3015
|
|
|
|
|
|
|
} |
3016
|
|
|
|
|
|
|
} |
3017
|
|
|
|
|
|
|
|
3018
|
|
|
|
|
|
|
#take a copy of the ResourceProperties to copy to file |
3019
|
|
|
|
|
|
|
my %tmphash = (%WSRF::WSRP::ResourceProperties); |
3020
|
|
|
|
|
|
|
foreach my $key ( keys %tmphash ) { |
3021
|
|
|
|
|
|
|
if ( ref( $tmphash{$key} ) eq "CODE" ) { |
3022
|
|
|
|
|
|
|
delete $tmphash{$key}; |
3023
|
|
|
|
|
|
|
} |
3024
|
|
|
|
|
|
|
} |
3025
|
|
|
|
|
|
|
|
3026
|
|
|
|
|
|
|
my %tmpStore = ( Properties => \%tmphash, Private => \%tmpPrivate ); |
3027
|
|
|
|
|
|
|
|
3028
|
|
|
|
|
|
|
local $Storable::forgive_me = "TRUE"; |
3029
|
|
|
|
|
|
|
lock_store \%tmpStore, $filename; |
3030
|
|
|
|
|
|
|
|
3031
|
|
|
|
|
|
|
return; |
3032
|
|
|
|
|
|
|
} |
3033
|
|
|
|
|
|
|
|
3034
|
|
|
|
|
|
|
sub unlock { |
3035
|
|
|
|
|
|
|
my ($self) = @_; |
3036
|
|
|
|
|
|
|
my $Lock = $self->{_lock}; |
3037
|
|
|
|
|
|
|
$Lock->DESTROY(); |
3038
|
|
|
|
|
|
|
} |
3039
|
|
|
|
|
|
|
|
3040
|
|
|
|
|
|
|
#=============================================================================== |
3041
|
|
|
|
|
|
|
# header function creates a SOAP::Header that should be included |
3042
|
|
|
|
|
|
|
# in the response to the client. Handles the WS-Address stuff. |
3043
|
|
|
|
|
|
|
# Takes the original envelope and creates a Header from it - |
3044
|
|
|
|
|
|
|
# the second paramter will be stuffed into the Header so must |
3045
|
|
|
|
|
|
|
# be XML |
3046
|
|
|
|
|
|
|
# |
3047
|
|
|
|
|
|
|
# BUG This should be better automated - probably in the SOAP serializer, |
3048
|
|
|
|
|
|
|
# not sure how because we need to remember the MessageID |
3049
|
|
|
|
|
|
|
package WSRF::Header; |
3050
|
|
|
|
|
|
|
|
3051
|
|
|
|
|
|
|
=pod |
3052
|
|
|
|
|
|
|
|
3053
|
|
|
|
|
|
|
=head1 WSRF::Header |
3054
|
|
|
|
|
|
|
|
3055
|
|
|
|
|
|
|
WSRF::Header provides one helper routine B |
3056
|
|
|
|
|
|
|
|
3057
|
|
|
|
|
|
|
=head2 METHODS |
3058
|
|
|
|
|
|
|
|
3059
|
|
|
|
|
|
|
=over |
3060
|
|
|
|
|
|
|
|
3061
|
|
|
|
|
|
|
=item header |
3062
|
|
|
|
|
|
|
|
3063
|
|
|
|
|
|
|
This subroutine takes a WSRF::SOM envelope and creates the appropriate |
3064
|
|
|
|
|
|
|
SOAP Headers for the response including the required WS-Addressing SOAP |
3065
|
|
|
|
|
|
|
headers. |
3066
|
|
|
|
|
|
|
|
3067
|
|
|
|
|
|
|
|
3068
|
|
|
|
|
|
|
sub foo { |
3069
|
|
|
|
|
|
|
my $envelope = pop @_; |
3070
|
|
|
|
|
|
|
|
3071
|
|
|
|
|
|
|
return WSRF::Header::header($envelope); |
3072
|
|
|
|
|
|
|
} |
3073
|
|
|
|
|
|
|
|
3074
|
|
|
|
|
|
|
=back |
3075
|
|
|
|
|
|
|
|
3076
|
|
|
|
|
|
|
=cut |
3077
|
|
|
|
|
|
|
|
3078
|
|
|
|
|
|
|
sub header { |
3079
|
|
|
|
|
|
|
my ( $envelope, $anythingelse ) = @_; |
3080
|
|
|
|
|
|
|
|
3081
|
|
|
|
|
|
|
#To create the wsa:Action we must find the operation name |
3082
|
|
|
|
|
|
|
#and its namespace |
3083
|
|
|
|
|
|
|
my $data = $envelope->match('/Envelope/Body/[1]')->dataof; |
3084
|
|
|
|
|
|
|
my $method = $data->name; |
3085
|
|
|
|
|
|
|
my $uri = $data->uri; |
3086
|
|
|
|
|
|
|
my $Action = $uri . "/" . $method . "Response"; |
3087
|
|
|
|
|
|
|
my $myHeader = "" . $Action . ""; |
3088
|
|
|
|
|
|
|
|
3089
|
|
|
|
|
|
|
#We only use "anonoymous" for wsa:To |
3090
|
|
|
|
|
|
|
$myHeader .= "$WSRF::Constants::WSA_ANON"; |
3091
|
|
|
|
|
|
|
|
3092
|
|
|
|
|
|
|
#We use our endpoint to create the wsa:From - the endpoint |
3093
|
|
|
|
|
|
|
#is an ENV variable |
3094
|
|
|
|
|
|
|
if ( $envelope->match("/Envelope/Header/{$WSRF::Constants::WSA}To") ) { |
3095
|
|
|
|
|
|
|
my $from = |
3096
|
|
|
|
|
|
|
$envelope->valueof("/Envelope/Header/{$WSRF::Constants::WSA}To"); |
3097
|
|
|
|
|
|
|
$myHeader .= |
3098
|
|
|
|
|
|
|
"$from"; |
3099
|
|
|
|
|
|
|
} |
3100
|
|
|
|
|
|
|
|
3101
|
|
|
|
|
|
|
$myHeader .= |
3102
|
|
|
|
|
|
|
"" |
3103
|
|
|
|
|
|
|
. WSRF::WS_Address::MessageID() |
3104
|
|
|
|
|
|
|
. ""; |
3105
|
|
|
|
|
|
|
|
3106
|
|
|
|
|
|
|
#check for wsa:MessageID in envelope - if it is set use it to |
3107
|
|
|
|
|
|
|
#create a wsa:RelatesTo element |
3108
|
|
|
|
|
|
|
my $messageID = $envelope->headerof("//{$WSRF::Constants::WSA}MessageID"); |
3109
|
|
|
|
|
|
|
if ( defined $messageID ) { |
3110
|
|
|
|
|
|
|
$messageID = |
3111
|
|
|
|
|
|
|
$envelope->headerof("//{$WSRF::Constants::WSA}MessageID")->value; |
3112
|
|
|
|
|
|
|
$myHeader .= |
3113
|
|
|
|
|
|
|
"" |
3114
|
|
|
|
|
|
|
. $messageID |
3115
|
|
|
|
|
|
|
. ""; |
3116
|
|
|
|
|
|
|
} |
3117
|
|
|
|
|
|
|
|
3118
|
|
|
|
|
|
|
#append anything else the user has given us |
3119
|
|
|
|
|
|
|
$myHeader .= $anythingelse; |
3120
|
|
|
|
|
|
|
|
3121
|
|
|
|
|
|
|
#create the SOAP::Header object and return to client |
3122
|
|
|
|
|
|
|
return SOAP::Header->value($myHeader)->type('xml'); |
3123
|
|
|
|
|
|
|
} |
3124
|
|
|
|
|
|
|
|
3125
|
|
|
|
|
|
|
#=============================================================================== |
3126
|
|
|
|
|
|
|
# Base class for the process based WSRF services - a Service can inherit from |
3127
|
|
|
|
|
|
|
# this class to pick up GetResourceProperty, GetMultiResourceProperties and |
3128
|
|
|
|
|
|
|
# SetResourceProperty operations. |
3129
|
|
|
|
|
|
|
|
3130
|
|
|
|
|
|
|
package WSRF::WSRP; |
3131
|
|
|
|
|
|
|
|
3132
|
|
|
|
|
|
|
=pod |
3133
|
|
|
|
|
|
|
|
3134
|
|
|
|
|
|
|
=head1 WSRF::WSRP |
3135
|
|
|
|
|
|
|
|
3136
|
|
|
|
|
|
|
Provides support for WSRF ResourceProperties, the properties of the WS-Resource |
3137
|
|
|
|
|
|
|
are stored in a hash called %WSRF::WSRP::ResourceProperties. |
3138
|
|
|
|
|
|
|
|
3139
|
|
|
|
|
|
|
=head2 METHODS |
3140
|
|
|
|
|
|
|
|
3141
|
|
|
|
|
|
|
=over |
3142
|
|
|
|
|
|
|
|
3143
|
|
|
|
|
|
|
=item xmlizeProperties |
3144
|
|
|
|
|
|
|
|
3145
|
|
|
|
|
|
|
=item GetResourcePropertyDocument |
3146
|
|
|
|
|
|
|
|
3147
|
|
|
|
|
|
|
=item GetResourceProperty |
3148
|
|
|
|
|
|
|
|
3149
|
|
|
|
|
|
|
=item GetMultipleResourceProperties |
3150
|
|
|
|
|
|
|
|
3151
|
|
|
|
|
|
|
=item SetResourceProperties |
3152
|
|
|
|
|
|
|
|
3153
|
|
|
|
|
|
|
=item InsertResourceProperties |
3154
|
|
|
|
|
|
|
|
3155
|
|
|
|
|
|
|
=item UpdateResourceProperties |
3156
|
|
|
|
|
|
|
|
3157
|
|
|
|
|
|
|
=item DeleteResourceProperties |
3158
|
|
|
|
|
|
|
|
3159
|
|
|
|
|
|
|
=back |
3160
|
|
|
|
|
|
|
|
3161
|
|
|
|
|
|
|
=cut |
3162
|
|
|
|
|
|
|
|
3163
|
|
|
|
|
|
|
use vars qw(@ISA); |
3164
|
|
|
|
|
|
|
|
3165
|
|
|
|
|
|
|
# we inherit this to gain access to the envelope - see SOAP::Lite |
3166
|
|
|
|
|
|
|
@ISA = qw(SOAP::Server::Parameters); |
3167
|
|
|
|
|
|
|
|
3168
|
|
|
|
|
|
|
# Hash to store resource properties - we make this effectively |
3169
|
|
|
|
|
|
|
# a globe variable |
3170
|
|
|
|
|
|
|
%WSRF::WSRP::ResourceProperties = (); |
3171
|
|
|
|
|
|
|
|
3172
|
|
|
|
|
|
|
# Hash stores the prefix for the resource property |
3173
|
|
|
|
|
|
|
# eg CurrentTime will use the prefix wsrl, the |
3174
|
|
|
|
|
|
|
# map between tthe prefix and the namespace is |
3175
|
|
|
|
|
|
|
# elsewhere |
3176
|
|
|
|
|
|
|
%WSRF::WSRP::PropertyNamespaceMap = (); |
3177
|
|
|
|
|
|
|
|
3178
|
|
|
|
|
|
|
# Hash that maps a property and the fuction that |
3179
|
|
|
|
|
|
|
# should be called when aan attempt is made to |
3180
|
|
|
|
|
|
|
# insert that property. Simple properties are |
3181
|
|
|
|
|
|
|
# handled by default. |
3182
|
|
|
|
|
|
|
%WSRF::WSRP::InsertMap = (); |
3183
|
|
|
|
|
|
|
|
3184
|
|
|
|
|
|
|
# Hash that maps property to function that should |
3185
|
|
|
|
|
|
|
# be used to delete it - simple properties are |
3186
|
|
|
|
|
|
|
# handled by default |
3187
|
|
|
|
|
|
|
%WSRF::WSRP::DeleteMap = (); |
3188
|
|
|
|
|
|
|
|
3189
|
|
|
|
|
|
|
# Hash to define which properties can be "nil" - by |
3190
|
|
|
|
|
|
|
# default properties can not be nil. |
3191
|
|
|
|
|
|
|
%WSRF::WSRP::Nillable = (); |
3192
|
|
|
|
|
|
|
|
3193
|
|
|
|
|
|
|
# Hash to define which properties cannot be Deleted |
3194
|
|
|
|
|
|
|
%WSRF::WSRP::NotDeletable = (); |
3195
|
|
|
|
|
|
|
|
3196
|
|
|
|
|
|
|
# Hash to define which properties cannot be changed |
3197
|
|
|
|
|
|
|
%WSRF::WSRP::NotModifiable = (); |
3198
|
|
|
|
|
|
|
|
3199
|
|
|
|
|
|
|
# Hash to define which properties cannot be inserted |
3200
|
|
|
|
|
|
|
%WSRF::WSRP::NotInsert = (); |
3201
|
|
|
|
|
|
|
|
3202
|
|
|
|
|
|
|
# serach for a resource property - this is used by getResourceProperty |
3203
|
|
|
|
|
|
|
# and getMultipleResourceProperties. Takes the ID of the resource |
3204
|
|
|
|
|
|
|
# and the name of the rsource. |
3205
|
|
|
|
|
|
|
# |
3206
|
|
|
|
|
|
|
# BUG - we do not handle namespaces of property!! |
3207
|
|
|
|
|
|
|
sub searchResourceProperty { |
3208
|
|
|
|
|
|
|
my $longsearch = shift @_; |
3209
|
|
|
|
|
|
|
|
3210
|
|
|
|
|
|
|
#dump the namespace of property |
3211
|
|
|
|
|
|
|
my ( $junk, $search ); |
3212
|
|
|
|
|
|
|
if ( $longsearch =~ m/:/ ) { |
3213
|
|
|
|
|
|
|
( $junk, $search ) = split /:/, $longsearch; |
3214
|
|
|
|
|
|
|
} else { |
3215
|
|
|
|
|
|
|
$search = $longsearch; |
3216
|
|
|
|
|
|
|
} |
3217
|
|
|
|
|
|
|
|
3218
|
|
|
|
|
|
|
#default result!! |
3219
|
|
|
|
|
|
|
my $ans = ""; |
3220
|
|
|
|
|
|
|
|
3221
|
|
|
|
|
|
|
#print "Printing keys\n"; |
3222
|
|
|
|
|
|
|
#foreach my $key ( keys %WSRF::WSRP::ResourceProperties) |
3223
|
|
|
|
|
|
|
#{ |
3224
|
|
|
|
|
|
|
# print " key= <$key>\n"; |
3225
|
|
|
|
|
|
|
#} |
3226
|
|
|
|
|
|
|
|
3227
|
|
|
|
|
|
|
#Check Resource property exists, if it does it can either |
3228
|
|
|
|
|
|
|
#be a simple scalar, an array or a function. |
3229
|
|
|
|
|
|
|
if ( defined( $WSRF::WSRP::ResourceProperties{$search} ) ) { |
3230
|
|
|
|
|
|
|
|
3231
|
|
|
|
|
|
|
#get type of property |
3232
|
|
|
|
|
|
|
my $type = ref( $WSRF::WSRP::ResourceProperties{$search} ); |
3233
|
|
|
|
|
|
|
if ( $type eq "" ) # if scalar |
3234
|
|
|
|
|
|
|
{ |
3235
|
|
|
|
|
|
|
|
3236
|
|
|
|
|
|
|
#check if property set |
3237
|
|
|
|
|
|
|
if ( $WSRF::WSRP::ResourceProperties{$search} ne "" ) { |
3238
|
|
|
|
|
|
|
$ans .= "<" |
3239
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} |
3240
|
|
|
|
|
|
|
. ":$search "; |
3241
|
|
|
|
|
|
|
|
3242
|
|
|
|
|
|
|
#do we need to add a namespace for this property |
3243
|
|
|
|
|
|
|
my $ns = |
3244
|
|
|
|
|
|
|
defined( |
3245
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{$search}{namespace} ) |
3246
|
|
|
|
|
|
|
? " xmlns:" |
3247
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} . "=\"" |
3248
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{namespace} |
3249
|
|
|
|
|
|
|
. "\">" |
3250
|
|
|
|
|
|
|
: ">"; |
3251
|
|
|
|
|
|
|
$ans .= $ns |
3252
|
|
|
|
|
|
|
. $WSRF::WSRP::ResourceProperties{$search} . "" |
3253
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} |
3254
|
|
|
|
|
|
|
. ":$search>"; |
3255
|
|
|
|
|
|
|
} |
3256
|
|
|
|
|
|
|
|
3257
|
|
|
|
|
|
|
#property NOT set - is it nillable? |
3258
|
|
|
|
|
|
|
elsif ( $WSRF::WSRP::ResourceProperties{$search} eq "" |
3259
|
|
|
|
|
|
|
&& defined( $WSRF::WSRP::Nillable{$search} ) ) |
3260
|
|
|
|
|
|
|
{ |
3261
|
|
|
|
|
|
|
$ans .= "<" |
3262
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} |
3263
|
|
|
|
|
|
|
. ":$search"; |
3264
|
|
|
|
|
|
|
my $ns = |
3265
|
|
|
|
|
|
|
defined( |
3266
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{$search}{namespace} ) |
3267
|
|
|
|
|
|
|
? " xmlns:" |
3268
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} . "=\"" |
3269
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{namespace} |
3270
|
|
|
|
|
|
|
. "\"" |
3271
|
|
|
|
|
|
|
: " "; |
3272
|
|
|
|
|
|
|
$ans .= $ns . " xsi:nil=\"true\"/>"; |
3273
|
|
|
|
|
|
|
} |
3274
|
|
|
|
|
|
|
} |
3275
|
|
|
|
|
|
|
|
3276
|
|
|
|
|
|
|
#property is array of things |
3277
|
|
|
|
|
|
|
elsif ( $type eq "ARRAY" ) { |
3278
|
|
|
|
|
|
|
|
3279
|
|
|
|
|
|
|
#check array is not empty - and property is nillable |
3280
|
|
|
|
|
|
|
if ( !@{ $WSRF::WSRP::ResourceProperties{$search} } |
3281
|
|
|
|
|
|
|
&& defined( $WSRF::WSRP::Nillable{$search} ) ) |
3282
|
|
|
|
|
|
|
{ |
3283
|
|
|
|
|
|
|
$ans .= "<" |
3284
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} |
3285
|
|
|
|
|
|
|
. ":$search"; |
3286
|
|
|
|
|
|
|
my $ns = |
3287
|
|
|
|
|
|
|
defined( |
3288
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{$search}{namespace} ) |
3289
|
|
|
|
|
|
|
? " xmlns:" |
3290
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} . "=\"" |
3291
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{namespace} |
3292
|
|
|
|
|
|
|
. "\"" |
3293
|
|
|
|
|
|
|
: " "; |
3294
|
|
|
|
|
|
|
$ans .= $ns . " xsi:nil=\"true\"/>"; |
3295
|
|
|
|
|
|
|
} |
3296
|
|
|
|
|
|
|
|
3297
|
|
|
|
|
|
|
#loop over array building result |
3298
|
|
|
|
|
|
|
else { |
3299
|
|
|
|
|
|
|
foreach |
3300
|
|
|
|
|
|
|
my $entry ( @{ $WSRF::WSRP::ResourceProperties{$search} } ) |
3301
|
|
|
|
|
|
|
{ |
3302
|
|
|
|
|
|
|
$ans .= "<" |
3303
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} |
3304
|
|
|
|
|
|
|
. ":$search"; |
3305
|
|
|
|
|
|
|
|
3306
|
|
|
|
|
|
|
#do we need to add a namespace for this property |
3307
|
|
|
|
|
|
|
my $ns = |
3308
|
|
|
|
|
|
|
defined( $WSRF::WSRP::PropertyNamespaceMap->{$search} |
3309
|
|
|
|
|
|
|
{namespace} ) |
3310
|
|
|
|
|
|
|
? " xmlns:" |
3311
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} |
3312
|
|
|
|
|
|
|
. "=\"" |
3313
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{namespace} |
3314
|
|
|
|
|
|
|
. "\">" |
3315
|
|
|
|
|
|
|
: ">"; |
3316
|
|
|
|
|
|
|
$ans .= |
3317
|
|
|
|
|
|
|
$ns . $entry . "" |
3318
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} |
3319
|
|
|
|
|
|
|
. ":$search>"; |
3320
|
|
|
|
|
|
|
} |
3321
|
|
|
|
|
|
|
} |
3322
|
|
|
|
|
|
|
} |
3323
|
|
|
|
|
|
|
|
3324
|
|
|
|
|
|
|
#property is a subroutine - call it to get result |
3325
|
|
|
|
|
|
|
#example of this is CurrentTime |
3326
|
|
|
|
|
|
|
elsif ( $type eq "CODE" ) { |
3327
|
|
|
|
|
|
|
$ans .= $WSRF::WSRP::ResourceProperties{$search}->(); |
3328
|
|
|
|
|
|
|
} |
3329
|
|
|
|
|
|
|
|
3330
|
|
|
|
|
|
|
#Some type we do not understand yet eg. Hash - attempt to serialize it anyway |
3331
|
|
|
|
|
|
|
else { |
3332
|
|
|
|
|
|
|
my $serializer = WSRF::SimpleSerializer->new(); |
3333
|
|
|
|
|
|
|
$ans .= "<" |
3334
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} |
3335
|
|
|
|
|
|
|
. ":$search"; |
3336
|
|
|
|
|
|
|
|
3337
|
|
|
|
|
|
|
#do we need to add a namespace for this property |
3338
|
|
|
|
|
|
|
my $ns = |
3339
|
|
|
|
|
|
|
defined( $WSRF::WSRP::PropertyNamespaceMap->{$search}{namespace} ) |
3340
|
|
|
|
|
|
|
? " xmlns:" |
3341
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} . "=\"" |
3342
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{namespace} . "\">" |
3343
|
|
|
|
|
|
|
: ">"; |
3344
|
|
|
|
|
|
|
|
3345
|
|
|
|
|
|
|
$ans .= $ns |
3346
|
|
|
|
|
|
|
. $serializer->serialize( |
3347
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{$search} ) |
3348
|
|
|
|
|
|
|
. "" |
3349
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} |
3350
|
|
|
|
|
|
|
. ":$search>"; |
3351
|
|
|
|
|
|
|
|
3352
|
|
|
|
|
|
|
# die SOAP::Fault->faultcode("WSRF::Lite Failure") |
3353
|
|
|
|
|
|
|
# ->faultstring("Could not understand type: $type"); |
3354
|
|
|
|
|
|
|
} |
3355
|
|
|
|
|
|
|
|
3356
|
|
|
|
|
|
|
} |
3357
|
|
|
|
|
|
|
|
3358
|
|
|
|
|
|
|
return $ans; |
3359
|
|
|
|
|
|
|
} |
3360
|
|
|
|
|
|
|
|
3361
|
|
|
|
|
|
|
# This creates XML with all the ResourceProperties in it - we can then |
3362
|
|
|
|
|
|
|
# use the XPath query from queryResourceProperty on it. |
3363
|
|
|
|
|
|
|
# BUG (FIXED(?) But we have not written queryResourceProperty yet - its a |
3364
|
|
|
|
|
|
|
# bad idea anyway so lets not worry about it. |
3365
|
|
|
|
|
|
|
# |
3366
|
|
|
|
|
|
|
sub xmlizeProperties { |
3367
|
|
|
|
|
|
|
|
3368
|
|
|
|
|
|
|
#my $ans = ""; |
3369
|
|
|
|
|
|
|
my $ans = |
3370
|
|
|
|
|
|
|
"
|
3371
|
|
|
|
|
|
|
. " xmlns:wsrp=\"$WSRF::Constants::WSRP\" " |
3372
|
|
|
|
|
|
|
. " xmlns:wsrl=\"$WSRF::Constants::WSRL\" " |
3373
|
|
|
|
|
|
|
. " xmlns:wssg=\"$WSRF::Constants::WSSG\" " |
3374
|
|
|
|
|
|
|
. " xmlns:wsa=\"$WSRF::Constants::WSA\" " |
3375
|
|
|
|
|
|
|
. " xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\" " |
3376
|
|
|
|
|
|
|
. " xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\">"; |
3377
|
|
|
|
|
|
|
|
3378
|
|
|
|
|
|
|
foreach my $key ( keys %WSRF::WSRP::ResourceProperties ) { |
3379
|
|
|
|
|
|
|
$ans .= searchResourceProperty($key); |
3380
|
|
|
|
|
|
|
} |
3381
|
|
|
|
|
|
|
|
3382
|
|
|
|
|
|
|
$ans .= ""; |
3383
|
|
|
|
|
|
|
|
3384
|
|
|
|
|
|
|
return $ans; |
3385
|
|
|
|
|
|
|
} |
3386
|
|
|
|
|
|
|
|
3387
|
|
|
|
|
|
|
sub GetResourcePropertyDocument { |
3388
|
|
|
|
|
|
|
my $envelope = pop @_; |
3389
|
|
|
|
|
|
|
my $xml = xmlizeProperties(); |
3390
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
3391
|
|
|
|
|
|
|
SOAP::Data->value($xml)->type('xml'); |
3392
|
|
|
|
|
|
|
} |
3393
|
|
|
|
|
|
|
|
3394
|
|
|
|
|
|
|
# delete property |
3395
|
|
|
|
|
|
|
# BUG we do not handle namespaces |
3396
|
|
|
|
|
|
|
my $mydelete = sub { |
3397
|
|
|
|
|
|
|
my ($name) = @_; |
3398
|
|
|
|
|
|
|
|
3399
|
|
|
|
|
|
|
#strip namespace |
3400
|
|
|
|
|
|
|
$name =~ s/\w*://o; |
3401
|
|
|
|
|
|
|
|
3402
|
|
|
|
|
|
|
# #check for user defined delete function for this property |
3403
|
|
|
|
|
|
|
if ( defined( $WSRF::WSRP::DeleteMap{$name} ) ) { |
3404
|
|
|
|
|
|
|
$WSRF::WSRP::DeleteMap{$name}->(); |
3405
|
|
|
|
|
|
|
return; |
3406
|
|
|
|
|
|
|
} |
3407
|
|
|
|
|
|
|
|
3408
|
|
|
|
|
|
|
#check we are allowed to delete this function |
3409
|
|
|
|
|
|
|
# if( defined( $WSRF::WSRP::NotDeletable{$name} ) ) |
3410
|
|
|
|
|
|
|
# { |
3411
|
|
|
|
|
|
|
# die SOAP::Fault->faultcode("setResourceproperty: Delete Failure") |
3412
|
|
|
|
|
|
|
# ->faultstring("Could not delete $name"); |
3413
|
|
|
|
|
|
|
# } |
3414
|
|
|
|
|
|
|
|
3415
|
|
|
|
|
|
|
#check property exists |
3416
|
|
|
|
|
|
|
if ( defined( $WSRF::WSRP::ResourceProperties{$name} ) ) { |
3417
|
|
|
|
|
|
|
|
3418
|
|
|
|
|
|
|
#check type either array or scalar |
3419
|
|
|
|
|
|
|
my $type = ref( $WSRF::WSRP::ResourceProperties{$name} ); |
3420
|
|
|
|
|
|
|
if ( $type eq "" ) #scalar |
3421
|
|
|
|
|
|
|
{ |
3422
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{$name} = ""; |
3423
|
|
|
|
|
|
|
} elsif ( $type eq "ARRAY" ) # array |
3424
|
|
|
|
|
|
|
{ |
3425
|
|
|
|
|
|
|
|
3426
|
|
|
|
|
|
|
#set contents to nothing |
3427
|
|
|
|
|
|
|
@{ $WSRF::WSRP::ResourceProperties{$name} } = (); |
3428
|
|
|
|
|
|
|
} else { |
3429
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("setResourceproperty: Delete Failure") |
3430
|
|
|
|
|
|
|
->faultstring("Could not delete $name"); |
3431
|
|
|
|
|
|
|
} |
3432
|
|
|
|
|
|
|
} else { |
3433
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("setResourceproperty: Delete Failure") |
3434
|
|
|
|
|
|
|
->faultstring("No ResourceProperty: $name"); |
3435
|
|
|
|
|
|
|
} |
3436
|
|
|
|
|
|
|
return; |
3437
|
|
|
|
|
|
|
}; |
3438
|
|
|
|
|
|
|
|
3439
|
|
|
|
|
|
|
# insert property - this function is used by the Insert and Update |
3440
|
|
|
|
|
|
|
# in the SetResourceProperty operation. This operation takes |
3441
|
|
|
|
|
|
|
# the ID of the resource and a SOAP::SOM object that has been set |
3442
|
|
|
|
|
|
|
# at the property that should be inserted |
3443
|
|
|
|
|
|
|
# Only one property can be inserted at a time using the function - |
3444
|
|
|
|
|
|
|
# SetResourceProperty of course loops over it |
3445
|
|
|
|
|
|
|
my $insert = sub { |
3446
|
|
|
|
|
|
|
my ($b) = @_; |
3447
|
|
|
|
|
|
|
|
3448
|
|
|
|
|
|
|
#get the name of the property |
3449
|
|
|
|
|
|
|
my $name = $b->dataof()->name; |
3450
|
|
|
|
|
|
|
|
3451
|
|
|
|
|
|
|
# #check there is no user defined function |
3452
|
|
|
|
|
|
|
# #for inserting this property |
3453
|
|
|
|
|
|
|
if ( defined( $WSRF::WSRP::InsertMap{$name} ) ) { |
3454
|
|
|
|
|
|
|
$WSRF::WSRP::InsertMap{$name}->($b); |
3455
|
|
|
|
|
|
|
return; |
3456
|
|
|
|
|
|
|
} |
3457
|
|
|
|
|
|
|
|
3458
|
|
|
|
|
|
|
#check this property can be changed |
3459
|
|
|
|
|
|
|
# if( defined( $WSRF::WSRP::NotModifiable{$name} )) |
3460
|
|
|
|
|
|
|
# { |
3461
|
|
|
|
|
|
|
# die SOAP::Fault->faultcode("setResourceproperty: Insert Failure") |
3462
|
|
|
|
|
|
|
# ->faultstring("Could not insert $name"); |
3463
|
|
|
|
|
|
|
# } |
3464
|
|
|
|
|
|
|
|
3465
|
|
|
|
|
|
|
#get the value of the property |
3466
|
|
|
|
|
|
|
my $value = $b->dataof()->value; |
3467
|
|
|
|
|
|
|
|
3468
|
|
|
|
|
|
|
#check the property actually exists |
3469
|
|
|
|
|
|
|
if ( defined( $WSRF::WSRP::ResourceProperties{$name} ) ) { |
3470
|
|
|
|
|
|
|
|
3471
|
|
|
|
|
|
|
#check the type of the property (scalar|array) |
3472
|
|
|
|
|
|
|
my $type = ref( $WSRF::WSRP::ResourceProperties{$name} ); |
3473
|
|
|
|
|
|
|
if ( $type eq "" ) #scalar |
3474
|
|
|
|
|
|
|
{ |
3475
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{$name} = $value; |
3476
|
|
|
|
|
|
|
} elsif ( $type eq "ARRAY" ) #array |
3477
|
|
|
|
|
|
|
{ |
3478
|
|
|
|
|
|
|
|
3479
|
|
|
|
|
|
|
#add property to array |
3480
|
|
|
|
|
|
|
push( @{ $WSRF::WSRP::ResourceProperties{$name} }, $value ); |
3481
|
|
|
|
|
|
|
} else #perhaps subroutine? |
3482
|
|
|
|
|
|
|
{ |
3483
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("setResourceproperty: Insert Failure") |
3484
|
|
|
|
|
|
|
->faultstring("Could not insert $name"); |
3485
|
|
|
|
|
|
|
} |
3486
|
|
|
|
|
|
|
} else { |
3487
|
|
|
|
|
|
|
die SOAP::Fault->faultcode( |
3488
|
|
|
|
|
|
|
"setResourceproperty: No such ResourceProperty") |
3489
|
|
|
|
|
|
|
->faultstring("$name is not a ResourceProperty of this WS-Resource"); |
3490
|
|
|
|
|
|
|
} |
3491
|
|
|
|
|
|
|
return; |
3492
|
|
|
|
|
|
|
}; |
3493
|
|
|
|
|
|
|
|
3494
|
|
|
|
|
|
|
# we provide an init method in case the service writer does bother - this |
3495
|
|
|
|
|
|
|
# will be called whenever the WS-Resource is created |
3496
|
|
|
|
|
|
|
sub init { return; } |
3497
|
|
|
|
|
|
|
|
3498
|
|
|
|
|
|
|
# wsrp GetResourceProperty |
3499
|
|
|
|
|
|
|
sub GetResourceProperty { |
3500
|
|
|
|
|
|
|
my $envelope = pop @_; |
3501
|
|
|
|
|
|
|
|
3502
|
|
|
|
|
|
|
#print "XML>>>\n".xmlizeProperties()."\n<<
|
3503
|
|
|
|
|
|
|
|
3504
|
|
|
|
|
|
|
#search through envelope to the GetResourceProperty bit |
3505
|
|
|
|
|
|
|
#and get the resource property name |
3506
|
|
|
|
|
|
|
my $search = $envelope->valueof('//GetResourceProperty/'); |
3507
|
|
|
|
|
|
|
|
3508
|
|
|
|
|
|
|
#print "GetResourceProperty = $search\n"; |
3509
|
|
|
|
|
|
|
my $ans = searchResourceProperty($search); |
3510
|
|
|
|
|
|
|
|
3511
|
|
|
|
|
|
|
#print "GetResourceProperty Ans= $ans\n"; |
3512
|
|
|
|
|
|
|
|
3513
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
3514
|
|
|
|
|
|
|
SOAP::Data->value($ans)->type('xml'); |
3515
|
|
|
|
|
|
|
} |
3516
|
|
|
|
|
|
|
|
3517
|
|
|
|
|
|
|
# wsrp GetMultipleResourceProperties |
3518
|
|
|
|
|
|
|
sub GetMultipleResourceProperties { |
3519
|
|
|
|
|
|
|
my $envelope = pop @_; |
3520
|
|
|
|
|
|
|
|
3521
|
|
|
|
|
|
|
my $ans = ""; #we will just cat the answers together |
3522
|
|
|
|
|
|
|
|
3523
|
|
|
|
|
|
|
# print "XML>>>\n".$xmlizeProperties->($ID)."\n<<
|
3524
|
|
|
|
|
|
|
|
3525
|
|
|
|
|
|
|
#loop over each ResourceProperty request |
3526
|
|
|
|
|
|
|
foreach my $search ( $envelope->valueof('//ResourceProperty/') ) { |
3527
|
|
|
|
|
|
|
$ans .= searchResourceProperty($search); |
3528
|
|
|
|
|
|
|
} |
3529
|
|
|
|
|
|
|
|
3530
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
3531
|
|
|
|
|
|
|
SOAP::Data->value($ans)->type('xml'); |
3532
|
|
|
|
|
|
|
|
3533
|
|
|
|
|
|
|
} |
3534
|
|
|
|
|
|
|
|
3535
|
|
|
|
|
|
|
# wsrp SetResourceProperties - the client can request that properties |
3536
|
|
|
|
|
|
|
# are inserted, updated and deleted in the one operation. The commands |
3537
|
|
|
|
|
|
|
# must happen in the order they come in the request, all stop when we |
3538
|
|
|
|
|
|
|
# hit a problem |
3539
|
|
|
|
|
|
|
sub SetResourceProperties { |
3540
|
|
|
|
|
|
|
|
3541
|
|
|
|
|
|
|
#get the envelope |
3542
|
|
|
|
|
|
|
my $som = pop @_; |
3543
|
|
|
|
|
|
|
|
3544
|
|
|
|
|
|
|
#the base point of all our searchs. |
3545
|
|
|
|
|
|
|
my $base = "//SetResourceProperties"; |
3546
|
|
|
|
|
|
|
|
3547
|
|
|
|
|
|
|
#find the start of commands - should think |
3548
|
|
|
|
|
|
|
#of this as an array of arries - that is why we have [$jj]/[$kk] |
3549
|
|
|
|
|
|
|
if ( $som->match($base) ) { |
3550
|
|
|
|
|
|
|
my $jj = 1; |
3551
|
|
|
|
|
|
|
|
3552
|
|
|
|
|
|
|
#now we loop over commands - $jj records our postion |
3553
|
|
|
|
|
|
|
while ( $som->dataof("$base/[$jj]") ) { |
3554
|
|
|
|
|
|
|
|
3555
|
|
|
|
|
|
|
#get the command name |
3556
|
|
|
|
|
|
|
my $Function = $som->dataof("$base/[$jj]")->name(); |
3557
|
|
|
|
|
|
|
if ( $Function eq "Insert" ) #an Insert |
3558
|
|
|
|
|
|
|
{ |
3559
|
|
|
|
|
|
|
my $kk = 1; |
3560
|
|
|
|
|
|
|
|
3561
|
|
|
|
|
|
|
#loop over the things that have to be inserted |
3562
|
|
|
|
|
|
|
while ( $som->match("$base/[$jj]/[$kk]") ) { |
3563
|
|
|
|
|
|
|
|
3564
|
|
|
|
|
|
|
#print "Inserting ".$som->dataof("$base/[$jj]/[$kk]")->name()."\n"; |
3565
|
|
|
|
|
|
|
#insert the thing - note we pass a SOM object becasue the |
3566
|
|
|
|
|
|
|
if ( |
3567
|
|
|
|
|
|
|
!defined( |
3568
|
|
|
|
|
|
|
$WSRF::WSRP::NotInsert{ $som->dataof( |
3569
|
|
|
|
|
|
|
"$base/[$jj]/[$kk]")->name() } |
3570
|
|
|
|
|
|
|
) |
3571
|
|
|
|
|
|
|
) |
3572
|
|
|
|
|
|
|
{ |
3573
|
|
|
|
|
|
|
$insert->( $som->match("$base/[$jj]/[$kk]") ); |
3574
|
|
|
|
|
|
|
} #thing could be pretty complex. |
3575
|
|
|
|
|
|
|
|
3576
|
|
|
|
|
|
|
$kk++; |
3577
|
|
|
|
|
|
|
} |
3578
|
|
|
|
|
|
|
} elsif ( $Function eq "Update" ) #an Update |
3579
|
|
|
|
|
|
|
{ |
3580
|
|
|
|
|
|
|
my $kk = 1; |
3581
|
|
|
|
|
|
|
my %tmpHash = (); |
3582
|
|
|
|
|
|
|
|
3583
|
|
|
|
|
|
|
#loop over things to Update - an update is a Delete followed |
3584
|
|
|
|
|
|
|
#by an Insert in a single atomic operation |
3585
|
|
|
|
|
|
|
while ( $som->match("$base/[$jj]/[$kk]") ) { |
3586
|
|
|
|
|
|
|
|
3587
|
|
|
|
|
|
|
#get name of thing we are updating |
3588
|
|
|
|
|
|
|
my $name = $som->dataof("$base/[$jj]/[$kk]")->name(); |
3589
|
|
|
|
|
|
|
|
3590
|
|
|
|
|
|
|
#print "Updating $name\n"; |
3591
|
|
|
|
|
|
|
#check we have not deleted it before else delete before inserting |
3592
|
|
|
|
|
|
|
if ( !defined( $WSRF::WSRP::NotModifiable{$name} ) ) { |
3593
|
|
|
|
|
|
|
if ( !defined( $tmpHash{$name} ) ) { |
3594
|
|
|
|
|
|
|
$mydelete->($name); |
3595
|
|
|
|
|
|
|
$tmpHash{$name} = 1; |
3596
|
|
|
|
|
|
|
} |
3597
|
|
|
|
|
|
|
|
3598
|
|
|
|
|
|
|
#insert value |
3599
|
|
|
|
|
|
|
$insert->( $som->match("$base/[$jj]/[$kk]") ); |
3600
|
|
|
|
|
|
|
} |
3601
|
|
|
|
|
|
|
$kk++; |
3602
|
|
|
|
|
|
|
} |
3603
|
|
|
|
|
|
|
} elsif ( $Function eq "Delete" ) #a Delete |
3604
|
|
|
|
|
|
|
{ |
3605
|
|
|
|
|
|
|
|
3606
|
|
|
|
|
|
|
#the property to delete is actually an attribute |
3607
|
|
|
|
|
|
|
#in the delete element |
3608
|
|
|
|
|
|
|
my $propname = |
3609
|
|
|
|
|
|
|
$som->dataof("$base/[$jj]")->attr->{'resourceProperty'}; |
3610
|
|
|
|
|
|
|
|
3611
|
|
|
|
|
|
|
#print "Delete $propname\n"; |
3612
|
|
|
|
|
|
|
#delete property |
3613
|
|
|
|
|
|
|
if ( !defined( $WSRF::WSRP::NotDeletable{$propname} ) ) { |
3614
|
|
|
|
|
|
|
$mydelete->($propname); |
3615
|
|
|
|
|
|
|
} |
3616
|
|
|
|
|
|
|
} else { #something other than Insert|Update|Delete |
3617
|
|
|
|
|
|
|
die SOAP::Fault->faultcode( |
3618
|
|
|
|
|
|
|
"setResourceproperty: Unkown operation") |
3619
|
|
|
|
|
|
|
->faultstring("$Function not supported - only Insert,Update and Delete are supported" |
3620
|
|
|
|
|
|
|
); |
3621
|
|
|
|
|
|
|
} |
3622
|
|
|
|
|
|
|
$jj++; |
3623
|
|
|
|
|
|
|
} |
3624
|
|
|
|
|
|
|
} |
3625
|
|
|
|
|
|
|
|
3626
|
|
|
|
|
|
|
return WSRF::Header::header($som); |
3627
|
|
|
|
|
|
|
} |
3628
|
|
|
|
|
|
|
|
3629
|
|
|
|
|
|
|
sub InsertResourceProperties { |
3630
|
|
|
|
|
|
|
my $som = pop @_; |
3631
|
|
|
|
|
|
|
my $base = "//InsertResourceProperties"; |
3632
|
|
|
|
|
|
|
if ( $som->match($base) ) { |
3633
|
|
|
|
|
|
|
my $kk = 1; |
3634
|
|
|
|
|
|
|
while ( $som->match("$base/[1]/[$kk]") ) { |
3635
|
|
|
|
|
|
|
my $name = $som->dataof("$base/[1]/[$kk]")->name(); |
3636
|
|
|
|
|
|
|
print "Inserting $name\n"; |
3637
|
|
|
|
|
|
|
|
3638
|
|
|
|
|
|
|
#insert the thing - note we pass a SOM object becasue the |
3639
|
|
|
|
|
|
|
#thing could be pretty complex. |
3640
|
|
|
|
|
|
|
if ( !defined( $WSRF::WSRP::NotInsert{$name} ) ) { |
3641
|
|
|
|
|
|
|
$insert->( $som->match("$base/[1]/[$kk]") ); |
3642
|
|
|
|
|
|
|
} else { |
3643
|
|
|
|
|
|
|
die "InvalidInsertResourcePropertiesRequestContent\n"; |
3644
|
|
|
|
|
|
|
} |
3645
|
|
|
|
|
|
|
$kk++; |
3646
|
|
|
|
|
|
|
} |
3647
|
|
|
|
|
|
|
} |
3648
|
|
|
|
|
|
|
return WSRF::Header::header($som); |
3649
|
|
|
|
|
|
|
} |
3650
|
|
|
|
|
|
|
|
3651
|
|
|
|
|
|
|
sub UpdateResourceProperties { |
3652
|
|
|
|
|
|
|
my $som = pop @_; |
3653
|
|
|
|
|
|
|
my $base = "//UpdateResourceProperties"; |
3654
|
|
|
|
|
|
|
if ( $som->match($base) ) { |
3655
|
|
|
|
|
|
|
my $kk = 1; |
3656
|
|
|
|
|
|
|
my %tmpHash = (); |
3657
|
|
|
|
|
|
|
while ( $som->match("$base/[1]/[$kk]") ) { |
3658
|
|
|
|
|
|
|
|
3659
|
|
|
|
|
|
|
#get name of thing we are updating |
3660
|
|
|
|
|
|
|
my $name = $som->dataof("$base/[1]/[$kk]")->name(); |
3661
|
|
|
|
|
|
|
print "Updating $name\n"; |
3662
|
|
|
|
|
|
|
if ( !defined( $WSRF::WSRP::NotModifiable{$name} ) ) { |
3663
|
|
|
|
|
|
|
|
3664
|
|
|
|
|
|
|
#check we have not deleted it before else delete before inserting |
3665
|
|
|
|
|
|
|
if ( !defined( $tmpHash{$name} ) ) { |
3666
|
|
|
|
|
|
|
$mydelete->($name); |
3667
|
|
|
|
|
|
|
$tmpHash{$name} = 1; |
3668
|
|
|
|
|
|
|
} |
3669
|
|
|
|
|
|
|
|
3670
|
|
|
|
|
|
|
#insert value |
3671
|
|
|
|
|
|
|
$insert->( $som->match("$base/[1]/[$kk]") ); |
3672
|
|
|
|
|
|
|
} else { |
3673
|
|
|
|
|
|
|
die "InvalidUpdateResourcePropertiesRequestContent\n"; |
3674
|
|
|
|
|
|
|
} |
3675
|
|
|
|
|
|
|
$kk++; |
3676
|
|
|
|
|
|
|
} |
3677
|
|
|
|
|
|
|
} |
3678
|
|
|
|
|
|
|
|
3679
|
|
|
|
|
|
|
return WSRF::Header::header($som); |
3680
|
|
|
|
|
|
|
} |
3681
|
|
|
|
|
|
|
|
3682
|
|
|
|
|
|
|
sub DeleteResourceProperties { |
3683
|
|
|
|
|
|
|
my $som = pop @_; |
3684
|
|
|
|
|
|
|
my $base = "//DeleteResourceProperties"; |
3685
|
|
|
|
|
|
|
if ( $som->match($base) ) { |
3686
|
|
|
|
|
|
|
my $kk = 1; |
3687
|
|
|
|
|
|
|
while ( $som->match("$base/[$kk]") ) { |
3688
|
|
|
|
|
|
|
print "Into Loop inner...\n"; |
3689
|
|
|
|
|
|
|
|
3690
|
|
|
|
|
|
|
#the property to delete is actually an attribute |
3691
|
|
|
|
|
|
|
#in the delete element |
3692
|
|
|
|
|
|
|
my $propname = |
3693
|
|
|
|
|
|
|
$som->dataof("$base/[$kk]")->attr->{'ResourceProperty'}; |
3694
|
|
|
|
|
|
|
$propname =~ s/\w*://o; |
3695
|
|
|
|
|
|
|
|
3696
|
|
|
|
|
|
|
#delete property |
3697
|
|
|
|
|
|
|
if ( !defined( $WSRF::WSRP::NotDeletable{$propname} ) ) { |
3698
|
|
|
|
|
|
|
$mydelete->($propname); |
3699
|
|
|
|
|
|
|
} else { |
3700
|
|
|
|
|
|
|
die "InvalidDeleteResourcePropertiesRequestContent\n"; |
3701
|
|
|
|
|
|
|
} |
3702
|
|
|
|
|
|
|
$kk++; |
3703
|
|
|
|
|
|
|
} |
3704
|
|
|
|
|
|
|
} |
3705
|
|
|
|
|
|
|
|
3706
|
|
|
|
|
|
|
return WSRF::Header::header($som); |
3707
|
|
|
|
|
|
|
} |
3708
|
|
|
|
|
|
|
|
3709
|
|
|
|
|
|
|
#=============================================================================== |
3710
|
|
|
|
|
|
|
# The WSRL class, inherits from the WSRF::WSRP class and adds Destroy |
3711
|
|
|
|
|
|
|
# and SetTerminationTime operations. Adds the resource properties |
3712
|
|
|
|
|
|
|
# required wsrl:TerminationTime and wsrl:CurrentTime |
3713
|
|
|
|
|
|
|
# |
3714
|
|
|
|
|
|
|
package WSRF::WSRL; |
3715
|
|
|
|
|
|
|
|
3716
|
|
|
|
|
|
|
=pod |
3717
|
|
|
|
|
|
|
|
3718
|
|
|
|
|
|
|
=head1 WSRF::WSRL |
3719
|
|
|
|
|
|
|
|
3720
|
|
|
|
|
|
|
Provides support for WS-ResourceLifetimes. WS-ResourceLifetime defines |
3721
|
|
|
|
|
|
|
a standard mechanism for controlling the lifetime of a WS-Resource. It |
3722
|
|
|
|
|
|
|
adds the ResourceProperty I to the set of ResourceProerties |
3723
|
|
|
|
|
|
|
of the WS-Resource, the I cannot be changed through the |
3724
|
|
|
|
|
|
|
WS-ResourceProperties - it can only be modified using the WS-ResourceLifetime |
3725
|
|
|
|
|
|
|
B operation. |
3726
|
|
|
|
|
|
|
|
3727
|
|
|
|
|
|
|
=head2 METHODS |
3728
|
|
|
|
|
|
|
|
3729
|
|
|
|
|
|
|
=over |
3730
|
|
|
|
|
|
|
|
3731
|
|
|
|
|
|
|
=item Destroy |
3732
|
|
|
|
|
|
|
|
3733
|
|
|
|
|
|
|
=item SetTerminationTime |
3734
|
|
|
|
|
|
|
|
3735
|
|
|
|
|
|
|
=back |
3736
|
|
|
|
|
|
|
|
3737
|
|
|
|
|
|
|
=cut |
3738
|
|
|
|
|
|
|
|
3739
|
|
|
|
|
|
|
use vars qw(@ISA); |
3740
|
|
|
|
|
|
|
|
3741
|
|
|
|
|
|
|
@ISA = qw(WSRF::WSRP); |
3742
|
|
|
|
|
|
|
|
3743
|
|
|
|
|
|
|
sub init { |
3744
|
|
|
|
|
|
|
my $self = shift @_; |
3745
|
|
|
|
|
|
|
|
3746
|
|
|
|
|
|
|
# Add TerminationTime as a resource property - |
3747
|
|
|
|
|
|
|
# initalise to nothing (ie. set TT to infinity) |
3748
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{'TerminationTime'} = ""; |
3749
|
|
|
|
|
|
|
|
3750
|
|
|
|
|
|
|
# belongs to RsourceLiftetime namespace - defined |
3751
|
|
|
|
|
|
|
# elsewhere to be wsrl |
3752
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{TerminationTime}{prefix} = "wsrl"; |
3753
|
|
|
|
|
|
|
|
3754
|
|
|
|
|
|
|
# the TerminationTime can be nil. |
3755
|
|
|
|
|
|
|
$WSRF::WSRP::Nillable{TerminationTime} = 1; |
3756
|
|
|
|
|
|
|
$WSRF::WSRP::NotModifiable{TerminationTime} = 1; |
3757
|
|
|
|
|
|
|
|
3758
|
|
|
|
|
|
|
# add resource property CurrentTime - in this |
3759
|
|
|
|
|
|
|
# case a subroutine that returns the current |
3760
|
|
|
|
|
|
|
# time in the correct format |
3761
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{'CurrentTime'} = sub { |
3762
|
|
|
|
|
|
|
return "" |
3763
|
|
|
|
|
|
|
. WSRF::Time::ConvertEpochTimeToString() |
3764
|
|
|
|
|
|
|
. ""; |
3765
|
|
|
|
|
|
|
}; |
3766
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{CurrentTime}{prefix} = "wsrl"; |
3767
|
|
|
|
|
|
|
|
3768
|
|
|
|
|
|
|
# By default if a resource property is a subroutine |
3769
|
|
|
|
|
|
|
# then you cannot change it or delete it - however |
3770
|
|
|
|
|
|
|
# for completeness we set the following |
3771
|
|
|
|
|
|
|
$WSRF::WSRP::NotDeletable{CurrentTime} = 1; |
3772
|
|
|
|
|
|
|
$WSRF::WSRP::NotModifiable{CurrentTime} = 1; |
3773
|
|
|
|
|
|
|
$WSRF::WSRP::NotInsert{CurrentTime} = 1; |
3774
|
|
|
|
|
|
|
|
3775
|
|
|
|
|
|
|
$self->SUPER::init(); |
3776
|
|
|
|
|
|
|
|
3777
|
|
|
|
|
|
|
} |
3778
|
|
|
|
|
|
|
|
3779
|
|
|
|
|
|
|
sub Destroy { |
3780
|
|
|
|
|
|
|
|
3781
|
|
|
|
|
|
|
#set alarm to 1, gives us time to return a result |
3782
|
|
|
|
|
|
|
#before we die |
3783
|
|
|
|
|
|
|
alarm(1); |
3784
|
|
|
|
|
|
|
|
3785
|
|
|
|
|
|
|
#return nothing except a SOAP HEADER |
3786
|
|
|
|
|
|
|
return WSRF::Header::header( pop @_ ); |
3787
|
|
|
|
|
|
|
} |
3788
|
|
|
|
|
|
|
|
3789
|
|
|
|
|
|
|
# wsrl SetTerminationTime - if you want to make a max limit your Resource |
3790
|
|
|
|
|
|
|
# you should override this function in your module. |
3791
|
|
|
|
|
|
|
sub SetTerminationTime { |
3792
|
|
|
|
|
|
|
my $envelope = pop @_; |
3793
|
|
|
|
|
|
|
shift @_; #the first paramter is always the class of the object |
3794
|
|
|
|
|
|
|
my $time = shift @_; #the new TerminationTime |
3795
|
|
|
|
|
|
|
|
3796
|
|
|
|
|
|
|
#check for null time - allowed by wsrl, means TT is infinity |
3797
|
|
|
|
|
|
|
if ( $time eq "" ) { |
3798
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{'TerminationTime'} = ""; |
3799
|
|
|
|
|
|
|
|
3800
|
|
|
|
|
|
|
#disable alarm |
3801
|
|
|
|
|
|
|
alarm; |
3802
|
|
|
|
|
|
|
my $ans = |
3803
|
|
|
|
|
|
|
"" |
3804
|
|
|
|
|
|
|
. "" |
3805
|
|
|
|
|
|
|
. WSRF::Time::ConvertEpochTimeToString() |
3806
|
|
|
|
|
|
|
. ""; |
3807
|
|
|
|
|
|
|
|
3808
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
3809
|
|
|
|
|
|
|
SOAP::Data->value($ans)->type('xml'); |
3810
|
|
|
|
|
|
|
} |
3811
|
|
|
|
|
|
|
|
3812
|
|
|
|
|
|
|
#BUG this is handled by WSRF::Time::ConvertStringToEpochTime now - should |
3813
|
|
|
|
|
|
|
#BUG be removed from here |
3814
|
|
|
|
|
|
|
$time =~ s/\.\d+//; |
3815
|
|
|
|
|
|
|
|
3816
|
|
|
|
|
|
|
#print "Setting TerminationTime to: $time\n"; |
3817
|
|
|
|
|
|
|
#test time is good - this will die if the string is faulty, causing |
3818
|
|
|
|
|
|
|
#a SOAP fault to be sent to the cli |
3819
|
|
|
|
|
|
|
#ent |
3820
|
|
|
|
|
|
|
DateTime::Format::W3CDTF->new->parse_datetime($time); |
3821
|
|
|
|
|
|
|
|
3822
|
|
|
|
|
|
|
my $SecsToLive = WSRF::Time::ConvertStringToEpochTime($time); |
3823
|
|
|
|
|
|
|
|
3824
|
|
|
|
|
|
|
if ( $SecsToLive < time ) # TT is sometime in the past, die now |
3825
|
|
|
|
|
|
|
{ |
3826
|
|
|
|
|
|
|
|
3827
|
|
|
|
|
|
|
#give us time to reply - then die |
3828
|
|
|
|
|
|
|
alarm 1; |
3829
|
|
|
|
|
|
|
} else { |
3830
|
|
|
|
|
|
|
|
3831
|
|
|
|
|
|
|
#reset the alarm, this is were you can set a max TT. |
3832
|
|
|
|
|
|
|
alarm( $SecsToLive - time ); |
3833
|
|
|
|
|
|
|
} |
3834
|
|
|
|
|
|
|
|
3835
|
|
|
|
|
|
|
#reset TerminationTime |
3836
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{'TerminationTime'} = $time; |
3837
|
|
|
|
|
|
|
|
3838
|
|
|
|
|
|
|
my $result = "$time"; |
3839
|
|
|
|
|
|
|
$result .= |
3840
|
|
|
|
|
|
|
"" |
3841
|
|
|
|
|
|
|
. WSRF::Time::ConvertEpochTimeToString() |
3842
|
|
|
|
|
|
|
. ""; |
3843
|
|
|
|
|
|
|
|
3844
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
3845
|
|
|
|
|
|
|
SOAP::Data->value($result)->type('xml'); |
3846
|
|
|
|
|
|
|
} |
3847
|
|
|
|
|
|
|
|
3848
|
|
|
|
|
|
|
#=============================================================================== |
3849
|
|
|
|
|
|
|
# If the Service inherits from this class then the ResourceProperties are |
3850
|
|
|
|
|
|
|
# stored in a file between calls. |
3851
|
|
|
|
|
|
|
# |
3852
|
|
|
|
|
|
|
package WSRF::FileBasedResourceProperties; |
3853
|
|
|
|
|
|
|
|
3854
|
|
|
|
|
|
|
=pod |
3855
|
|
|
|
|
|
|
|
3856
|
|
|
|
|
|
|
=head1 WSRF::FileBasedResourceProperties |
3857
|
|
|
|
|
|
|
|
3858
|
|
|
|
|
|
|
If a WS-Resource module inherits from this class then its ResourceProperties |
3859
|
|
|
|
|
|
|
will be stored in a file. |
3860
|
|
|
|
|
|
|
|
3861
|
|
|
|
|
|
|
=head2 METHODS |
3862
|
|
|
|
|
|
|
|
3863
|
|
|
|
|
|
|
=over |
3864
|
|
|
|
|
|
|
|
3865
|
|
|
|
|
|
|
=item GetResourceProperty |
3866
|
|
|
|
|
|
|
|
3867
|
|
|
|
|
|
|
=item GetMultipleResourceProperties |
3868
|
|
|
|
|
|
|
|
3869
|
|
|
|
|
|
|
=item SetResourceProperties |
3870
|
|
|
|
|
|
|
|
3871
|
|
|
|
|
|
|
=item InsertResourceProperties |
3872
|
|
|
|
|
|
|
|
3873
|
|
|
|
|
|
|
=item UpdateResourceProperties |
3874
|
|
|
|
|
|
|
|
3875
|
|
|
|
|
|
|
=item DeleteResourceProperties |
3876
|
|
|
|
|
|
|
|
3877
|
|
|
|
|
|
|
=item GetResourcePropertyDocument |
3878
|
|
|
|
|
|
|
|
3879
|
|
|
|
|
|
|
=back |
3880
|
|
|
|
|
|
|
|
3881
|
|
|
|
|
|
|
=cut |
3882
|
|
|
|
|
|
|
|
3883
|
|
|
|
|
|
|
use vars qw(@ISA); |
3884
|
|
|
|
|
|
|
|
3885
|
|
|
|
|
|
|
@ISA = qw(WSRF::WSRP); |
3886
|
|
|
|
|
|
|
|
3887
|
|
|
|
|
|
|
# Load the ResourceProperties from the file into the ResourceProperties hash |
3888
|
|
|
|
|
|
|
# then call the super operation. |
3889
|
|
|
|
|
|
|
sub GetResourceProperty { |
3890
|
|
|
|
|
|
|
my $self = shift @_; |
3891
|
|
|
|
|
|
|
my $envelope = pop @_; |
3892
|
|
|
|
|
|
|
my $lock = WSRF::File->new($envelope); |
3893
|
|
|
|
|
|
|
|
3894
|
|
|
|
|
|
|
#print "TT= ".$WSRF::WSRP::ResourceProperties{TerminationTime}."\n"; |
3895
|
|
|
|
|
|
|
#print "calling SUPER::GetResourceProperty\n"; |
3896
|
|
|
|
|
|
|
my @resp = $self->SUPER::GetResourceProperty($envelope); |
3897
|
|
|
|
|
|
|
$lock->toFile(); |
3898
|
|
|
|
|
|
|
return @resp; |
3899
|
|
|
|
|
|
|
} |
3900
|
|
|
|
|
|
|
|
3901
|
|
|
|
|
|
|
# Load the ResourceProperties from the file into the ResourceProperties hash |
3902
|
|
|
|
|
|
|
# then call the super operation. |
3903
|
|
|
|
|
|
|
sub GetMultipleResourceProperties { |
3904
|
|
|
|
|
|
|
my $self = shift @_; |
3905
|
|
|
|
|
|
|
my $envelope = pop @_; |
3906
|
|
|
|
|
|
|
my $lock = WSRF::File->new($envelope); |
3907
|
|
|
|
|
|
|
my @resp = $self->SUPER::GetMultipleResourceProperties($envelope); |
3908
|
|
|
|
|
|
|
$lock->toFile(); |
3909
|
|
|
|
|
|
|
return @resp; |
3910
|
|
|
|
|
|
|
} |
3911
|
|
|
|
|
|
|
|
3912
|
|
|
|
|
|
|
# Load the ResourceProperties from the file into the ResourceProperties hash |
3913
|
|
|
|
|
|
|
# then call the super operation. |
3914
|
|
|
|
|
|
|
sub SetResourceProperties { |
3915
|
|
|
|
|
|
|
my $self = shift @_; |
3916
|
|
|
|
|
|
|
my $envelope = pop @_; |
3917
|
|
|
|
|
|
|
my $lock = WSRF::File->new($envelope); |
3918
|
|
|
|
|
|
|
my @resp = $self->SUPER::SetResourceProperties($envelope); |
3919
|
|
|
|
|
|
|
$lock->toFile(); |
3920
|
|
|
|
|
|
|
return @resp; |
3921
|
|
|
|
|
|
|
} |
3922
|
|
|
|
|
|
|
|
3923
|
|
|
|
|
|
|
# Load the ResourceProperties from the file into the ResourceProperties hash |
3924
|
|
|
|
|
|
|
# then call the super operation. |
3925
|
|
|
|
|
|
|
sub InsertResourceProperties { |
3926
|
|
|
|
|
|
|
my $self = shift @_; |
3927
|
|
|
|
|
|
|
my $envelope = pop @_; |
3928
|
|
|
|
|
|
|
my $lock = WSRF::File->new($envelope); |
3929
|
|
|
|
|
|
|
my @resp = $self->SUPER::InsertResourceProperties($envelope); |
3930
|
|
|
|
|
|
|
$lock->toFile(); |
3931
|
|
|
|
|
|
|
return @resp; |
3932
|
|
|
|
|
|
|
} |
3933
|
|
|
|
|
|
|
|
3934
|
|
|
|
|
|
|
# Load the ResourceProperties from the file into the ResourceProperties hash |
3935
|
|
|
|
|
|
|
# then call the super operation. |
3936
|
|
|
|
|
|
|
sub UpdateResourceProperties { |
3937
|
|
|
|
|
|
|
my $self = shift @_; |
3938
|
|
|
|
|
|
|
my $envelope = pop @_; |
3939
|
|
|
|
|
|
|
my $lock = WSRF::File->new($envelope); |
3940
|
|
|
|
|
|
|
my @resp = $self->SUPER::UpdateResourceProperties($envelope); |
3941
|
|
|
|
|
|
|
$lock->toFile(); |
3942
|
|
|
|
|
|
|
return @resp; |
3943
|
|
|
|
|
|
|
} |
3944
|
|
|
|
|
|
|
|
3945
|
|
|
|
|
|
|
# Load the ResourceProperties from the file into the ResourceProperties hash |
3946
|
|
|
|
|
|
|
# then call the super operation. |
3947
|
|
|
|
|
|
|
sub DeleteResourceProperties { |
3948
|
|
|
|
|
|
|
my $self = shift @_; |
3949
|
|
|
|
|
|
|
my $envelope = pop @_; |
3950
|
|
|
|
|
|
|
my $lock = WSRF::File->new($envelope); |
3951
|
|
|
|
|
|
|
my @resp = $self->SUPER::DeleteResourceProperties($envelope); |
3952
|
|
|
|
|
|
|
$lock->toFile(); |
3953
|
|
|
|
|
|
|
return @resp; |
3954
|
|
|
|
|
|
|
} |
3955
|
|
|
|
|
|
|
|
3956
|
|
|
|
|
|
|
# Load the ResourceProperties from the file into the ResourceProperties hash |
3957
|
|
|
|
|
|
|
# then call the super operation. |
3958
|
|
|
|
|
|
|
sub GetResourcePropertyDocument { |
3959
|
|
|
|
|
|
|
my $self = shift @_; |
3960
|
|
|
|
|
|
|
my $envelope = pop @_; |
3961
|
|
|
|
|
|
|
my $lock = WSRF::File->new($envelope); |
3962
|
|
|
|
|
|
|
my @resp = $self->SUPER::GetResourcePropertyDocument($envelope); |
3963
|
|
|
|
|
|
|
$lock->toFile(); |
3964
|
|
|
|
|
|
|
return @resp; |
3965
|
|
|
|
|
|
|
} |
3966
|
|
|
|
|
|
|
|
3967
|
|
|
|
|
|
|
#============================================================================= |
3968
|
|
|
|
|
|
|
# Inherits from WSRF::FileBasedResourceProperties, adds the WSRL operations |
3969
|
|
|
|
|
|
|
# to the Service. Again all the ResourceProperties are stored in a file |
3970
|
|
|
|
|
|
|
# between calls - the name of the file is the same as the Resource ID |
3971
|
|
|
|
|
|
|
# |
3972
|
|
|
|
|
|
|
|
3973
|
|
|
|
|
|
|
package WSRF::FileBasedResourceLifetimes; |
3974
|
|
|
|
|
|
|
|
3975
|
|
|
|
|
|
|
=pod |
3976
|
|
|
|
|
|
|
|
3977
|
|
|
|
|
|
|
=head1 WSRF::FileBasedResourceLifetimes |
3978
|
|
|
|
|
|
|
|
3979
|
|
|
|
|
|
|
If a WS-Resource wants to store its state in a file and wants to support |
3980
|
|
|
|
|
|
|
WS-ResourceLifetimes it should inherit from this class. |
3981
|
|
|
|
|
|
|
WSRF::FileBasedResourceLifetimes inherits from |
3982
|
|
|
|
|
|
|
WSRF::FileBasedResourceProperties. |
3983
|
|
|
|
|
|
|
|
3984
|
|
|
|
|
|
|
=head2 METHODS |
3985
|
|
|
|
|
|
|
|
3986
|
|
|
|
|
|
|
=over |
3987
|
|
|
|
|
|
|
|
3988
|
|
|
|
|
|
|
=item Destroy |
3989
|
|
|
|
|
|
|
|
3990
|
|
|
|
|
|
|
=item SetTerminationTime |
3991
|
|
|
|
|
|
|
|
3992
|
|
|
|
|
|
|
=back |
3993
|
|
|
|
|
|
|
|
3994
|
|
|
|
|
|
|
=cut |
3995
|
|
|
|
|
|
|
|
3996
|
|
|
|
|
|
|
use vars qw(@ISA); |
3997
|
|
|
|
|
|
|
|
3998
|
|
|
|
|
|
|
@ISA = qw(WSRF::FileBasedResourceProperties); |
3999
|
|
|
|
|
|
|
|
4000
|
|
|
|
|
|
|
#Add TerminationTime as a reource property - |
4001
|
|
|
|
|
|
|
#initalise to nothing (infinity) |
4002
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{'TerminationTime'} = ""; |
4003
|
|
|
|
|
|
|
|
4004
|
|
|
|
|
|
|
#belongs to RsourceLiftetime namespace - defined |
4005
|
|
|
|
|
|
|
#elsewhere to be wsrl |
4006
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{TerminationTime}{prefix} = "wsrl"; |
4007
|
|
|
|
|
|
|
|
4008
|
|
|
|
|
|
|
#the TerminationTime can be nil |
4009
|
|
|
|
|
|
|
$WSRF::WSRP::Nillable{TerminationTime} = 1; |
4010
|
|
|
|
|
|
|
$WSRF::WSRP::NotModifiable{TerminationTime} = 1; |
4011
|
|
|
|
|
|
|
|
4012
|
|
|
|
|
|
|
#add resource property CurrentTime - in this |
4013
|
|
|
|
|
|
|
#case a subroutine that returns the current |
4014
|
|
|
|
|
|
|
#time in the correct format |
4015
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{'CurrentTime'} = sub { |
4016
|
|
|
|
|
|
|
return "" |
4017
|
|
|
|
|
|
|
. WSRF::Time::ConvertEpochTimeToString() |
4018
|
|
|
|
|
|
|
. ""; |
4019
|
|
|
|
|
|
|
}; |
4020
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{CurrentTime}{prefix} = "wsrl"; |
4021
|
|
|
|
|
|
|
|
4022
|
|
|
|
|
|
|
#By default if a resource property is a subroutine |
4023
|
|
|
|
|
|
|
#then you cannot change it or delete it - however |
4024
|
|
|
|
|
|
|
#for completeness we set the following |
4025
|
|
|
|
|
|
|
$WSRF::WSRP::NotDeletable{CurrentTime} = 1; |
4026
|
|
|
|
|
|
|
$WSRF::WSRP::NotModifiable{CurrentTime} = 1; |
4027
|
|
|
|
|
|
|
|
4028
|
|
|
|
|
|
|
# remove the file with the resource properties in it. |
4029
|
|
|
|
|
|
|
sub Destroy { |
4030
|
|
|
|
|
|
|
my $envelope = pop @_; |
4031
|
|
|
|
|
|
|
my $lock = WSRF::File->new($envelope); |
4032
|
|
|
|
|
|
|
my $file = $WSRF::Constants::Data . $lock->ID(); |
4033
|
|
|
|
|
|
|
unlink $file |
4034
|
|
|
|
|
|
|
or die SOAP::Fault->faultcode("Container Failure") |
4035
|
|
|
|
|
|
|
->faultstring("Container Failure: could not remove file"); |
4036
|
|
|
|
|
|
|
return WSRF::Header::header($envelope); |
4037
|
|
|
|
|
|
|
} |
4038
|
|
|
|
|
|
|
|
4039
|
|
|
|
|
|
|
# load the properties from the file into the hash then |
4040
|
|
|
|
|
|
|
# set the termination time and store back to the file. |
4041
|
|
|
|
|
|
|
sub SetTerminationTime { |
4042
|
|
|
|
|
|
|
my $envelope = pop @_; |
4043
|
|
|
|
|
|
|
my $lock = WSRF::File->new($envelope); |
4044
|
|
|
|
|
|
|
shift @_; #the first paramter is always the class of the object |
4045
|
|
|
|
|
|
|
my $time = shift @_; #the new TerminationTime |
4046
|
|
|
|
|
|
|
|
4047
|
|
|
|
|
|
|
#check for null time - allowed by wsrl |
4048
|
|
|
|
|
|
|
my ($ans); |
4049
|
|
|
|
|
|
|
if ( $time eq "" ) { |
4050
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{'TerminationTime'} = ""; |
4051
|
|
|
|
|
|
|
|
4052
|
|
|
|
|
|
|
my $ans = |
4053
|
|
|
|
|
|
|
"" |
4054
|
|
|
|
|
|
|
. "" |
4055
|
|
|
|
|
|
|
. WSRF::Time::ConvertEpochTimeToString(time) |
4056
|
|
|
|
|
|
|
. ""; |
4057
|
|
|
|
|
|
|
} else { |
4058
|
|
|
|
|
|
|
|
4059
|
|
|
|
|
|
|
#BUG - this is done in ConvertEpochTimeToString now so we can drop it |
4060
|
|
|
|
|
|
|
$time =~ s/\.\d+//; |
4061
|
|
|
|
|
|
|
|
4062
|
|
|
|
|
|
|
#print "Setting TerminationTime to: $time\n"; |
4063
|
|
|
|
|
|
|
|
4064
|
|
|
|
|
|
|
#test time is good - this will die if the string is faulty, causing |
4065
|
|
|
|
|
|
|
#a SOAP fault to be sent to the client |
4066
|
|
|
|
|
|
|
DateTime::Format::W3CDTF->new->parse_datetime($time); |
4067
|
|
|
|
|
|
|
|
4068
|
|
|
|
|
|
|
#reset TerminationTime |
4069
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{'TerminationTime'} = $time; |
4070
|
|
|
|
|
|
|
|
4071
|
|
|
|
|
|
|
$ans = "$time"; |
4072
|
|
|
|
|
|
|
$ans .= |
4073
|
|
|
|
|
|
|
"" |
4074
|
|
|
|
|
|
|
. WSRF::Time::ConvertEpochTimeToString() |
4075
|
|
|
|
|
|
|
. ""; |
4076
|
|
|
|
|
|
|
} |
4077
|
|
|
|
|
|
|
|
4078
|
|
|
|
|
|
|
$lock->toFile(); |
4079
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
4080
|
|
|
|
|
|
|
SOAP::Data->value($ans)->type('xml'); |
4081
|
|
|
|
|
|
|
} |
4082
|
|
|
|
|
|
|
|
4083
|
|
|
|
|
|
|
#=============================================================================== |
4084
|
|
|
|
|
|
|
# In this case a single process acts on behave of a number of |
4085
|
|
|
|
|
|
|
# Resources - the resource properties are all held in a hash - the |
4086
|
|
|
|
|
|
|
# ID of the resource is used as the key to the hash. The Container |
4087
|
|
|
|
|
|
|
# talks to the process through a named UNIX socket - the name of the |
4088
|
|
|
|
|
|
|
# socket is the same as the name of the module. |
4089
|
|
|
|
|
|
|
# |
4090
|
|
|
|
|
|
|
package WSRF::MultiResourceProperties; |
4091
|
|
|
|
|
|
|
|
4092
|
|
|
|
|
|
|
=pod |
4093
|
|
|
|
|
|
|
|
4094
|
|
|
|
|
|
|
=head1 WSRF::MultiResourceProperties |
4095
|
|
|
|
|
|
|
|
4096
|
|
|
|
|
|
|
In this case a single process acts on behave of a number of |
4097
|
|
|
|
|
|
|
WS-Resources. The I are all held in a hash - the |
4098
|
|
|
|
|
|
|
WSRF::Lite identifier of the WS-Resource is used as the key to the hash. |
4099
|
|
|
|
|
|
|
The WSRF::Lite I talks to the process through a named UNIX socket |
4100
|
|
|
|
|
|
|
- the name of the socket is the same as the name of the module. |
4101
|
|
|
|
|
|
|
The WS-Resource module should inherit this class |
4102
|
|
|
|
|
|
|
|
4103
|
|
|
|
|
|
|
=head2 METHODS |
4104
|
|
|
|
|
|
|
|
4105
|
|
|
|
|
|
|
=over |
4106
|
|
|
|
|
|
|
|
4107
|
|
|
|
|
|
|
=item GetResourcePropertyDocument |
4108
|
|
|
|
|
|
|
|
4109
|
|
|
|
|
|
|
=item GetResourceProperty |
4110
|
|
|
|
|
|
|
|
4111
|
|
|
|
|
|
|
=item GetMultipleResourceProperties |
4112
|
|
|
|
|
|
|
|
4113
|
|
|
|
|
|
|
=item SetResourceProperties |
4114
|
|
|
|
|
|
|
|
4115
|
|
|
|
|
|
|
=item InsertResourceProperties |
4116
|
|
|
|
|
|
|
|
4117
|
|
|
|
|
|
|
=item UpdateResourceProperties |
4118
|
|
|
|
|
|
|
|
4119
|
|
|
|
|
|
|
=item DeleteResourceProperties |
4120
|
|
|
|
|
|
|
|
4121
|
|
|
|
|
|
|
=back |
4122
|
|
|
|
|
|
|
|
4123
|
|
|
|
|
|
|
=cut |
4124
|
|
|
|
|
|
|
|
4125
|
|
|
|
|
|
|
use vars qw(@ISA); |
4126
|
|
|
|
|
|
|
|
4127
|
|
|
|
|
|
|
#we inherit this to gain access to the envelope - see SOAP::Lite |
4128
|
|
|
|
|
|
|
@ISA = qw(SOAP::Server::Parameters); |
4129
|
|
|
|
|
|
|
|
4130
|
|
|
|
|
|
|
# For this example all Resources are managed by one process, |
4131
|
|
|
|
|
|
|
# a hash holds an entry for each resource, the same hash |
4132
|
|
|
|
|
|
|
# also holds all the resource properties for each resource |
4133
|
|
|
|
|
|
|
|
4134
|
|
|
|
|
|
|
#Hash to store each resource and its properties |
4135
|
|
|
|
|
|
|
%WSRF::MultiResourceProperties::ResourceProperties = (); |
4136
|
|
|
|
|
|
|
|
4137
|
|
|
|
|
|
|
# Hash stores the prefix for the resource property |
4138
|
|
|
|
|
|
|
# eg CurrentTime will use the prefix wsrl, the |
4139
|
|
|
|
|
|
|
# map between tthe prefix and the namespace is |
4140
|
|
|
|
|
|
|
# elsewhere |
4141
|
|
|
|
|
|
|
%WSRF::MultiResourceProperties::PropertyNamespaceMap = (); |
4142
|
|
|
|
|
|
|
|
4143
|
|
|
|
|
|
|
# Hash that maps a property and the fuction that |
4144
|
|
|
|
|
|
|
# should be called when aan attempt is made to |
4145
|
|
|
|
|
|
|
# insert that property. Simple properties are |
4146
|
|
|
|
|
|
|
# handled by default. |
4147
|
|
|
|
|
|
|
%WSRF::MultiResourceProperties::InsertMap = (); |
4148
|
|
|
|
|
|
|
|
4149
|
|
|
|
|
|
|
# Hash that maps property to function that should |
4150
|
|
|
|
|
|
|
# be used to delete it - simple properties are |
4151
|
|
|
|
|
|
|
# handled by default |
4152
|
|
|
|
|
|
|
%WSRF::MultiResourceProperties::DeleteMap = (); |
4153
|
|
|
|
|
|
|
|
4154
|
|
|
|
|
|
|
# Hash to define which properties can be "nil" - by |
4155
|
|
|
|
|
|
|
# default properties can not be nil. |
4156
|
|
|
|
|
|
|
%WSRF::MultiResourceProperties::Nillable = (); |
4157
|
|
|
|
|
|
|
|
4158
|
|
|
|
|
|
|
# Hash to define which properties cannot be Deleted |
4159
|
|
|
|
|
|
|
%WSRF::MultiResourceProperties::NotDeletable = (); |
4160
|
|
|
|
|
|
|
|
4161
|
|
|
|
|
|
|
# Hash to define which properties cannot be changed |
4162
|
|
|
|
|
|
|
%WSRF::MultiResourceProperties::NotModifiable = (); |
4163
|
|
|
|
|
|
|
|
4164
|
|
|
|
|
|
|
%WSRF::MultiResourceProperties::NotInsert = (); |
4165
|
|
|
|
|
|
|
|
4166
|
|
|
|
|
|
|
# get the Resource ID from the envelope - check that it is in the |
4167
|
|
|
|
|
|
|
# hash and check the termination time for the resource. |
4168
|
|
|
|
|
|
|
# BUG - should we check the TT for all resources and do Garbag Collection |
4169
|
|
|
|
|
|
|
# pro-actively |
4170
|
|
|
|
|
|
|
sub getID { |
4171
|
|
|
|
|
|
|
my $envelope = shift; |
4172
|
|
|
|
|
|
|
|
4173
|
|
|
|
|
|
|
#print STDERR "Calling getID...\n"; |
4174
|
|
|
|
|
|
|
#search for ResourceID in Header |
4175
|
|
|
|
|
|
|
my $ID = $envelope->headerof("//{$WSRF::Constants::WSA}To"); |
4176
|
|
|
|
|
|
|
if ( defined $ID ) { |
4177
|
|
|
|
|
|
|
$ID = $envelope->headerof("//{$WSRF::Constants::WSA}To")->value; |
4178
|
|
|
|
|
|
|
} else { |
4179
|
|
|
|
|
|
|
die SOAP::Fault->faultcode('No WS-Resource Identifier') |
4180
|
|
|
|
|
|
|
->faultstring('No Resource Identifier in SOAP Header'); |
4181
|
|
|
|
|
|
|
} |
4182
|
|
|
|
|
|
|
|
4183
|
|
|
|
|
|
|
my @PathArray = split( /\//, $ID ); |
4184
|
|
|
|
|
|
|
$ID = pop @PathArray; |
4185
|
|
|
|
|
|
|
|
4186
|
|
|
|
|
|
|
#print STDERR "ID => $ID\n"; |
4187
|
|
|
|
|
|
|
|
4188
|
|
|
|
|
|
|
#check the Resource actually exists or die |
4189
|
|
|
|
|
|
|
if ( !defined( $WSRF::MultiResourceProperties::ResourceProperties->{$ID} ) ) |
4190
|
|
|
|
|
|
|
{ |
4191
|
|
|
|
|
|
|
die SOAP::Fault->faultcode('No WS-Resource') |
4192
|
|
|
|
|
|
|
->faultstring("No Resource with Identifier $ID"); |
4193
|
|
|
|
|
|
|
} |
4194
|
|
|
|
|
|
|
|
4195
|
|
|
|
|
|
|
#check that the resource is still alive - if TT time is not |
4196
|
|
|
|
|
|
|
#set then TT is infinity |
4197
|
|
|
|
|
|
|
foreach |
4198
|
|
|
|
|
|
|
my $key ( keys %{$WSRF::MultiResourceProperties::ResourceProperties} ) |
4199
|
|
|
|
|
|
|
{ |
4200
|
|
|
|
|
|
|
if ( |
4201
|
|
|
|
|
|
|
defined( |
4202
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::ResourceProperties->{$key} |
4203
|
|
|
|
|
|
|
{'TerminationTime'} |
4204
|
|
|
|
|
|
|
) |
4205
|
|
|
|
|
|
|
&& ( $WSRF::MultiResourceProperties::ResourceProperties->{$key} |
4206
|
|
|
|
|
|
|
{'TerminationTime'} ne "" ) |
4207
|
|
|
|
|
|
|
) |
4208
|
|
|
|
|
|
|
{ |
4209
|
|
|
|
|
|
|
if ( |
4210
|
|
|
|
|
|
|
WSRF::Time::ConvertStringToEpochTime( |
4211
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::ResourceProperties->{$key} |
4212
|
|
|
|
|
|
|
{'TerminationTime'} |
4213
|
|
|
|
|
|
|
) < time |
4214
|
|
|
|
|
|
|
) |
4215
|
|
|
|
|
|
|
{ |
4216
|
|
|
|
|
|
|
print STDERR "MultiResourceProperties Resource $key Expired\n"; |
4217
|
|
|
|
|
|
|
delete |
4218
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::ResourceProperties->{$key}; |
4219
|
|
|
|
|
|
|
} |
4220
|
|
|
|
|
|
|
} |
4221
|
|
|
|
|
|
|
} |
4222
|
|
|
|
|
|
|
|
4223
|
|
|
|
|
|
|
#check the Resource actually exists or die |
4224
|
|
|
|
|
|
|
if ( !defined( $WSRF::MultiResourceProperties::ResourceProperties->{$ID} ) ) |
4225
|
|
|
|
|
|
|
{ |
4226
|
|
|
|
|
|
|
die SOAP::Fault->faultcode('No WS-Resource') |
4227
|
|
|
|
|
|
|
->faultstring("No Resource with Identifier $ID"); |
4228
|
|
|
|
|
|
|
} |
4229
|
|
|
|
|
|
|
|
4230
|
|
|
|
|
|
|
#could set as ENV variable? |
4231
|
|
|
|
|
|
|
return $ID; |
4232
|
|
|
|
|
|
|
} |
4233
|
|
|
|
|
|
|
|
4234
|
|
|
|
|
|
|
# serach for a resource property - this is used by getResourceProperty |
4235
|
|
|
|
|
|
|
# and getMultipleResourceProperties. Takes the ID of the resource |
4236
|
|
|
|
|
|
|
# and the name of the rsource. |
4237
|
|
|
|
|
|
|
# BUG - we do not handle namespaces of peroperty!! |
4238
|
|
|
|
|
|
|
my $MultisearchResourceProperty = sub { |
4239
|
|
|
|
|
|
|
my %args = @_; |
4240
|
|
|
|
|
|
|
my $ID = $args{ID}; |
4241
|
|
|
|
|
|
|
my $longsearch = $args{property}; |
4242
|
|
|
|
|
|
|
|
4243
|
|
|
|
|
|
|
#dump the namespace of property |
4244
|
|
|
|
|
|
|
my ( $junk, $search ); |
4245
|
|
|
|
|
|
|
if ( $longsearch =~ m/:/ ) { |
4246
|
|
|
|
|
|
|
( $junk, $search ) = split /:/, $longsearch; |
4247
|
|
|
|
|
|
|
} else { |
4248
|
|
|
|
|
|
|
$search = $longsearch; |
4249
|
|
|
|
|
|
|
} |
4250
|
|
|
|
|
|
|
|
4251
|
|
|
|
|
|
|
#default result!! |
4252
|
|
|
|
|
|
|
my $ans = ""; |
4253
|
|
|
|
|
|
|
|
4254
|
|
|
|
|
|
|
#Check Resource property exists, if it does it can either |
4255
|
|
|
|
|
|
|
#be a simple scalar, an array or a function. |
4256
|
|
|
|
|
|
|
if ( |
4257
|
|
|
|
|
|
|
defined( $WSRF::MultiResourceProperties::ResourceProperties->{$ID}{$search} |
4258
|
|
|
|
|
|
|
) |
4259
|
|
|
|
|
|
|
) |
4260
|
|
|
|
|
|
|
{ |
4261
|
|
|
|
|
|
|
|
4262
|
|
|
|
|
|
|
#get type of property |
4263
|
|
|
|
|
|
|
my $type = |
4264
|
|
|
|
|
|
|
ref( $WSRF::MultiResourceProperties::ResourceProperties->{$ID} |
4265
|
|
|
|
|
|
|
{$search} ); |
4266
|
|
|
|
|
|
|
if ( $type eq "" ) # if scalar |
4267
|
|
|
|
|
|
|
{ |
4268
|
|
|
|
|
|
|
|
4269
|
|
|
|
|
|
|
#check if property set |
4270
|
|
|
|
|
|
|
if ( $WSRF::MultiResourceProperties::ResourceProperties->{$ID} |
4271
|
|
|
|
|
|
|
{$search} ne "" ) |
4272
|
|
|
|
|
|
|
{ |
4273
|
|
|
|
|
|
|
$ans .= "<" |
4274
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4275
|
|
|
|
|
|
|
->{$search}{prefix} . ":$search "; |
4276
|
|
|
|
|
|
|
|
4277
|
|
|
|
|
|
|
#do we need to add a namespace for this property |
4278
|
|
|
|
|
|
|
my $ns = |
4279
|
|
|
|
|
|
|
defined( $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4280
|
|
|
|
|
|
|
->{$search}{namespace} ) |
4281
|
|
|
|
|
|
|
? " xmlns:" |
4282
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4283
|
|
|
|
|
|
|
->{$search}{prefix} . "=\"" |
4284
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4285
|
|
|
|
|
|
|
->{$search}{namespace} . "\">" |
4286
|
|
|
|
|
|
|
: ">"; |
4287
|
|
|
|
|
|
|
$ans .= $ns |
4288
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::ResourceProperties->{$ID} |
4289
|
|
|
|
|
|
|
{$search} . "" |
4290
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4291
|
|
|
|
|
|
|
->{$search}{prefix} . ":$search>"; |
4292
|
|
|
|
|
|
|
} |
4293
|
|
|
|
|
|
|
|
4294
|
|
|
|
|
|
|
#property NOT set - is it nillable? |
4295
|
|
|
|
|
|
|
elsif ( $WSRF::MultiResourceProperties::ResourceProperties->{$ID} |
4296
|
|
|
|
|
|
|
{$search} eq "" |
4297
|
|
|
|
|
|
|
&& defined( $WSRF::MultiResourceProperties::Nillable{$search} ) |
4298
|
|
|
|
|
|
|
) |
4299
|
|
|
|
|
|
|
{ |
4300
|
|
|
|
|
|
|
$ans .= "<" |
4301
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4302
|
|
|
|
|
|
|
->{$search}{prefix} . ":$search"; |
4303
|
|
|
|
|
|
|
my $ns = |
4304
|
|
|
|
|
|
|
defined( $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4305
|
|
|
|
|
|
|
->{$search}{namespace} ) |
4306
|
|
|
|
|
|
|
? " xmlns:" |
4307
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4308
|
|
|
|
|
|
|
->{$search}{prefix} . "=\"" |
4309
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4310
|
|
|
|
|
|
|
->{$search}{namespace} . "\"" |
4311
|
|
|
|
|
|
|
: " "; |
4312
|
|
|
|
|
|
|
$ans .= $ns . " xsi:nil=\"true\"/>"; |
4313
|
|
|
|
|
|
|
} |
4314
|
|
|
|
|
|
|
} |
4315
|
|
|
|
|
|
|
|
4316
|
|
|
|
|
|
|
#property is array of things |
4317
|
|
|
|
|
|
|
elsif ( $type eq "ARRAY" ) { |
4318
|
|
|
|
|
|
|
|
4319
|
|
|
|
|
|
|
#check array is not empty - and property is nillable |
4320
|
|
|
|
|
|
|
if ( |
4321
|
|
|
|
|
|
|
!@{ |
4322
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::ResourceProperties->{$ID} |
4323
|
|
|
|
|
|
|
{$search} |
4324
|
|
|
|
|
|
|
} |
4325
|
|
|
|
|
|
|
&& defined( $WSRF::MultiResourceProperties::Nillable{$search} ) |
4326
|
|
|
|
|
|
|
) |
4327
|
|
|
|
|
|
|
{ |
4328
|
|
|
|
|
|
|
$ans .= "<" |
4329
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4330
|
|
|
|
|
|
|
->{$search}{prefix} . ":$search"; |
4331
|
|
|
|
|
|
|
my $ns = |
4332
|
|
|
|
|
|
|
defined( $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4333
|
|
|
|
|
|
|
->{$search}{namespace} ) |
4334
|
|
|
|
|
|
|
? " xmlns:" |
4335
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4336
|
|
|
|
|
|
|
->{$search}{prefix} . "=\"" |
4337
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4338
|
|
|
|
|
|
|
->{$search}{namespace} . "\"" |
4339
|
|
|
|
|
|
|
: " "; |
4340
|
|
|
|
|
|
|
$ans .= $ns . " xsi:nil=\"true\"/>"; |
4341
|
|
|
|
|
|
|
} |
4342
|
|
|
|
|
|
|
|
4343
|
|
|
|
|
|
|
#loop over array building result |
4344
|
|
|
|
|
|
|
else { |
4345
|
|
|
|
|
|
|
foreach my $entry ( |
4346
|
|
|
|
|
|
|
@{ |
4347
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::ResourceProperties |
4348
|
|
|
|
|
|
|
->{$ID}{$search} |
4349
|
|
|
|
|
|
|
} |
4350
|
|
|
|
|
|
|
) |
4351
|
|
|
|
|
|
|
{ |
4352
|
|
|
|
|
|
|
$ans .= "<" |
4353
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4354
|
|
|
|
|
|
|
->{$search}{prefix} . ":$search"; |
4355
|
|
|
|
|
|
|
|
4356
|
|
|
|
|
|
|
#do we need to add a namespace for this property |
4357
|
|
|
|
|
|
|
my $ns = |
4358
|
|
|
|
|
|
|
defined( |
4359
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::PropertyNamespaceMap |
4360
|
|
|
|
|
|
|
->{$search}{namespace} ) |
4361
|
|
|
|
|
|
|
? " xmlns:" |
4362
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4363
|
|
|
|
|
|
|
->{$search}{prefix} . "=\"" |
4364
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4365
|
|
|
|
|
|
|
->{$search}{namespace} . "\">" |
4366
|
|
|
|
|
|
|
: ">"; |
4367
|
|
|
|
|
|
|
$ans .= |
4368
|
|
|
|
|
|
|
$ns . $entry . "" |
4369
|
|
|
|
|
|
|
. $WSRF::MultiResourceProperties::PropertyNamespaceMap |
4370
|
|
|
|
|
|
|
->{$search}{prefix} . ":$search>"; |
4371
|
|
|
|
|
|
|
} |
4372
|
|
|
|
|
|
|
} |
4373
|
|
|
|
|
|
|
} |
4374
|
|
|
|
|
|
|
|
4375
|
|
|
|
|
|
|
#property is a subroutine - call it to get result |
4376
|
|
|
|
|
|
|
#example of this is CurrentTime |
4377
|
|
|
|
|
|
|
elsif ( $type eq "CODE" ) { |
4378
|
|
|
|
|
|
|
$ans .= |
4379
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::ResourceProperties->{$ID}{$search} |
4380
|
|
|
|
|
|
|
->(); |
4381
|
|
|
|
|
|
|
} |
4382
|
|
|
|
|
|
|
|
4383
|
|
|
|
|
|
|
#Some type we do not understand yet eg. Hash |
4384
|
|
|
|
|
|
|
else { |
4385
|
|
|
|
|
|
|
|
4386
|
|
|
|
|
|
|
my $serializer = WSRF::SimpleSerializer->new(); |
4387
|
|
|
|
|
|
|
$ans .= "<" |
4388
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} |
4389
|
|
|
|
|
|
|
. ":$search"; |
4390
|
|
|
|
|
|
|
|
4391
|
|
|
|
|
|
|
#do we need to add a namespace for this property |
4392
|
|
|
|
|
|
|
my $ns = |
4393
|
|
|
|
|
|
|
defined( $WSRF::WSRP::PropertyNamespaceMap->{$search}{namespace} ) |
4394
|
|
|
|
|
|
|
? " xmlns:" |
4395
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} . "=\"" |
4396
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{namespace} . "\">" |
4397
|
|
|
|
|
|
|
: ">"; |
4398
|
|
|
|
|
|
|
|
4399
|
|
|
|
|
|
|
$ans .= $ns |
4400
|
|
|
|
|
|
|
. $serializer->serialize( |
4401
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties->{$ID}{$search} ) |
4402
|
|
|
|
|
|
|
. "" |
4403
|
|
|
|
|
|
|
. $WSRF::WSRP::PropertyNamespaceMap->{$search}{prefix} |
4404
|
|
|
|
|
|
|
. ":$search>"; |
4405
|
|
|
|
|
|
|
|
4406
|
|
|
|
|
|
|
#die "Do not understand type\n"; |
4407
|
|
|
|
|
|
|
} |
4408
|
|
|
|
|
|
|
|
4409
|
|
|
|
|
|
|
} |
4410
|
|
|
|
|
|
|
|
4411
|
|
|
|
|
|
|
return $ans; |
4412
|
|
|
|
|
|
|
}; |
4413
|
|
|
|
|
|
|
|
4414
|
|
|
|
|
|
|
# This creates XML with all the ResourceProperties in it - we can then |
4415
|
|
|
|
|
|
|
# use the XPath query from queryResourceProperty on it. |
4416
|
|
|
|
|
|
|
# BUG - we have not written queryResourceProperty |
4417
|
|
|
|
|
|
|
my $xmlizeProperties = sub { |
4418
|
|
|
|
|
|
|
my $ID = shift @_; |
4419
|
|
|
|
|
|
|
|
4420
|
|
|
|
|
|
|
if ( !defined($ID) || $ID eq "" ) { |
4421
|
|
|
|
|
|
|
die "Attempt to call xmlizeProperties without ID\n"; |
4422
|
|
|
|
|
|
|
} |
4423
|
|
|
|
|
|
|
|
4424
|
|
|
|
|
|
|
#print "$$ MultiSession xmlizeProperties called for $ID\n"; |
4425
|
|
|
|
|
|
|
|
4426
|
|
|
|
|
|
|
#my $ans = ""; |
4427
|
|
|
|
|
|
|
my $ans = |
4428
|
|
|
|
|
|
|
"
|
4429
|
|
|
|
|
|
|
. " xmlns:wsrp=\"$WSRF::Constants::WSRP\" " |
4430
|
|
|
|
|
|
|
. " xmlns:wsrl=\"$WSRF::Constants::WSRL\" " |
4431
|
|
|
|
|
|
|
. " xmlns:wsa=\"$WSRF::Constants::WSA\" >"; |
4432
|
|
|
|
|
|
|
|
4433
|
|
|
|
|
|
|
foreach my $key ( |
4434
|
|
|
|
|
|
|
keys %{ $WSRF::MultiResourceProperties::ResourceProperties->{$ID} } ) |
4435
|
|
|
|
|
|
|
{ |
4436
|
|
|
|
|
|
|
$ans .= $MultisearchResourceProperty->( ID => $ID, property => $key ); |
4437
|
|
|
|
|
|
|
} |
4438
|
|
|
|
|
|
|
|
4439
|
|
|
|
|
|
|
$ans .= ""; |
4440
|
|
|
|
|
|
|
|
4441
|
|
|
|
|
|
|
return $ans; |
4442
|
|
|
|
|
|
|
}; |
4443
|
|
|
|
|
|
|
|
4444
|
|
|
|
|
|
|
sub GetResourcePropertyDocument { |
4445
|
|
|
|
|
|
|
my $envelope = pop @_; |
4446
|
|
|
|
|
|
|
my $ID = getID($envelope); |
4447
|
|
|
|
|
|
|
print "$$ Called GetResourcePropertyDocument, ID= $ID\n"; |
4448
|
|
|
|
|
|
|
my $xml = $xmlizeProperties->($ID); |
4449
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
4450
|
|
|
|
|
|
|
SOAP::Data->value($xml)->type('xml'); |
4451
|
|
|
|
|
|
|
} |
4452
|
|
|
|
|
|
|
|
4453
|
|
|
|
|
|
|
# insert property - this function is used by the Insert and Update |
4454
|
|
|
|
|
|
|
# in the SetResourceProperty operation. This operation takes |
4455
|
|
|
|
|
|
|
# the ID of the resource and a SOAP::SOM object that has been set |
4456
|
|
|
|
|
|
|
# at the property that should be inserted |
4457
|
|
|
|
|
|
|
# Only one property can be inserted at a time using the function - |
4458
|
|
|
|
|
|
|
# SetResourceProperty of course loops over it |
4459
|
|
|
|
|
|
|
my $Multiinsert = sub { |
4460
|
|
|
|
|
|
|
my %args = @_; |
4461
|
|
|
|
|
|
|
my $ID = $args{ID}; |
4462
|
|
|
|
|
|
|
my $b = $args{som}; |
4463
|
|
|
|
|
|
|
|
4464
|
|
|
|
|
|
|
#get the name of the property |
4465
|
|
|
|
|
|
|
my $name = $b->dataof()->name; |
4466
|
|
|
|
|
|
|
|
4467
|
|
|
|
|
|
|
#check there is no user defined function |
4468
|
|
|
|
|
|
|
#for inserting this property |
4469
|
|
|
|
|
|
|
if ( defined( $WSRF::MultiResourceProperties::InsertMap{$name} ) ) { |
4470
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::InsertMap{$name}->( $ID, $b ); |
4471
|
|
|
|
|
|
|
return; |
4472
|
|
|
|
|
|
|
} |
4473
|
|
|
|
|
|
|
|
4474
|
|
|
|
|
|
|
#check this property can be changed |
4475
|
|
|
|
|
|
|
# if( defined( $WSRF::MultiResourceProperties::NotModifiable{$name} )) |
4476
|
|
|
|
|
|
|
# { |
4477
|
|
|
|
|
|
|
# die SOAP::Fault->faultcode("setResourceproperty: Failure") |
4478
|
|
|
|
|
|
|
# ->faultstring("Could not modify $name"); |
4479
|
|
|
|
|
|
|
# } |
4480
|
|
|
|
|
|
|
|
4481
|
|
|
|
|
|
|
#get the value of the property |
4482
|
|
|
|
|
|
|
my $value = $b->dataof()->value; |
4483
|
|
|
|
|
|
|
|
4484
|
|
|
|
|
|
|
#check the property actually exists |
4485
|
|
|
|
|
|
|
if ( |
4486
|
|
|
|
|
|
|
defined( $WSRF::MultiResourceProperties::ResourceProperties->{$ID}{$name} |
4487
|
|
|
|
|
|
|
) |
4488
|
|
|
|
|
|
|
) |
4489
|
|
|
|
|
|
|
{ |
4490
|
|
|
|
|
|
|
|
4491
|
|
|
|
|
|
|
#check the type of the property (scalar|array) |
4492
|
|
|
|
|
|
|
my $type = |
4493
|
|
|
|
|
|
|
ref( |
4494
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::ResourceProperties->{$ID}{$name} ); |
4495
|
|
|
|
|
|
|
if ( $type eq "" ) #scalar |
4496
|
|
|
|
|
|
|
{ |
4497
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::ResourceProperties->{$ID}{$name} = |
4498
|
|
|
|
|
|
|
$value; |
4499
|
|
|
|
|
|
|
} elsif ( $type eq "ARRAY" ) #array |
4500
|
|
|
|
|
|
|
{ |
4501
|
|
|
|
|
|
|
|
4502
|
|
|
|
|
|
|
#add property to array |
4503
|
|
|
|
|
|
|
push( |
4504
|
|
|
|
|
|
|
@{ |
4505
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::ResourceProperties->{$ID} |
4506
|
|
|
|
|
|
|
{$name} |
4507
|
|
|
|
|
|
|
}, |
4508
|
|
|
|
|
|
|
$value |
4509
|
|
|
|
|
|
|
); |
4510
|
|
|
|
|
|
|
} else #perhaps subroutine? |
4511
|
|
|
|
|
|
|
{ |
4512
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("setResourceproperty: Failure") |
4513
|
|
|
|
|
|
|
->faultstring("Could not modify $name"); |
4514
|
|
|
|
|
|
|
} |
4515
|
|
|
|
|
|
|
} else { |
4516
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("No such WS-Resource") |
4517
|
|
|
|
|
|
|
->faultstring("No such WS-Resource with identifier $ID"); |
4518
|
|
|
|
|
|
|
} |
4519
|
|
|
|
|
|
|
return; |
4520
|
|
|
|
|
|
|
}; |
4521
|
|
|
|
|
|
|
|
4522
|
|
|
|
|
|
|
# delete property |
4523
|
|
|
|
|
|
|
# BUG we do not handle namespaces |
4524
|
|
|
|
|
|
|
my $Multimydelete = sub { |
4525
|
|
|
|
|
|
|
my %args = @_; |
4526
|
|
|
|
|
|
|
my $ID = $args{ID}; |
4527
|
|
|
|
|
|
|
my $name = $args{property}; |
4528
|
|
|
|
|
|
|
|
4529
|
|
|
|
|
|
|
#strip namespace |
4530
|
|
|
|
|
|
|
$name =~ s/\w*://; |
4531
|
|
|
|
|
|
|
|
4532
|
|
|
|
|
|
|
#check for user defined delete function for this property |
4533
|
|
|
|
|
|
|
if ( defined( $WSRF::MultiResourceProperties::DeleteMap{$name} ) ) { |
4534
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::DeleteMap{$name}->($ID); |
4535
|
|
|
|
|
|
|
return; |
4536
|
|
|
|
|
|
|
} |
4537
|
|
|
|
|
|
|
|
4538
|
|
|
|
|
|
|
#check we are allowed to delete this function |
4539
|
|
|
|
|
|
|
# if( defined( $WSRF::MultiResourceProperties::NotDeletable{$name} ) ) |
4540
|
|
|
|
|
|
|
# { |
4541
|
|
|
|
|
|
|
# die SOAP::Fault->faultcode("setResourceproperty: Delete Failure") |
4542
|
|
|
|
|
|
|
# ->faultstring("Could not delete $name"); |
4543
|
|
|
|
|
|
|
# } |
4544
|
|
|
|
|
|
|
|
4545
|
|
|
|
|
|
|
#check property exists |
4546
|
|
|
|
|
|
|
if ( |
4547
|
|
|
|
|
|
|
defined( $WSRF::MultiResourceProperties::ResourceProperties->{$ID}{$name} |
4548
|
|
|
|
|
|
|
) |
4549
|
|
|
|
|
|
|
) |
4550
|
|
|
|
|
|
|
{ |
4551
|
|
|
|
|
|
|
|
4552
|
|
|
|
|
|
|
#check type either array or scalar |
4553
|
|
|
|
|
|
|
my $type = |
4554
|
|
|
|
|
|
|
ref( |
4555
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::ResourceProperties->{$ID}{$name} ); |
4556
|
|
|
|
|
|
|
if ( $type eq "" ) #scalar |
4557
|
|
|
|
|
|
|
{ |
4558
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::ResourceProperties->{$ID}{$name} = |
4559
|
|
|
|
|
|
|
""; |
4560
|
|
|
|
|
|
|
} elsif ( $type eq "ARRAY" ) # array |
4561
|
|
|
|
|
|
|
{ |
4562
|
|
|
|
|
|
|
|
4563
|
|
|
|
|
|
|
#set contents to nothing |
4564
|
|
|
|
|
|
|
@{ $WSRF::MultiResourceProperties::ResourceProperties->{$ID} |
4565
|
|
|
|
|
|
|
{$name} } = (); |
4566
|
|
|
|
|
|
|
} else { |
4567
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("setResourceproperty: Delete Failure") |
4568
|
|
|
|
|
|
|
->faultstring("Could not delete $name"); |
4569
|
|
|
|
|
|
|
} |
4570
|
|
|
|
|
|
|
} else { |
4571
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("No such WS-Resource") |
4572
|
|
|
|
|
|
|
->faultstring("No WS-Resource with identifier $ID"); |
4573
|
|
|
|
|
|
|
} |
4574
|
|
|
|
|
|
|
return; |
4575
|
|
|
|
|
|
|
}; |
4576
|
|
|
|
|
|
|
|
4577
|
|
|
|
|
|
|
# provide a default init - incase the service developer doesn't bother |
4578
|
|
|
|
|
|
|
sub init { return; } |
4579
|
|
|
|
|
|
|
|
4580
|
|
|
|
|
|
|
# wsrp GetResourceProperty |
4581
|
|
|
|
|
|
|
sub GetResourceProperty { |
4582
|
|
|
|
|
|
|
my $envelope = pop @_; |
4583
|
|
|
|
|
|
|
my $ID = getID($envelope); |
4584
|
|
|
|
|
|
|
|
4585
|
|
|
|
|
|
|
#search through envelope to the GetResourceProperty bit |
4586
|
|
|
|
|
|
|
#and get the resource property name |
4587
|
|
|
|
|
|
|
my $search = $envelope->valueof('//GetResourceProperty/'); |
4588
|
|
|
|
|
|
|
|
4589
|
|
|
|
|
|
|
my $ans = $MultisearchResourceProperty->( ID => $ID, |
4590
|
|
|
|
|
|
|
property => $search ); |
4591
|
|
|
|
|
|
|
|
4592
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
4593
|
|
|
|
|
|
|
SOAP::Data->value($ans)->type('xml'); |
4594
|
|
|
|
|
|
|
} |
4595
|
|
|
|
|
|
|
|
4596
|
|
|
|
|
|
|
# wsrp GetMultipleResourceProperties |
4597
|
|
|
|
|
|
|
sub GetMultipleResourceProperties { |
4598
|
|
|
|
|
|
|
my $envelope = pop @_; |
4599
|
|
|
|
|
|
|
my $ID = getID($envelope); |
4600
|
|
|
|
|
|
|
|
4601
|
|
|
|
|
|
|
my $ans = ""; #we will just cat the answers together |
4602
|
|
|
|
|
|
|
|
4603
|
|
|
|
|
|
|
# print "XML>>>\n".$xmlizeProperties->($ID)."\n<<
|
4604
|
|
|
|
|
|
|
|
4605
|
|
|
|
|
|
|
#loop over each ResourceProperty request |
4606
|
|
|
|
|
|
|
foreach my $search ( $envelope->valueof('//ResourceProperty/') ) { |
4607
|
|
|
|
|
|
|
$ans .= $MultisearchResourceProperty->( ID => $ID, |
4608
|
|
|
|
|
|
|
property => $search ); |
4609
|
|
|
|
|
|
|
} |
4610
|
|
|
|
|
|
|
|
4611
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
4612
|
|
|
|
|
|
|
SOAP::Data->value($ans)->type('xml'); |
4613
|
|
|
|
|
|
|
|
4614
|
|
|
|
|
|
|
} |
4615
|
|
|
|
|
|
|
|
4616
|
|
|
|
|
|
|
# wsrp SetResourceProperties - the client can request that properties |
4617
|
|
|
|
|
|
|
# are inserted, updated and deleted in the one operation. The commands |
4618
|
|
|
|
|
|
|
# must happen in the order they come in the request, all stop when we |
4619
|
|
|
|
|
|
|
# hit a problem |
4620
|
|
|
|
|
|
|
sub SetResourceProperties { |
4621
|
|
|
|
|
|
|
|
4622
|
|
|
|
|
|
|
#get the envelope |
4623
|
|
|
|
|
|
|
my $som = pop @_; |
4624
|
|
|
|
|
|
|
my $ID = getID($som); |
4625
|
|
|
|
|
|
|
|
4626
|
|
|
|
|
|
|
#the base point of all our searchs. |
4627
|
|
|
|
|
|
|
my $base = "//SetResourceProperties"; |
4628
|
|
|
|
|
|
|
|
4629
|
|
|
|
|
|
|
#find the start of commands - should think |
4630
|
|
|
|
|
|
|
#of this as an array of arries - that is why we have [$jj]/[$kk] |
4631
|
|
|
|
|
|
|
if ( $som->match($base) ) { |
4632
|
|
|
|
|
|
|
my $jj = 1; |
4633
|
|
|
|
|
|
|
|
4634
|
|
|
|
|
|
|
#now we loop over commands - $jj records our postion |
4635
|
|
|
|
|
|
|
while ( $som->dataof("$base/[$jj]") ) { |
4636
|
|
|
|
|
|
|
|
4637
|
|
|
|
|
|
|
#get the command name |
4638
|
|
|
|
|
|
|
my $Function = $som->dataof("$base/[$jj]")->name(); |
4639
|
|
|
|
|
|
|
if ( $Function eq "Insert" ) #an Insert |
4640
|
|
|
|
|
|
|
{ |
4641
|
|
|
|
|
|
|
my $kk = 1; |
4642
|
|
|
|
|
|
|
|
4643
|
|
|
|
|
|
|
#loop over the things that have to be inserted |
4644
|
|
|
|
|
|
|
while ( $som->match("$base/[$jj]/[$kk]") ) { |
4645
|
|
|
|
|
|
|
|
4646
|
|
|
|
|
|
|
#print "Inserting ".$som->dataof("$base/[$jj]/[$kk]")->name()."\n"; |
4647
|
|
|
|
|
|
|
#insert the thing - note we pass a SOM object becasue the |
4648
|
|
|
|
|
|
|
#thing could be pretty complex. |
4649
|
|
|
|
|
|
|
if ( |
4650
|
|
|
|
|
|
|
!defined( |
4651
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::NotInsert{ $som |
4652
|
|
|
|
|
|
|
->dataof("$base/[$jj]/[$kk]")->name() } |
4653
|
|
|
|
|
|
|
) |
4654
|
|
|
|
|
|
|
) |
4655
|
|
|
|
|
|
|
{ |
4656
|
|
|
|
|
|
|
$Multiinsert->( ID => $ID, |
4657
|
|
|
|
|
|
|
som => $som->match("$base/[$jj]/[$kk]") ); |
4658
|
|
|
|
|
|
|
} |
4659
|
|
|
|
|
|
|
$kk++; |
4660
|
|
|
|
|
|
|
} |
4661
|
|
|
|
|
|
|
} elsif ( $Function eq "Update" ) #an Update |
4662
|
|
|
|
|
|
|
{ |
4663
|
|
|
|
|
|
|
my $kk = 1; |
4664
|
|
|
|
|
|
|
my %tmpHash = (); |
4665
|
|
|
|
|
|
|
|
4666
|
|
|
|
|
|
|
#loop over things to Update - an update is a Delete followed |
4667
|
|
|
|
|
|
|
#by an Insert in a single atomic operation |
4668
|
|
|
|
|
|
|
while ( $som->match("$base/[$jj]/[$kk]") ) { |
4669
|
|
|
|
|
|
|
|
4670
|
|
|
|
|
|
|
#get name of thing we are updating |
4671
|
|
|
|
|
|
|
my $name = $som->dataof("$base/[$jj]/[$kk]")->name(); |
4672
|
|
|
|
|
|
|
|
4673
|
|
|
|
|
|
|
#print "Updating $name\n"; |
4674
|
|
|
|
|
|
|
#check we have not deleted it before else delete before inserting |
4675
|
|
|
|
|
|
|
if ( |
4676
|
|
|
|
|
|
|
!defined( $WSRF::MultiResourceProperties::NotModifiable{$name} |
4677
|
|
|
|
|
|
|
) |
4678
|
|
|
|
|
|
|
) |
4679
|
|
|
|
|
|
|
{ |
4680
|
|
|
|
|
|
|
if ( !defined( $tmpHash{$name} ) ) { |
4681
|
|
|
|
|
|
|
$Multimydelete->( ID => $ID, |
4682
|
|
|
|
|
|
|
property => $name ); |
4683
|
|
|
|
|
|
|
$tmpHash{$name} = 1; |
4684
|
|
|
|
|
|
|
} |
4685
|
|
|
|
|
|
|
|
4686
|
|
|
|
|
|
|
#insert value |
4687
|
|
|
|
|
|
|
$Multiinsert->( ID => $ID, |
4688
|
|
|
|
|
|
|
som => $som->match("$base/[$jj]/[$kk]") ); |
4689
|
|
|
|
|
|
|
} |
4690
|
|
|
|
|
|
|
$kk++; |
4691
|
|
|
|
|
|
|
} |
4692
|
|
|
|
|
|
|
} elsif ( $Function eq "Delete" ) #a Delete |
4693
|
|
|
|
|
|
|
{ |
4694
|
|
|
|
|
|
|
|
4695
|
|
|
|
|
|
|
#the property to delete is actually an attribute |
4696
|
|
|
|
|
|
|
#in the delete element |
4697
|
|
|
|
|
|
|
my $propname = |
4698
|
|
|
|
|
|
|
$som->dataof("$base/[$jj]")->attr->{'resourceProperty'}; |
4699
|
|
|
|
|
|
|
|
4700
|
|
|
|
|
|
|
#print "Delete $propname\n"; |
4701
|
|
|
|
|
|
|
#delete property |
4702
|
|
|
|
|
|
|
if ( |
4703
|
|
|
|
|
|
|
!defined( $WSRF::MultiResourceProperties::NotDeletable{$propname} |
4704
|
|
|
|
|
|
|
) |
4705
|
|
|
|
|
|
|
) |
4706
|
|
|
|
|
|
|
{ |
4707
|
|
|
|
|
|
|
$Multimydelete->( ID => $ID, |
4708
|
|
|
|
|
|
|
property => $propname ); |
4709
|
|
|
|
|
|
|
} |
4710
|
|
|
|
|
|
|
} else { #something other than Insert|Update|Delete |
4711
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("setResourceproperty: Failure") |
4712
|
|
|
|
|
|
|
->faultstring("setResourceProperty does not support $Function: only Insert, Update and Delete are supported" |
4713
|
|
|
|
|
|
|
); |
4714
|
|
|
|
|
|
|
} |
4715
|
|
|
|
|
|
|
$jj++; |
4716
|
|
|
|
|
|
|
} |
4717
|
|
|
|
|
|
|
} |
4718
|
|
|
|
|
|
|
|
4719
|
|
|
|
|
|
|
return WSRF::Header::header($som); |
4720
|
|
|
|
|
|
|
} |
4721
|
|
|
|
|
|
|
|
4722
|
|
|
|
|
|
|
sub InsertResourceProperties { |
4723
|
|
|
|
|
|
|
my $som = pop @_; |
4724
|
|
|
|
|
|
|
my $ID = getID($som); |
4725
|
|
|
|
|
|
|
my $base = "//InsertResourceProperties"; |
4726
|
|
|
|
|
|
|
if ( $som->match($base) ) { |
4727
|
|
|
|
|
|
|
my $kk = 1; |
4728
|
|
|
|
|
|
|
while ( $som->match("$base/[1]/[$kk]") ) { |
4729
|
|
|
|
|
|
|
my $name = $som->dataof("$base/[1]/[$kk]")->name(); |
4730
|
|
|
|
|
|
|
print "Inserting $name\n"; |
4731
|
|
|
|
|
|
|
|
4732
|
|
|
|
|
|
|
#insert the thing - note we pass a SOM object becasue the |
4733
|
|
|
|
|
|
|
#thing could be pretty complex. |
4734
|
|
|
|
|
|
|
if ( !defined( $WSRF::MultiResourceProperties::NotInsert{$name} ) ) |
4735
|
|
|
|
|
|
|
{ |
4736
|
|
|
|
|
|
|
$Multiinsert->( ID => $ID, |
4737
|
|
|
|
|
|
|
som => $som->match("$base/[1]/[$kk]") ); |
4738
|
|
|
|
|
|
|
} else { |
4739
|
|
|
|
|
|
|
die "InvalidInsertResourcePropertiesRequestContent\n"; |
4740
|
|
|
|
|
|
|
} |
4741
|
|
|
|
|
|
|
$kk++; |
4742
|
|
|
|
|
|
|
} |
4743
|
|
|
|
|
|
|
} |
4744
|
|
|
|
|
|
|
return WSRF::Header::header($som); |
4745
|
|
|
|
|
|
|
} |
4746
|
|
|
|
|
|
|
|
4747
|
|
|
|
|
|
|
sub UpdateResourceProperties { |
4748
|
|
|
|
|
|
|
my $som = pop @_; |
4749
|
|
|
|
|
|
|
my $ID = getID($som); |
4750
|
|
|
|
|
|
|
my $base = "//UpdateResourceProperties"; |
4751
|
|
|
|
|
|
|
if ( $som->match($base) ) { |
4752
|
|
|
|
|
|
|
my $kk = 1; |
4753
|
|
|
|
|
|
|
my %tmpHash = (); |
4754
|
|
|
|
|
|
|
while ( $som->match("$base/[1]/[$kk]") ) { |
4755
|
|
|
|
|
|
|
|
4756
|
|
|
|
|
|
|
#get name of thing we are updating |
4757
|
|
|
|
|
|
|
my $name = $som->dataof("$base/[1]/[$kk]")->name(); |
4758
|
|
|
|
|
|
|
print "Updating $name\n"; |
4759
|
|
|
|
|
|
|
if ( |
4760
|
|
|
|
|
|
|
!defined( $WSRF::MultiResourceProperties::NotModifiable{$name} |
4761
|
|
|
|
|
|
|
) |
4762
|
|
|
|
|
|
|
) |
4763
|
|
|
|
|
|
|
{ |
4764
|
|
|
|
|
|
|
|
4765
|
|
|
|
|
|
|
#check we have not deleted it before else delete before inserting |
4766
|
|
|
|
|
|
|
if ( !defined( $tmpHash{$name} ) ) { |
4767
|
|
|
|
|
|
|
$Multimydelete->( ID => $ID, |
4768
|
|
|
|
|
|
|
property => $name ); |
4769
|
|
|
|
|
|
|
$tmpHash{$name} = 1; |
4770
|
|
|
|
|
|
|
} |
4771
|
|
|
|
|
|
|
|
4772
|
|
|
|
|
|
|
#insert value |
4773
|
|
|
|
|
|
|
$Multiinsert->( ID => $ID, |
4774
|
|
|
|
|
|
|
som => $som->match("$base/[1]/[$kk]") ); |
4775
|
|
|
|
|
|
|
} else { |
4776
|
|
|
|
|
|
|
die "InvalidUpdateResourcePropertiesRequestContent\n"; |
4777
|
|
|
|
|
|
|
} |
4778
|
|
|
|
|
|
|
$kk++; |
4779
|
|
|
|
|
|
|
} |
4780
|
|
|
|
|
|
|
} |
4781
|
|
|
|
|
|
|
|
4782
|
|
|
|
|
|
|
return WSRF::Header::header($som); |
4783
|
|
|
|
|
|
|
} |
4784
|
|
|
|
|
|
|
|
4785
|
|
|
|
|
|
|
sub DeleteResourceProperties { |
4786
|
|
|
|
|
|
|
my $som = pop @_; |
4787
|
|
|
|
|
|
|
my $ID = getID($som); |
4788
|
|
|
|
|
|
|
my $base = "//DeleteResourceProperties"; |
4789
|
|
|
|
|
|
|
if ( $som->match($base) ) { |
4790
|
|
|
|
|
|
|
my $kk = 1; |
4791
|
|
|
|
|
|
|
while ( $som->match("$base/[$kk]") ) { |
4792
|
|
|
|
|
|
|
print "Into Loop inner...\n"; |
4793
|
|
|
|
|
|
|
|
4794
|
|
|
|
|
|
|
#the property to delete is actually an attribute |
4795
|
|
|
|
|
|
|
#in the delete element |
4796
|
|
|
|
|
|
|
my $propname = |
4797
|
|
|
|
|
|
|
$som->dataof("$base/[$kk]")->attr->{'ResourceProperty'}; |
4798
|
|
|
|
|
|
|
$propname =~ s/\w*://o; |
4799
|
|
|
|
|
|
|
|
4800
|
|
|
|
|
|
|
#delete property |
4801
|
|
|
|
|
|
|
if ( |
4802
|
|
|
|
|
|
|
!defined( $WSRF::MultiResourceProperties::NotDeletable{$propname} |
4803
|
|
|
|
|
|
|
) |
4804
|
|
|
|
|
|
|
) |
4805
|
|
|
|
|
|
|
{ |
4806
|
|
|
|
|
|
|
$Multimydelete->( ID => $ID, |
4807
|
|
|
|
|
|
|
property => $propname ); |
4808
|
|
|
|
|
|
|
} else { |
4809
|
|
|
|
|
|
|
die "InvalidDeleteResourcePropertiesRequestContent\n"; |
4810
|
|
|
|
|
|
|
} |
4811
|
|
|
|
|
|
|
$kk++; |
4812
|
|
|
|
|
|
|
} |
4813
|
|
|
|
|
|
|
} |
4814
|
|
|
|
|
|
|
|
4815
|
|
|
|
|
|
|
return WSRF::Header::header($som); |
4816
|
|
|
|
|
|
|
} |
4817
|
|
|
|
|
|
|
|
4818
|
|
|
|
|
|
|
#=============================================================================== |
4819
|
|
|
|
|
|
|
# The extension to WSRF::MultiResourceProperties that supports WSRL - adding |
4820
|
|
|
|
|
|
|
# the operations Destroy and SetTerminationTime |
4821
|
|
|
|
|
|
|
# |
4822
|
|
|
|
|
|
|
package WSRF::MultiResourceLifetimes; |
4823
|
|
|
|
|
|
|
|
4824
|
|
|
|
|
|
|
=pod |
4825
|
|
|
|
|
|
|
|
4826
|
|
|
|
|
|
|
=head1 WSRF::MultiResourceLifetimes |
4827
|
|
|
|
|
|
|
|
4828
|
|
|
|
|
|
|
Extends WSRF::MultiResourceProperties to add support for WS-ResourceLifetime. |
4829
|
|
|
|
|
|
|
|
4830
|
|
|
|
|
|
|
=head2 METHODS |
4831
|
|
|
|
|
|
|
|
4832
|
|
|
|
|
|
|
=over |
4833
|
|
|
|
|
|
|
|
4834
|
|
|
|
|
|
|
=item Destroy |
4835
|
|
|
|
|
|
|
|
4836
|
|
|
|
|
|
|
=item SetTerminationTime |
4837
|
|
|
|
|
|
|
|
4838
|
|
|
|
|
|
|
=back |
4839
|
|
|
|
|
|
|
|
4840
|
|
|
|
|
|
|
=cut |
4841
|
|
|
|
|
|
|
|
4842
|
|
|
|
|
|
|
use vars qw(@ISA); |
4843
|
|
|
|
|
|
|
|
4844
|
|
|
|
|
|
|
@ISA = qw(WSRF::MultiResourceProperties); |
4845
|
|
|
|
|
|
|
|
4846
|
|
|
|
|
|
|
# wsrl Destroy |
4847
|
|
|
|
|
|
|
sub Destroy { |
4848
|
|
|
|
|
|
|
my $envelope = pop @_; |
4849
|
|
|
|
|
|
|
my $ID = WSRF::MultiResourceProperties::getID($envelope); |
4850
|
|
|
|
|
|
|
|
4851
|
|
|
|
|
|
|
delete $WSRF::MultiResourceProperties::ResourceProperties->{$ID}; |
4852
|
|
|
|
|
|
|
|
4853
|
|
|
|
|
|
|
#return nothing except a SOAP HEADER |
4854
|
|
|
|
|
|
|
return WSRF::Header::header($envelope); |
4855
|
|
|
|
|
|
|
} |
4856
|
|
|
|
|
|
|
|
4857
|
|
|
|
|
|
|
# wsrl SetTerminationTime |
4858
|
|
|
|
|
|
|
sub SetTerminationTime { |
4859
|
|
|
|
|
|
|
my $envelope = pop @_; |
4860
|
|
|
|
|
|
|
shift @_; #the first paramter is always the class of the object |
4861
|
|
|
|
|
|
|
my $time = shift @_; #the new TerminationTime |
4862
|
|
|
|
|
|
|
my $ID = WSRF::MultiResourceProperties::getID($envelope); |
4863
|
|
|
|
|
|
|
|
4864
|
|
|
|
|
|
|
#check for null time - allowed by wsrl |
4865
|
|
|
|
|
|
|
if ( $time eq "" ) { |
4866
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::ResourceProperties->{$ID} |
4867
|
|
|
|
|
|
|
{'TerminationTime'} = ""; |
4868
|
|
|
|
|
|
|
|
4869
|
|
|
|
|
|
|
my $ans = |
4870
|
|
|
|
|
|
|
"" |
4871
|
|
|
|
|
|
|
. "" |
4872
|
|
|
|
|
|
|
. WSRF::Time::ConvertEpochTimeToString(time) |
4873
|
|
|
|
|
|
|
. ""; |
4874
|
|
|
|
|
|
|
|
4875
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
4876
|
|
|
|
|
|
|
SOAP::Data->value($ans)->type('xml'); |
4877
|
|
|
|
|
|
|
} |
4878
|
|
|
|
|
|
|
|
4879
|
|
|
|
|
|
|
#BUG - with DateTime::Format::W3CDTF - does not |
4880
|
|
|
|
|
|
|
#like subseconds - should patch DateTime::Format::W3CDTF |
4881
|
|
|
|
|
|
|
#print "Called SetTerminationTime: $time\n"; |
4882
|
|
|
|
|
|
|
$time =~ s/\.\d+//; |
4883
|
|
|
|
|
|
|
|
4884
|
|
|
|
|
|
|
#print "Setting TerminationTime to: $time\n"; |
4885
|
|
|
|
|
|
|
|
4886
|
|
|
|
|
|
|
#test time is good - this will die if the string is faulty, causing |
4887
|
|
|
|
|
|
|
#a SOAP fault to be sent to the client |
4888
|
|
|
|
|
|
|
DateTime::Format::W3CDTF->new->parse_datetime($time); |
4889
|
|
|
|
|
|
|
|
4890
|
|
|
|
|
|
|
#reset TerminationTime |
4891
|
|
|
|
|
|
|
$WSRF::MultiResourceProperties::ResourceProperties->{$ID} |
4892
|
|
|
|
|
|
|
{'TerminationTime'} = $time; |
4893
|
|
|
|
|
|
|
|
4894
|
|
|
|
|
|
|
my $result = "$time"; |
4895
|
|
|
|
|
|
|
$result .= |
4896
|
|
|
|
|
|
|
"" |
4897
|
|
|
|
|
|
|
. WSRF::Time::ConvertEpochTimeToString() |
4898
|
|
|
|
|
|
|
. ""; |
4899
|
|
|
|
|
|
|
|
4900
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
4901
|
|
|
|
|
|
|
SOAP::Data->value($result)->type('xml'); |
4902
|
|
|
|
|
|
|
} |
4903
|
|
|
|
|
|
|
|
4904
|
|
|
|
|
|
|
#=============================================================================== |
4905
|
|
|
|
|
|
|
# This package is for supporting ServiceGroups: |
4906
|
|
|
|
|
|
|
# http://www.globus.org/wsrf/specs/ws-servicegroup.pdf |
4907
|
|
|
|
|
|
|
# |
4908
|
|
|
|
|
|
|
# ServiceGroups allows you to bunch a set of WS-Resources |
4909
|
|
|
|
|
|
|
# together. They are the building blocks of Registries |
4910
|
|
|
|
|
|
|
# |
4911
|
|
|
|
|
|
|
# |
4912
|
|
|
|
|
|
|
package WSRF::ServiceGroup; |
4913
|
|
|
|
|
|
|
|
4914
|
|
|
|
|
|
|
=pod |
4915
|
|
|
|
|
|
|
|
4916
|
|
|
|
|
|
|
=head1 WSRF::ServiceGroup |
4917
|
|
|
|
|
|
|
|
4918
|
|
|
|
|
|
|
Provides support for WS-ServiceGroups. This implementation of WS-ServiceGroups |
4919
|
|
|
|
|
|
|
stores the state of the WS-ServiceGroup in a file, it extends |
4920
|
|
|
|
|
|
|
WSRF::FileBasedResourceLifetimes. |
4921
|
|
|
|
|
|
|
|
4922
|
|
|
|
|
|
|
=head2 METHODS |
4923
|
|
|
|
|
|
|
|
4924
|
|
|
|
|
|
|
=over |
4925
|
|
|
|
|
|
|
|
4926
|
|
|
|
|
|
|
=item Add |
4927
|
|
|
|
|
|
|
|
4928
|
|
|
|
|
|
|
Adds a WS-Resource to the ServiceGroup |
4929
|
|
|
|
|
|
|
|
4930
|
|
|
|
|
|
|
=item createServiceGroup |
4931
|
|
|
|
|
|
|
|
4932
|
|
|
|
|
|
|
Creates a new ServiceGroup |
4933
|
|
|
|
|
|
|
|
4934
|
|
|
|
|
|
|
=back |
4935
|
|
|
|
|
|
|
|
4936
|
|
|
|
|
|
|
=cut |
4937
|
|
|
|
|
|
|
|
4938
|
|
|
|
|
|
|
use vars qw(@ISA); |
4939
|
|
|
|
|
|
|
|
4940
|
|
|
|
|
|
|
@ISA = qw(WSRF::FileBasedResourceLifetimes); |
4941
|
|
|
|
|
|
|
|
4942
|
|
|
|
|
|
|
# foo is an array of things |
4943
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{Entry} = []; |
4944
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{Entry}{prefix} = "wssg"; |
4945
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{Entry}{namespace} = $WSRF::Constants::WSSG; |
4946
|
|
|
|
|
|
|
$WSRF::WSRP::NotDeletable{Entry} = 1; #Cannot delete through SetResourceProperty |
4947
|
|
|
|
|
|
|
$WSRF::WSRP::NotModifiable{Entry} = |
4948
|
|
|
|
|
|
|
1; #Cannot modify through SetResourceProperty |
4949
|
|
|
|
|
|
|
|
4950
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{ServiceGroupEPR} = ""; |
4951
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{ServiceGroupEPR}{prefix} = "wssg"; |
4952
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{ServiceGroupEPR}{namespace} = |
4953
|
|
|
|
|
|
|
$WSRF::Constants::WSSG; |
4954
|
|
|
|
|
|
|
$WSRF::WSRP::NotDeletable{ServiceGroupEPR} = |
4955
|
|
|
|
|
|
|
1; #Cannot delete through SetResourceProperty |
4956
|
|
|
|
|
|
|
$WSRF::WSRP::NotModifiable{ServiceGroupEPR} = |
4957
|
|
|
|
|
|
|
1; #Cannot modify through SetResourceProperty |
4958
|
|
|
|
|
|
|
|
4959
|
|
|
|
|
|
|
# The module name and path to use when creating a new entry |
4960
|
|
|
|
|
|
|
# in the SG. Can be overridden by any module that subclasses this one. |
4961
|
|
|
|
|
|
|
$WSRF::ServiceGroup::ServiceGroupEntryModule = "ServiceGroupEntry"; |
4962
|
|
|
|
|
|
|
$WSRF::ServiceGroup::ServiceGroupEntryPath = "Session/ServiceGroupEntry/"; |
4963
|
|
|
|
|
|
|
|
4964
|
|
|
|
|
|
|
$WSRF::WSRP::InsertMap{ServiceGroupEPR} = sub { |
4965
|
|
|
|
|
|
|
my ($som) = @_; |
4966
|
|
|
|
|
|
|
|
4967
|
|
|
|
|
|
|
print STDERR |
4968
|
|
|
|
|
|
|
"ServiceGroup WSRF::WSRP::InsertMap{ServiceGroupEPR} called\n"; |
4969
|
|
|
|
|
|
|
|
4970
|
|
|
|
|
|
|
my $serializer = new WSRF::SimpleSerializer; |
4971
|
|
|
|
|
|
|
|
4972
|
|
|
|
|
|
|
#print STDERR "$$ WSRF::ServiceGroup serializing ServiceGroupEPR\n"; |
4973
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{ServiceGroupEPR} = |
4974
|
|
|
|
|
|
|
$serializer->serialize( $som->dataof('[1]') ); |
4975
|
|
|
|
|
|
|
}; |
4976
|
|
|
|
|
|
|
|
4977
|
|
|
|
|
|
|
$WSRF::WSRP::InsertMap{Entry} = sub { |
4978
|
|
|
|
|
|
|
my ($som) = @_; |
4979
|
|
|
|
|
|
|
|
4980
|
|
|
|
|
|
|
print STDERR "ServiceGroup WSRF::WSRP::InsertMap{Entry} called\n"; |
4981
|
|
|
|
|
|
|
|
4982
|
|
|
|
|
|
|
my $serializer = new WSRF::SimpleSerializer; |
4983
|
|
|
|
|
|
|
|
4984
|
|
|
|
|
|
|
#We store the entry as follows |
4985
|
|
|
|
|
|
|
# MemberServiceEPR |
4986
|
|
|
|
|
|
|
# ServiceGroupEntryEPR |
4987
|
|
|
|
|
|
|
# Content (optional) |
4988
|
|
|
|
|
|
|
# EntryTerminationTime |
4989
|
|
|
|
|
|
|
#We will use EntryTerminationTime as a marker |
4990
|
|
|
|
|
|
|
|
4991
|
|
|
|
|
|
|
#get MemberServiceEPR |
4992
|
|
|
|
|
|
|
my $Entry = $serializer->serialize( $som->dataof('[1]') ); |
4993
|
|
|
|
|
|
|
|
4994
|
|
|
|
|
|
|
#get ServiceGroupEntryEPR |
4995
|
|
|
|
|
|
|
$Entry .= $serializer->serialize( $som->dataof('[2]') ); |
4996
|
|
|
|
|
|
|
|
4997
|
|
|
|
|
|
|
#Get the Content |
4998
|
|
|
|
|
|
|
my $ContentorTime = $serializer->serialize( $som->dataof('[3]') ); |
4999
|
|
|
|
|
|
|
|
5000
|
|
|
|
|
|
|
my $Time = ""; |
5001
|
|
|
|
|
|
|
if ( $ContentorTime =~ m/EntryTerminationTime/o ) { |
5002
|
|
|
|
|
|
|
$Time = $ContentorTime; |
5003
|
|
|
|
|
|
|
$Entry .= $Time; |
5004
|
|
|
|
|
|
|
} else { |
5005
|
|
|
|
|
|
|
$Entry .= $ContentorTime; |
5006
|
|
|
|
|
|
|
$Time = $serializer->serialize( $som->dataof('[4]') ); |
5007
|
|
|
|
|
|
|
$Entry .= $Time; |
5008
|
|
|
|
|
|
|
} |
5009
|
|
|
|
|
|
|
|
5010
|
|
|
|
|
|
|
#print STDERR "$$ Entry= $Entry\n\n"; |
5011
|
|
|
|
|
|
|
|
5012
|
|
|
|
|
|
|
#strip xml tags away from time |
5013
|
|
|
|
|
|
|
$Time =~ s/<\/?EntryTerminationTime\/?>//og; |
5014
|
|
|
|
|
|
|
|
5015
|
|
|
|
|
|
|
#print STDERR "$$ TerminationTime for Entry= $Time\n"; |
5016
|
|
|
|
|
|
|
|
5017
|
|
|
|
|
|
|
if ( $Time eq "nil" ) #No TerminationTime |
5018
|
|
|
|
|
|
|
{ |
5019
|
|
|
|
|
|
|
push( @{ $WSRF::WSRP::ResourceProperties{Entry} }, $Entry ); |
5020
|
|
|
|
|
|
|
} else { |
5021
|
|
|
|
|
|
|
|
5022
|
|
|
|
|
|
|
#check TerminationTime |
5023
|
|
|
|
|
|
|
if ( WSRF::Time::ConvertStringToEpochTime($Time) > time ) { |
5024
|
|
|
|
|
|
|
push( @{ $WSRF::WSRP::ResourceProperties{Entry} }, $Entry ); |
5025
|
|
|
|
|
|
|
} |
5026
|
|
|
|
|
|
|
} |
5027
|
|
|
|
|
|
|
|
5028
|
|
|
|
|
|
|
}; |
5029
|
|
|
|
|
|
|
|
5030
|
|
|
|
|
|
|
my $strip_old_Entries = sub { |
5031
|
|
|
|
|
|
|
my $parser = new XML::DOM::Parser; |
5032
|
|
|
|
|
|
|
my @tmp = @{ $WSRF::WSRP::ResourceProperties{Entry} }; |
5033
|
|
|
|
|
|
|
@{ $WSRF::WSRP::ResourceProperties{Entry} } = (); |
5034
|
|
|
|
|
|
|
foreach my $entry (@tmp) { |
5035
|
|
|
|
|
|
|
my $tmpentry = "" . $entry . ""; |
5036
|
|
|
|
|
|
|
my $doc = $parser->parse($tmpentry); |
5037
|
|
|
|
|
|
|
|
5038
|
|
|
|
|
|
|
#print STDERR "Parsed document..\n"; |
5039
|
|
|
|
|
|
|
my $TermTime = |
5040
|
|
|
|
|
|
|
defined( $doc->getElementsByTagName("EntryTerminationTime")->item(0) |
5041
|
|
|
|
|
|
|
->getFirstChild ) |
5042
|
|
|
|
|
|
|
? $doc->getElementsByTagName("EntryTerminationTime")->item(0) |
5043
|
|
|
|
|
|
|
->getFirstChild->getNodeValue |
5044
|
|
|
|
|
|
|
: ""; |
5045
|
|
|
|
|
|
|
|
5046
|
|
|
|
|
|
|
next |
5047
|
|
|
|
|
|
|
if ( ( $TermTime ne "nil" ) |
5048
|
|
|
|
|
|
|
&& ( WSRF::Time::ConvertStringToEpochTime($TermTime) < time ) ); |
5049
|
|
|
|
|
|
|
|
5050
|
|
|
|
|
|
|
push @{ $WSRF::WSRP::ResourceProperties{Entry} }, $entry; |
5051
|
|
|
|
|
|
|
$doc->dispose; |
5052
|
|
|
|
|
|
|
} |
5053
|
|
|
|
|
|
|
|
5054
|
|
|
|
|
|
|
}; |
5055
|
|
|
|
|
|
|
|
5056
|
|
|
|
|
|
|
# wsrp GetResourceProperty |
5057
|
|
|
|
|
|
|
sub GetResourceProperty { |
5058
|
|
|
|
|
|
|
my $self = shift @_; |
5059
|
|
|
|
|
|
|
my $envelope = pop @_; |
5060
|
|
|
|
|
|
|
|
5061
|
|
|
|
|
|
|
my $lock = WSRF::File->new($envelope); |
5062
|
|
|
|
|
|
|
$strip_old_Entries->(); |
5063
|
|
|
|
|
|
|
|
5064
|
|
|
|
|
|
|
my $search = $envelope->valueof('//GetResourceProperty/'); |
5065
|
|
|
|
|
|
|
|
5066
|
|
|
|
|
|
|
#strip namespace - BUG we should handle namespaces properly and |
5067
|
|
|
|
|
|
|
#not just ignore them |
5068
|
|
|
|
|
|
|
$search =~ s/\w*://o; |
5069
|
|
|
|
|
|
|
|
5070
|
|
|
|
|
|
|
my $ans = ""; |
5071
|
|
|
|
|
|
|
|
5072
|
|
|
|
|
|
|
#print STDERR "GetResourceProperty = $search\n"; |
5073
|
|
|
|
|
|
|
if ( $search eq "Entry" ) { |
5074
|
|
|
|
|
|
|
foreach my $entry ( @{ $WSRF::WSRP::ResourceProperties{Entry} } ) { |
5075
|
|
|
|
|
|
|
$ans .= ""; |
5076
|
|
|
|
|
|
|
|
5077
|
|
|
|
|
|
|
#BUG - why must we take a copy? |
5078
|
|
|
|
|
|
|
my $tmp = $entry; |
5079
|
|
|
|
|
|
|
$tmp =~ s///o; |
5080
|
|
|
|
|
|
|
$tmp =~ s/\w*<\/EntryTerminationTime>//o; |
5081
|
|
|
|
|
|
|
$ans .= $tmp; |
5082
|
|
|
|
|
|
|
$ans .= ""; |
5083
|
|
|
|
|
|
|
} |
5084
|
|
|
|
|
|
|
} else { |
5085
|
|
|
|
|
|
|
$ans = WSRF::WSRP::searchResourceProperty($search); |
5086
|
|
|
|
|
|
|
} |
5087
|
|
|
|
|
|
|
|
5088
|
|
|
|
|
|
|
$lock->toFile(); |
5089
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
5090
|
|
|
|
|
|
|
SOAP::Data->value($ans)->type('xml'); |
5091
|
|
|
|
|
|
|
} |
5092
|
|
|
|
|
|
|
|
5093
|
|
|
|
|
|
|
# wsrp GetMultipleResourceProperties |
5094
|
|
|
|
|
|
|
sub GetMultipleResourceProperties { |
5095
|
|
|
|
|
|
|
my $self = shift @_; |
5096
|
|
|
|
|
|
|
my $envelope = pop @_; |
5097
|
|
|
|
|
|
|
my $lock = WSRF::File->new($envelope); |
5098
|
|
|
|
|
|
|
$strip_old_Entries->(); |
5099
|
|
|
|
|
|
|
|
5100
|
|
|
|
|
|
|
#print ">>>>BEFORE>>>>\n".WSRF::WSRP::xmlizeProperties()."\n<<<<<<<<<<<<\n\n"; |
5101
|
|
|
|
|
|
|
|
5102
|
|
|
|
|
|
|
my $ans = ""; #we will just cat the answers together |
5103
|
|
|
|
|
|
|
|
5104
|
|
|
|
|
|
|
# print "XML>>>\n".$xmlizeProperties->($ID)."\n<<
|
5105
|
|
|
|
|
|
|
|
5106
|
|
|
|
|
|
|
#loop over each ResourceProperty request |
5107
|
|
|
|
|
|
|
foreach my $search ( $envelope->valueof('//ResourceProperty/') ) { |
5108
|
|
|
|
|
|
|
|
5109
|
|
|
|
|
|
|
#strip namespace |
5110
|
|
|
|
|
|
|
$search =~ s/\w*://o; |
5111
|
|
|
|
|
|
|
if ( $search eq "Entry" ) { |
5112
|
|
|
|
|
|
|
foreach my $entry ( @{ $WSRF::WSRP::ResourceProperties{Entry} } ) { |
5113
|
|
|
|
|
|
|
$ans .= ""; |
5114
|
|
|
|
|
|
|
|
5115
|
|
|
|
|
|
|
#BUG - why must we take a copy? |
5116
|
|
|
|
|
|
|
my $tmp = $entry; |
5117
|
|
|
|
|
|
|
$tmp =~ s///o; |
5118
|
|
|
|
|
|
|
$tmp =~ s/\w*<\/EntryTerminationTime>//o; |
5119
|
|
|
|
|
|
|
$ans .= $tmp; |
5120
|
|
|
|
|
|
|
$ans .= ""; |
5121
|
|
|
|
|
|
|
} |
5122
|
|
|
|
|
|
|
} else { |
5123
|
|
|
|
|
|
|
$ans .= WSRF::WSRP::searchResourceProperty($search); |
5124
|
|
|
|
|
|
|
} |
5125
|
|
|
|
|
|
|
} |
5126
|
|
|
|
|
|
|
|
5127
|
|
|
|
|
|
|
#print STDERR ">>>>AFTER>>>>\n".WSRF::WSRP::xmlizeProperties()."\n<<<<<<<<<<<<\n\n"; |
5128
|
|
|
|
|
|
|
|
5129
|
|
|
|
|
|
|
$lock->toFile(); |
5130
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
5131
|
|
|
|
|
|
|
SOAP::Data->value($ans)->type('xml'); |
5132
|
|
|
|
|
|
|
} |
5133
|
|
|
|
|
|
|
|
5134
|
|
|
|
|
|
|
# operation to create a new File based Counter |
5135
|
|
|
|
|
|
|
sub createServiceGroup { |
5136
|
|
|
|
|
|
|
my $envelope = pop @_; |
5137
|
|
|
|
|
|
|
my ( $class, @params ) = @_; |
5138
|
|
|
|
|
|
|
|
5139
|
|
|
|
|
|
|
# get an ID for the Resource |
5140
|
|
|
|
|
|
|
my $ID = WSRF::GSutil::CalGSH_ID(); |
5141
|
|
|
|
|
|
|
|
5142
|
|
|
|
|
|
|
#create a WS-Address for the Resource |
5143
|
|
|
|
|
|
|
my $wsa = WSRF::GSutil::createWSAddress( |
5144
|
|
|
|
|
|
|
module => 'ServiceGroup', |
5145
|
|
|
|
|
|
|
path => 'Session/ServiceGroup/', |
5146
|
|
|
|
|
|
|
ID => $ID |
5147
|
|
|
|
|
|
|
); |
5148
|
|
|
|
|
|
|
|
5149
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{ServiceGroupEPR} = $wsa; |
5150
|
|
|
|
|
|
|
|
5151
|
|
|
|
|
|
|
#write the properties to a file |
5152
|
|
|
|
|
|
|
WSRF::File::toFile($ID); |
5153
|
|
|
|
|
|
|
|
5154
|
|
|
|
|
|
|
#return the WS-Address |
5155
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
5156
|
|
|
|
|
|
|
SOAP::Data->value($wsa)->type('xml'); |
5157
|
|
|
|
|
|
|
} |
5158
|
|
|
|
|
|
|
|
5159
|
|
|
|
|
|
|
# add an entry to the SG |
5160
|
|
|
|
|
|
|
sub Add { |
5161
|
|
|
|
|
|
|
my $envelope = pop @_; #get the SOAP envelope |
5162
|
|
|
|
|
|
|
my $lock = WSRF::File->new($envelope); #get the properties from the file |
5163
|
|
|
|
|
|
|
$strip_old_Entries->(); |
5164
|
|
|
|
|
|
|
my ( $class, $val ) = @_; #get the operation paramaters |
5165
|
|
|
|
|
|
|
|
5166
|
|
|
|
|
|
|
my $serializer = new WSRF::SimpleSerializer; |
5167
|
|
|
|
|
|
|
|
5168
|
|
|
|
|
|
|
#print "$$ Message::\n".$serializer->serialize( $envelope->dataof('/') )."\n\n"; |
5169
|
|
|
|
|
|
|
|
5170
|
|
|
|
|
|
|
# BUG |
5171
|
|
|
|
|
|
|
# We cannot use the following to get the MemberEPR |
5172
|
|
|
|
|
|
|
# my $mepr = $serializer->serialize( $envelope->dataof('//MemberEPR/[1]') ); |
5173
|
|
|
|
|
|
|
# because it screws up the namespaces - SimpleSerializer cannot |
5174
|
|
|
|
|
|
|
# handle more than one namespace in a message. |
5175
|
|
|
|
|
|
|
|
5176
|
|
|
|
|
|
|
my $mepraddress = |
5177
|
|
|
|
|
|
|
$envelope->match("//MemberEPR//{$WSRF::Constants::WSA}Address") |
5178
|
|
|
|
|
|
|
? $envelope->valueof("//MemberEPR//{$WSRF::Constants::WSA}Address") |
5179
|
|
|
|
|
|
|
: die "No MemberEPR in Add message\n"; #BUG - BaseFault |
5180
|
|
|
|
|
|
|
|
5181
|
|
|
|
|
|
|
#check for ReferenceParameters |
5182
|
|
|
|
|
|
|
my ($RefParam); |
5183
|
|
|
|
|
|
|
if ( $envelope->dataof('//MemberEPR//ReferenceParameters/*') ) { |
5184
|
|
|
|
|
|
|
my $i = 0; |
5185
|
|
|
|
|
|
|
foreach |
5186
|
|
|
|
|
|
|
my $a ( $envelope->dataof('//MemberEPR//ReferenceParameters/*') ) |
5187
|
|
|
|
|
|
|
{ |
5188
|
|
|
|
|
|
|
$i++; |
5189
|
|
|
|
|
|
|
my $name = $a->name(); |
5190
|
|
|
|
|
|
|
my $uri = $a->uri(); |
5191
|
|
|
|
|
|
|
my $value = $a->value(); |
5192
|
|
|
|
|
|
|
$RefParam .= |
5193
|
|
|
|
|
|
|
"
|
5194
|
|
|
|
|
|
|
. " xmlns:myns" |
5195
|
|
|
|
|
|
|
. $i . "=\"" |
5196
|
|
|
|
|
|
|
. $uri . "\">" |
5197
|
|
|
|
|
|
|
. $value |
5198
|
|
|
|
|
|
|
. "
|
5199
|
|
|
|
|
|
|
. $i . ":" |
5200
|
|
|
|
|
|
|
. $name . ">"; |
5201
|
|
|
|
|
|
|
} |
5202
|
|
|
|
|
|
|
} |
5203
|
|
|
|
|
|
|
|
5204
|
|
|
|
|
|
|
my $mepr = ""; |
5205
|
|
|
|
|
|
|
$mepr .= "$mepraddress"; |
5206
|
|
|
|
|
|
|
$mepr .= $RefParam ? $RefParam : ""; |
5207
|
|
|
|
|
|
|
$mepr .= ""; |
5208
|
|
|
|
|
|
|
|
5209
|
|
|
|
|
|
|
$mepr = "$mepr"; |
5210
|
|
|
|
|
|
|
|
5211
|
|
|
|
|
|
|
#print STDERR "$$ MEPR = $mepr\n"; |
5212
|
|
|
|
|
|
|
|
5213
|
|
|
|
|
|
|
my $content = ""; |
5214
|
|
|
|
|
|
|
if ( defined( $envelope->dataof('//Content/[1]') ) ) { |
5215
|
|
|
|
|
|
|
|
5216
|
|
|
|
|
|
|
#print "Content!! ". $envelope->dataof('//Content') ."\n"; |
5217
|
|
|
|
|
|
|
$content = $serializer->serialize( $envelope->dataof('//Content/[1]') ); |
5218
|
|
|
|
|
|
|
|
5219
|
|
|
|
|
|
|
$content = "$content"; |
5220
|
|
|
|
|
|
|
} |
5221
|
|
|
|
|
|
|
|
5222
|
|
|
|
|
|
|
# print STDERR "Content = $content\n"; |
5223
|
|
|
|
|
|
|
|
5224
|
|
|
|
|
|
|
my $termTime = "nil"; |
5225
|
|
|
|
|
|
|
if ( defined( $envelope->valueof('//InitialTerminationTime') ) ) { |
5226
|
|
|
|
|
|
|
$termTime = $envelope->valueof('//InitialTerminationTime'); |
5227
|
|
|
|
|
|
|
|
5228
|
|
|
|
|
|
|
#BUG with DateTime::Format::W3CDTF - does not |
5229
|
|
|
|
|
|
|
#like subseconds - should patch DateTime::Format::W3CDTF |
5230
|
|
|
|
|
|
|
#print "Called SetTerminationTime: $time\n"; |
5231
|
|
|
|
|
|
|
$termTime =~ s/\.\d+//; |
5232
|
|
|
|
|
|
|
|
5233
|
|
|
|
|
|
|
#print "Setting TerminationTime to: $time\n"; |
5234
|
|
|
|
|
|
|
|
5235
|
|
|
|
|
|
|
#test time is good - this will die if the string is faulty, causing |
5236
|
|
|
|
|
|
|
#a SOAP fault to be sent to the client |
5237
|
|
|
|
|
|
|
#BUG should eval this and throw a WS-BaseFault |
5238
|
|
|
|
|
|
|
DateTime::Format::W3CDTF->new->parse_datetime($termTime); |
5239
|
|
|
|
|
|
|
} |
5240
|
|
|
|
|
|
|
|
5241
|
|
|
|
|
|
|
$termTime = "$termTime"; |
5242
|
|
|
|
|
|
|
|
5243
|
|
|
|
|
|
|
# get an ID for the new ServiceGroupEntry |
5244
|
|
|
|
|
|
|
my $ID = WSRF::GSutil::CalGSH_ID(); |
5245
|
|
|
|
|
|
|
$ID = $lock->ID() . "-" . $ID; |
5246
|
|
|
|
|
|
|
|
5247
|
|
|
|
|
|
|
#print STDERR "ServiceGroup ID = ".$lock->ID()."\n"; |
5248
|
|
|
|
|
|
|
#print STDERR "ServiceGroupEntry ID = $ID\n"; |
5249
|
|
|
|
|
|
|
|
5250
|
|
|
|
|
|
|
my $sge_wsa = WSRF::GSutil::createWSAddress( |
5251
|
|
|
|
|
|
|
module => $WSRF::ServiceGroup::ServiceGroupEntryModule, |
5252
|
|
|
|
|
|
|
path => $WSRF::ServiceGroup::ServiceGroupEntryPath, |
5253
|
|
|
|
|
|
|
ID => $ID |
5254
|
|
|
|
|
|
|
); |
5255
|
|
|
|
|
|
|
|
5256
|
|
|
|
|
|
|
my $ans = $sge_wsa; |
5257
|
|
|
|
|
|
|
$sge_wsa = |
5258
|
|
|
|
|
|
|
"$sge_wsa"; |
5259
|
|
|
|
|
|
|
|
5260
|
|
|
|
|
|
|
my $Entry = $mepr . $sge_wsa . $content . $termTime; |
5261
|
|
|
|
|
|
|
|
5262
|
|
|
|
|
|
|
push( @{ $WSRF::WSRP::ResourceProperties{Entry} }, $Entry ); |
5263
|
|
|
|
|
|
|
|
5264
|
|
|
|
|
|
|
$lock->toFile(); #put the properties back in the file |
5265
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), #return result |
5266
|
|
|
|
|
|
|
SOAP::Data->value($ans)->type('xml'); |
5267
|
|
|
|
|
|
|
} |
5268
|
|
|
|
|
|
|
|
5269
|
|
|
|
|
|
|
#=============================================================================== |
5270
|
|
|
|
|
|
|
|
5271
|
|
|
|
|
|
|
package WSRF::ServiceGroupEntry; |
5272
|
|
|
|
|
|
|
|
5273
|
|
|
|
|
|
|
=pod |
5274
|
|
|
|
|
|
|
|
5275
|
|
|
|
|
|
|
=head1 WSRF::ServiceGroupEntry |
5276
|
|
|
|
|
|
|
|
5277
|
|
|
|
|
|
|
Provides support for ServiceGroupEntry WS-Resources defined in the |
5278
|
|
|
|
|
|
|
WS-ServiceGroup specification. Each ServiceGroupEntry WS-Resource |
5279
|
|
|
|
|
|
|
represents an entry in a ServiceGroup, destroy the ServiceGroupEntry |
5280
|
|
|
|
|
|
|
and the entry disappears from the ServiceGroup. |
5281
|
|
|
|
|
|
|
|
5282
|
|
|
|
|
|
|
=head2 METHODS |
5283
|
|
|
|
|
|
|
|
5284
|
|
|
|
|
|
|
=over |
5285
|
|
|
|
|
|
|
|
5286
|
|
|
|
|
|
|
=item GetResourcePropertyDocument |
5287
|
|
|
|
|
|
|
|
5288
|
|
|
|
|
|
|
=item GetResourceProperty |
5289
|
|
|
|
|
|
|
|
5290
|
|
|
|
|
|
|
=item GetMultipleResourceProperties |
5291
|
|
|
|
|
|
|
|
5292
|
|
|
|
|
|
|
=item SetResourceProperties |
5293
|
|
|
|
|
|
|
|
5294
|
|
|
|
|
|
|
=item Destroy |
5295
|
|
|
|
|
|
|
|
5296
|
|
|
|
|
|
|
=item SetTerminationTime |
5297
|
|
|
|
|
|
|
|
5298
|
|
|
|
|
|
|
=back |
5299
|
|
|
|
|
|
|
|
5300
|
|
|
|
|
|
|
=cut |
5301
|
|
|
|
|
|
|
|
5302
|
|
|
|
|
|
|
use vars qw(@ISA); |
5303
|
|
|
|
|
|
|
use XML::DOM; |
5304
|
|
|
|
|
|
|
use Storable qw(lock_store lock_nstore lock_retrieve); |
5305
|
|
|
|
|
|
|
|
5306
|
|
|
|
|
|
|
@ISA = qw(WSRF::WSRL); |
5307
|
|
|
|
|
|
|
|
5308
|
|
|
|
|
|
|
# foo is an array of things |
5309
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{Content} = ""; |
5310
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{Content}{prefix} = "wssg"; |
5311
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{Content}{namespace} = |
5312
|
|
|
|
|
|
|
$WSRF::Constants::WSSG; |
5313
|
|
|
|
|
|
|
$WSRF::WSRP::NotDeletable{Content} = |
5314
|
|
|
|
|
|
|
1; #Cannot delete through SetResourceProperty |
5315
|
|
|
|
|
|
|
$WSRF::WSRP::NotModifiable{Content} = |
5316
|
|
|
|
|
|
|
1; #Cannot modify through SetResourceProperty |
5317
|
|
|
|
|
|
|
|
5318
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{ServiceGroupEPR} = ""; |
5319
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{ServiceGroupEPR}{prefix} = "wssg"; |
5320
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{ServiceGroupEPR}{namespace} = |
5321
|
|
|
|
|
|
|
$WSRF::Constants::WSSG; |
5322
|
|
|
|
|
|
|
$WSRF::WSRP::NotDeletable{ServiceGroupEPR} = |
5323
|
|
|
|
|
|
|
1; #Cannot delete through SetResourceProperty |
5324
|
|
|
|
|
|
|
$WSRF::WSRP::NotModifiable{ServiceGroupEPR} = |
5325
|
|
|
|
|
|
|
1; #Cannot modify through SetResourceProperty |
5326
|
|
|
|
|
|
|
|
5327
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{MemberEPR} = ""; |
5328
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{MemberEPR}{prefix} = "wssg"; |
5329
|
|
|
|
|
|
|
$WSRF::WSRP::PropertyNamespaceMap->{MemberEPR}{namespace} = |
5330
|
|
|
|
|
|
|
$WSRF::Constants::WSSG; |
5331
|
|
|
|
|
|
|
$WSRF::WSRP::NotDeletable{MemberEPR} = |
5332
|
|
|
|
|
|
|
1; #Cannot delete through SetResourceProperty |
5333
|
|
|
|
|
|
|
$WSRF::WSRP::NotModifiable{MemberEPR} = |
5334
|
|
|
|
|
|
|
1; #Cannot modify through SetResourceProperty |
5335
|
|
|
|
|
|
|
|
5336
|
|
|
|
|
|
|
my $fromFile = sub { |
5337
|
|
|
|
|
|
|
|
5338
|
|
|
|
|
|
|
# get ID |
5339
|
|
|
|
|
|
|
my ( $envelope, %args ) = @_; |
5340
|
|
|
|
|
|
|
|
5341
|
|
|
|
|
|
|
foreach my $key ( keys %args ) { |
5342
|
|
|
|
|
|
|
print "$$ fromFile $key => " . $args{$key} . "\n"; |
5343
|
|
|
|
|
|
|
} |
5344
|
|
|
|
|
|
|
if ( defined( $args{Destroy} ) ) { |
5345
|
|
|
|
|
|
|
print "$$ fromFile Attempt to Destroy\n"; |
5346
|
|
|
|
|
|
|
} |
5347
|
|
|
|
|
|
|
|
5348
|
|
|
|
|
|
|
my $address = $envelope->headerof("//{$WSRF::Constants::WSA}To"); |
5349
|
|
|
|
|
|
|
if ( defined $address ) { |
5350
|
|
|
|
|
|
|
$address = $envelope->headerof("//{$WSRF::Constants::WSA}To")->value; |
5351
|
|
|
|
|
|
|
} else { |
5352
|
|
|
|
|
|
|
print STDERR "ERROR: No ResourceID in the SOAP Header\n"; |
5353
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("No WS-Resource Identifier") |
5354
|
|
|
|
|
|
|
->faultstring("No WS-Resource identifier in SOAP Header"); |
5355
|
|
|
|
|
|
|
} |
5356
|
|
|
|
|
|
|
|
5357
|
|
|
|
|
|
|
my @PathArray = split( /\//, $address ); |
5358
|
|
|
|
|
|
|
my $ID = pop @PathArray; |
5359
|
|
|
|
|
|
|
|
5360
|
|
|
|
|
|
|
#check the ID is safe - we do not accept dots, |
5361
|
|
|
|
|
|
|
#all paths will be relative to $ENV{WRF_MODULES} |
5362
|
|
|
|
|
|
|
#only allow alphanumeric, underscore and hyphen |
5363
|
|
|
|
|
|
|
if ( $ID =~ /^([-\w]+)$/ ) { |
5364
|
|
|
|
|
|
|
$ID = $1; |
5365
|
|
|
|
|
|
|
} else { |
5366
|
|
|
|
|
|
|
print STDERR "ERROR: Bad ResourceID $ID in SOAP Header\n"; |
5367
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("Badly formed WS-Resource Identifier") |
5368
|
|
|
|
|
|
|
->faultstring("Badly formed WS-Resource Identifier in SOAP Header"); |
5369
|
|
|
|
|
|
|
} |
5370
|
|
|
|
|
|
|
|
5371
|
|
|
|
|
|
|
$ENV{ID} = $ID; |
5372
|
|
|
|
|
|
|
|
5373
|
|
|
|
|
|
|
my $ID_clipped = $ID; |
5374
|
|
|
|
|
|
|
|
5375
|
|
|
|
|
|
|
#ID can be of the form 1341-4565, we use this form to all multiple |
5376
|
|
|
|
|
|
|
#WS-Resources to share the same state, the state is in the file |
5377
|
|
|
|
|
|
|
#1341 - we use this with ServiceGroup/ServiceGroupEntry |
5378
|
|
|
|
|
|
|
$ID_clipped =~ s/-\w*//o; |
5379
|
|
|
|
|
|
|
|
5380
|
|
|
|
|
|
|
my $path = $WSRF::Constants::Data . $ID_clipped; |
5381
|
|
|
|
|
|
|
|
5382
|
|
|
|
|
|
|
if ( !( -e $path ) ) { |
5383
|
|
|
|
|
|
|
print STDERR "ERROR: No Resource $path\n"; |
5384
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("No such WS-Resource") |
5385
|
|
|
|
|
|
|
->faultstring("No WS-Resource with identifier $ID"); |
5386
|
|
|
|
|
|
|
} |
5387
|
|
|
|
|
|
|
|
5388
|
|
|
|
|
|
|
my $lock = $path . ".lock"; |
5389
|
|
|
|
|
|
|
|
5390
|
|
|
|
|
|
|
my $Lock = WSRF::FileLock->new($lock); |
5391
|
|
|
|
|
|
|
|
5392
|
|
|
|
|
|
|
my $hashref = Storable::lock_retrieve($path); |
5393
|
|
|
|
|
|
|
|
5394
|
|
|
|
|
|
|
%WSRF::WSRP::ResourceProperties = |
5395
|
|
|
|
|
|
|
( %WSRF::WSRP::ResourceProperties, %{ $hashref->{Properties} } ); |
5396
|
|
|
|
|
|
|
|
5397
|
|
|
|
|
|
|
%WSRF::WSRP::Private = ( %WSRF::WSRP::Private, %{ $hashref->{Private} } ); |
5398
|
|
|
|
|
|
|
|
5399
|
|
|
|
|
|
|
# print STDERR "$$ fromFile about to enter loop\n"; |
5400
|
|
|
|
|
|
|
my $parser = new XML::DOM::Parser; |
5401
|
|
|
|
|
|
|
my $found = 0; |
5402
|
|
|
|
|
|
|
my ( $doc, $TerminationTime, $MEPR, $Content, $Destroyed ); |
5403
|
|
|
|
|
|
|
my @tmp = @{ $WSRF::WSRP::ResourceProperties{Entry} }; |
5404
|
|
|
|
|
|
|
@{ $WSRF::WSRP::ResourceProperties{Entry} } = (); |
5405
|
|
|
|
|
|
|
|
5406
|
|
|
|
|
|
|
# print "$$ Number of Entries= @tmp\n"; |
5407
|
|
|
|
|
|
|
foreach my $entry (@tmp) { |
5408
|
|
|
|
|
|
|
|
5409
|
|
|
|
|
|
|
# print STDERR $entry."\n"; |
5410
|
|
|
|
|
|
|
my $tmpentry = "" . $entry . ""; |
5411
|
|
|
|
|
|
|
$doc = $parser->parse($tmpentry); |
5412
|
|
|
|
|
|
|
|
5413
|
|
|
|
|
|
|
#print STDERR "Parsed document..\n"; |
5414
|
|
|
|
|
|
|
my $TermTime = |
5415
|
|
|
|
|
|
|
defined( $doc->getElementsByTagName("EntryTerminationTime")->item(0) |
5416
|
|
|
|
|
|
|
->getFirstChild ) |
5417
|
|
|
|
|
|
|
? $doc->getElementsByTagName("EntryTerminationTime")->item(0) |
5418
|
|
|
|
|
|
|
->getFirstChild->getNodeValue |
5419
|
|
|
|
|
|
|
: ""; |
5420
|
|
|
|
|
|
|
|
5421
|
|
|
|
|
|
|
if ( ( $TermTime ne "nil" ) |
5422
|
|
|
|
|
|
|
&& ( WSRF::Time::ConvertStringToEpochTime($TermTime) < time ) ) |
5423
|
|
|
|
|
|
|
{ |
5424
|
|
|
|
|
|
|
print STDERR "Deleting Node\n"; |
5425
|
|
|
|
|
|
|
next; |
5426
|
|
|
|
|
|
|
} |
5427
|
|
|
|
|
|
|
|
5428
|
|
|
|
|
|
|
my $subnodes = $doc->getElementsByTagName("wssg:ServiceGroupEntryEPR"); |
5429
|
|
|
|
|
|
|
|
5430
|
|
|
|
|
|
|
# print "Length= ".$subnodes->getLength."\n"; |
5431
|
|
|
|
|
|
|
my $ResourceID = $subnodes->item(0)->getElementsByTagName("Address"); |
5432
|
|
|
|
|
|
|
if ( $ResourceID->getLength == 0 ) { |
5433
|
|
|
|
|
|
|
$ResourceID = |
5434
|
|
|
|
|
|
|
$subnodes->item(0)->getElementsByTagName("wsa:Address"); |
5435
|
|
|
|
|
|
|
} |
5436
|
|
|
|
|
|
|
|
5437
|
|
|
|
|
|
|
# print "$$ ResourceID Length= ".$ResourceID->getLength."\n"; |
5438
|
|
|
|
|
|
|
$ResourceID = $ResourceID->item(0)->getFirstChild->getNodeValue; |
5439
|
|
|
|
|
|
|
|
5440
|
|
|
|
|
|
|
# print STDERR "$$ ResourceID = $ResourceID\n"; |
5441
|
|
|
|
|
|
|
if ( $ResourceID eq $address ) #found node we want |
5442
|
|
|
|
|
|
|
{ |
5443
|
|
|
|
|
|
|
print STDERR "$$ ResourceIDs match\n"; |
5444
|
|
|
|
|
|
|
$TerminationTime = ( $TermTime eq "nil" ) ? "" : $TermTime; |
5445
|
|
|
|
|
|
|
$Content = |
5446
|
|
|
|
|
|
|
$doc->getElementsByTagName("wssg:Content")->item(0) |
5447
|
|
|
|
|
|
|
->getFirstChild->toString; |
5448
|
|
|
|
|
|
|
$MEPR = |
5449
|
|
|
|
|
|
|
$doc->getElementsByTagName("wssg:MemberServiceEPR")->item(0) |
5450
|
|
|
|
|
|
|
->getFirstChild->toString; |
5451
|
|
|
|
|
|
|
$found = 1; |
5452
|
|
|
|
|
|
|
if ( defined( $args{Destroy} ) ) { |
5453
|
|
|
|
|
|
|
|
5454
|
|
|
|
|
|
|
# print STDERR "$$ Destroying ServiceGroupEntry $ID\n"; |
5455
|
|
|
|
|
|
|
$Destroyed = "True"; |
5456
|
|
|
|
|
|
|
next; |
5457
|
|
|
|
|
|
|
} |
5458
|
|
|
|
|
|
|
if ( defined( $args{TerminationTime} ) ) { |
5459
|
|
|
|
|
|
|
$doc->getElementsByTagName("EntryTerminationTime")->item(0) |
5460
|
|
|
|
|
|
|
->getFirstChild->setNodeValue( $args{TerminationTime} ); |
5461
|
|
|
|
|
|
|
} |
5462
|
|
|
|
|
|
|
my $foo = $doc->toString; |
5463
|
|
|
|
|
|
|
$foo =~ s/<\/?t>//og; |
5464
|
|
|
|
|
|
|
$entry = $foo; |
5465
|
|
|
|
|
|
|
} |
5466
|
|
|
|
|
|
|
push @{ $WSRF::WSRP::ResourceProperties{Entry} }, $entry; |
5467
|
|
|
|
|
|
|
$doc->dispose; |
5468
|
|
|
|
|
|
|
} |
5469
|
|
|
|
|
|
|
|
5470
|
|
|
|
|
|
|
my %tmpPrivate = (%WSRF::WSRP::Private); |
5471
|
|
|
|
|
|
|
|
5472
|
|
|
|
|
|
|
#should use map? |
5473
|
|
|
|
|
|
|
foreach my $key ( keys %tmpPrivate ) { |
5474
|
|
|
|
|
|
|
if ( ref( $tmpPrivate{$key} ) eq "CODE" ) { |
5475
|
|
|
|
|
|
|
delete $tmpPrivate{$key}; |
5476
|
|
|
|
|
|
|
} |
5477
|
|
|
|
|
|
|
} |
5478
|
|
|
|
|
|
|
|
5479
|
|
|
|
|
|
|
#take a copy of the ResourceProperties to copy to file |
5480
|
|
|
|
|
|
|
my %tmphash = (%WSRF::WSRP::ResourceProperties); |
5481
|
|
|
|
|
|
|
foreach my $key ( keys %tmphash ) { |
5482
|
|
|
|
|
|
|
if ( ref( $tmphash{$key} ) eq "CODE" ) { |
5483
|
|
|
|
|
|
|
delete $tmphash{$key}; |
5484
|
|
|
|
|
|
|
} |
5485
|
|
|
|
|
|
|
} |
5486
|
|
|
|
|
|
|
|
5487
|
|
|
|
|
|
|
my %tmpStore = ( Properties => \%tmphash, Private => \%tmpPrivate ); |
5488
|
|
|
|
|
|
|
|
5489
|
|
|
|
|
|
|
local $Storable::forgive_me = "TRUE"; |
5490
|
|
|
|
|
|
|
lock_store \%tmpStore, $path; |
5491
|
|
|
|
|
|
|
|
5492
|
|
|
|
|
|
|
#ServiceGroupEntry not found |
5493
|
|
|
|
|
|
|
if ( !$found && !$Destroyed ) { |
5494
|
|
|
|
|
|
|
die SOAP::Fault->faultcode("No such WS-Resource") |
5495
|
|
|
|
|
|
|
->faultstring("No WS-Resource with identifier $address"); |
5496
|
|
|
|
|
|
|
} |
5497
|
|
|
|
|
|
|
|
5498
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{TerminationTime} = $TerminationTime; |
5499
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{Content} = $Content; |
5500
|
|
|
|
|
|
|
$WSRF::WSRP::ResourceProperties{MemberEPR} = $MEPR; |
5501
|
|
|
|
|
|
|
|
5502
|
|
|
|
|
|
|
return $path; |
5503
|
|
|
|
|
|
|
}; |
5504
|
|
|
|
|
|
|
|
5505
|
|
|
|
|
|
|
sub GetResourceProperty { |
5506
|
|
|
|
|
|
|
my $self = shift @_; |
5507
|
|
|
|
|
|
|
my $envelope = pop @_; |
5508
|
|
|
|
|
|
|
$fromFile->($envelope); |
5509
|
|
|
|
|
|
|
|
5510
|
|
|
|
|
|
|
# print STDERR "ServiceGroupEntry::GetResourceProperty Dumping Properties..\n"; |
5511
|
|
|
|
|
|
|
# foreach my $key ( keys %WSRF::WSRP::ResourceProperties ) |
5512
|
|
|
|
|
|
|
# { |
5513
|
|
|
|
|
|
|
# print " $key: ".$WSRF::WSRP::ResourceProperties{$key}."\n"; |
5514
|
|
|
|
|
|
|
# } |
5515
|
|
|
|
|
|
|
my @resp = $self->SUPER::GetResourceProperty($envelope); |
5516
|
|
|
|
|
|
|
return @resp; |
5517
|
|
|
|
|
|
|
} |
5518
|
|
|
|
|
|
|
|
5519
|
|
|
|
|
|
|
sub GetResourcePropertyDocument { |
5520
|
|
|
|
|
|
|
my $self = shift @_; |
5521
|
|
|
|
|
|
|
my $envelope = pop @_; |
5522
|
|
|
|
|
|
|
$fromFile->($envelope); |
5523
|
|
|
|
|
|
|
my @resp = $self->SUPER::GetResourcePropertyDocument($envelope); |
5524
|
|
|
|
|
|
|
return @resp; |
5525
|
|
|
|
|
|
|
} |
5526
|
|
|
|
|
|
|
|
5527
|
|
|
|
|
|
|
sub SetResourceProperties { |
5528
|
|
|
|
|
|
|
my $self = shift @_; |
5529
|
|
|
|
|
|
|
my $envelope = pop @_; |
5530
|
|
|
|
|
|
|
my $path = $fromFile->($envelope); |
5531
|
|
|
|
|
|
|
my @resp = $self->SUPER::SetResourceProperties($envelope); |
5532
|
|
|
|
|
|
|
return @resp; |
5533
|
|
|
|
|
|
|
} |
5534
|
|
|
|
|
|
|
|
5535
|
|
|
|
|
|
|
sub GetMultipleResourceProperties { |
5536
|
|
|
|
|
|
|
my $self = shift @_; |
5537
|
|
|
|
|
|
|
my $envelope = pop @_; |
5538
|
|
|
|
|
|
|
my $path = $fromFile->($envelope); |
5539
|
|
|
|
|
|
|
my @resp = $self->SUPER::GetMultipleResourceProperties($envelope); |
5540
|
|
|
|
|
|
|
return @resp; |
5541
|
|
|
|
|
|
|
} |
5542
|
|
|
|
|
|
|
|
5543
|
|
|
|
|
|
|
sub Destroy { |
5544
|
|
|
|
|
|
|
|
5545
|
|
|
|
|
|
|
# get ID |
5546
|
|
|
|
|
|
|
my ($envelope) = pop @_; |
5547
|
|
|
|
|
|
|
print STDERR "$$ WSRF::ServiceGroupEntry Destroy invoked\n"; |
5548
|
|
|
|
|
|
|
$fromFile->( $envelope, Destroy => 1 ); |
5549
|
|
|
|
|
|
|
return WSRF::Header::header($envelope); |
5550
|
|
|
|
|
|
|
} |
5551
|
|
|
|
|
|
|
|
5552
|
|
|
|
|
|
|
sub SetTerminationTime { |
5553
|
|
|
|
|
|
|
|
5554
|
|
|
|
|
|
|
# get ID |
5555
|
|
|
|
|
|
|
my ($envelope) = pop @_; |
5556
|
|
|
|
|
|
|
shift @_; #the first paramter is always the class of the object |
5557
|
|
|
|
|
|
|
my $time = shift @_; |
5558
|
|
|
|
|
|
|
|
5559
|
|
|
|
|
|
|
#print STDERR "time= $time\n"; |
5560
|
|
|
|
|
|
|
|
5561
|
|
|
|
|
|
|
#BUG with DateTime::Format::W3CDTF - does not |
5562
|
|
|
|
|
|
|
#like subseconds - should patch DateTime::Format::W3CDTF |
5563
|
|
|
|
|
|
|
#print "Called SetTerminationTime: $time\n"; |
5564
|
|
|
|
|
|
|
$time =~ s/\.\d+//; |
5565
|
|
|
|
|
|
|
|
5566
|
|
|
|
|
|
|
#check time is in good format - otherwise die! |
5567
|
|
|
|
|
|
|
DateTime::Format::W3CDTF->new->parse_datetime($time); |
5568
|
|
|
|
|
|
|
|
5569
|
|
|
|
|
|
|
$fromFile->( $envelope, TerminationTime => $time ); |
5570
|
|
|
|
|
|
|
|
5571
|
|
|
|
|
|
|
my $result = "$time"; |
5572
|
|
|
|
|
|
|
$result .= |
5573
|
|
|
|
|
|
|
"" |
5574
|
|
|
|
|
|
|
. WSRF::Time::ConvertEpochTimeToString() |
5575
|
|
|
|
|
|
|
. ""; |
5576
|
|
|
|
|
|
|
|
5577
|
|
|
|
|
|
|
return WSRF::Header::header($envelope), |
5578
|
|
|
|
|
|
|
SOAP::Data->value($result)->type('xml'); |
5579
|
|
|
|
|
|
|
|
5580
|
|
|
|
|
|
|
} |
5581
|
|
|
|
|
|
|
|
5582
|
|
|
|
|
|
|
# ====================================================================== |
5583
|
|
|
|
|
|
|
|
5584
|
|
|
|
|
|
|
package WSRF; |
5585
|
|
|
|
|
|
|
|
5586
|
|
|
|
|
|
|
use vars qw($AUTOLOAD); |
5587
|
|
|
|
|
|
|
require URI; |
5588
|
|
|
|
|
|
|
|
5589
|
|
|
|
|
|
|
my $soap; # shared between SOAP and SOAP::Lite packages |
5590
|
|
|
|
|
|
|
|
5591
|
|
|
|
|
|
|
{ |
5592
|
|
|
|
|
|
|
no strict 'refs'; |
5593
|
|
|
|
|
|
|
*AUTOLOAD = sub { |
5594
|
|
|
|
|
|
|
local ( $1, $2 ); |
5595
|
|
|
|
|
|
|
my ( $package, $method ) = $AUTOLOAD =~ m/(?:(.+)::)([^:]+)$/; |
5596
|
|
|
|
|
|
|
return if $method eq 'DESTROY'; |
5597
|
|
|
|
|
|
|
|
5598
|
|
|
|
|
|
|
my $soap = |
5599
|
|
|
|
|
|
|
ref $_[0] && UNIVERSAL::isa( $_[0] => 'SOAP::Lite' ) ? $_[0] : $soap |
5600
|
|
|
|
|
|
|
|| die |
5601
|
|
|
|
|
|
|
"SOAP:: prefix shall only be used in combination with +autodispatch option\n"; |
5602
|
|
|
|
|
|
|
|
5603
|
|
|
|
|
|
|
my $uri = URI->new( $soap->uri ); |
5604
|
|
|
|
|
|
|
my $currenturi = $uri->path; |
5605
|
|
|
|
|
|
|
$package = |
5606
|
|
|
|
|
|
|
ref $_[0] && UNIVERSAL::isa( $_[0] => 'SOAP::Lite' ) |
5607
|
|
|
|
|
|
|
? $currenturi |
5608
|
|
|
|
|
|
|
: $package eq 'SOAP' |
5609
|
|
|
|
|
|
|
? ref $_[0] |
5610
|
|
|
|
|
|
|
|| ( $_[0] eq 'SOAP' |
5611
|
|
|
|
|
|
|
? $currenturi || Carp::croak "URI is not specified for method call" |
5612
|
|
|
|
|
|
|
: $_[0] ) |
5613
|
|
|
|
|
|
|
: $package eq 'main' |
5614
|
|
|
|
|
|
|
? $currenturi || $package |
5615
|
|
|
|
|
|
|
: $package; |
5616
|
|
|
|
|
|
|
|
5617
|
|
|
|
|
|
|
# drop first parameter if it's a class name |
5618
|
|
|
|
|
|
|
{ |
5619
|
|
|
|
|
|
|
my $pack = $package; |
5620
|
|
|
|
|
|
|
for ($pack) { s!^/!!; s!/!::!g; } |
5621
|
|
|
|
|
|
|
shift @_ |
5622
|
|
|
|
|
|
|
if @_ && !ref $_[0] && ( $_[0] eq $pack || $_[0] eq 'SOAP' ) |
5623
|
|
|
|
|
|
|
|| ref $_[0] && UNIVERSAL::isa( $_[0] => 'SOAP::Lite' ); |
5624
|
|
|
|
|
|
|
} |
5625
|
|
|
|
|
|
|
|
5626
|
|
|
|
|
|
|
for ($package) { s!::!/!g; s!^/?!/!; } |
5627
|
|
|
|
|
|
|
$uri->path($package); |
5628
|
|
|
|
|
|
|
|
5629
|
|
|
|
|
|
|
my $som = $soap->uri( $uri->as_string )->call( $method => @_ ); |
5630
|
|
|
|
|
|
|
UNIVERSAL::isa( $som => 'SOAP::SOM' ) |
5631
|
|
|
|
|
|
|
? wantarray ? $som->paramsall : $som->result |
5632
|
|
|
|
|
|
|
: $som; |
5633
|
|
|
|
|
|
|
}; |
5634
|
|
|
|
|
|
|
} |
5635
|
|
|
|
|
|
|
|
5636
|
|
|
|
|
|
|
# ====================================================================== |
5637
|
|
|
|
|
|
|
# Copyright (C) 2000-2004 Paul Kulchenko (paulclinger@yahoo.com) |
5638
|
|
|
|
|
|
|
# SOAP::Lite is free software; you can redistribute it |
5639
|
|
|
|
|
|
|
# and/or modify it under the same terms as Perl itself. |
5640
|
|
|
|
|
|
|
|
5641
|
|
|
|
|
|
|
package WSRF::Lite; |
5642
|
|
|
|
|
|
|
|
5643
|
|
|
|
|
|
|
=pod |
5644
|
|
|
|
|
|
|
|
5645
|
|
|
|
|
|
|
=head1 WSRF::Lite |
5646
|
|
|
|
|
|
|
|
5647
|
|
|
|
|
|
|
Extends SOAP::Lite to provide support for WS-Addressing. |
5648
|
|
|
|
|
|
|
WSRF::Lite uses WSRF::WSRFSerializer and WSRF::Deserializer |
5649
|
|
|
|
|
|
|
by default, it will also automatically include the WS-Addressing |
5650
|
|
|
|
|
|
|
SOAP headers in the SOAP message. If $ENV{WSS} is set to true, |
5651
|
|
|
|
|
|
|
$ENV{HTTPS_CERT_FILE} points to the public part of a X.509 |
5652
|
|
|
|
|
|
|
certificate and $ENV{HTTPS_KEY_FILE} points to the unencrypted |
5653
|
|
|
|
|
|
|
private key of the certificate then WSRF::Lite will digitally |
5654
|
|
|
|
|
|
|
sign the message according to the WS-Security specification. |
5655
|
|
|
|
|
|
|
|
5656
|
|
|
|
|
|
|
=head2 METHODS |
5657
|
|
|
|
|
|
|
|
5658
|
|
|
|
|
|
|
WSRF::Lite supports the same set of methods as SOAP::Lite with the |
5659
|
|
|
|
|
|
|
addition of wsaddess. |
5660
|
|
|
|
|
|
|
|
5661
|
|
|
|
|
|
|
=over |
5662
|
|
|
|
|
|
|
|
5663
|
|
|
|
|
|
|
=item wsaddress |
5664
|
|
|
|
|
|
|
|
5665
|
|
|
|
|
|
|
This can be used instead of the proxy method, it takes a WSRF::WS_Address |
5666
|
|
|
|
|
|
|
object for the address of the service or WS-Resource: |
5667
|
|
|
|
|
|
|
|
5668
|
|
|
|
|
|
|
$ans= WSRF::Lite |
5669
|
|
|
|
|
|
|
-> uri($uri) |
5670
|
|
|
|
|
|
|
-> wsaddress(WSRF::WS_Address->new()->Address($target)) |
5671
|
|
|
|
|
|
|
-> createCounterResource(); |
5672
|
|
|
|
|
|
|
|
5673
|
|
|
|
|
|
|
=back |
5674
|
|
|
|
|
|
|
|
5675
|
|
|
|
|
|
|
=cut |
5676
|
|
|
|
|
|
|
|
5677
|
|
|
|
|
|
|
use vars qw($AUTOLOAD @ISA); |
5678
|
|
|
|
|
|
|
use Carp (); |
5679
|
|
|
|
|
|
|
|
5680
|
|
|
|
|
|
|
use SOAP::Packager; |
5681
|
|
|
|
|
|
|
|
5682
|
|
|
|
|
|
|
@ISA = qw(SOAP::Cloneable); |
5683
|
|
|
|
|
|
|
|
5684
|
|
|
|
|
|
|
# provide access to global/autodispatched object |
5685
|
|
|
|
|
|
|
sub self { @_ > 1 ? $soap = $_[1] : $soap } |
5686
|
|
|
|
|
|
|
|
5687
|
|
|
|
|
|
|
# no more warnings about "used only once" |
5688
|
|
|
|
|
|
|
*UNIVERSAL::AUTOLOAD if 0; |
5689
|
|
|
|
|
|
|
|
5690
|
|
|
|
|
|
|
sub autodispatched { \&{*UNIVERSAL::AUTOLOAD} eq \&{*SOAP::AUTOLOAD} } |
5691
|
|
|
|
|
|
|
|
5692
|
|
|
|
|
|
|
sub soapversion { |
5693
|
|
|
|
|
|
|
my $self = shift; |
5694
|
|
|
|
|
|
|
my $version = shift or return $SOAP::Constants::SOAP_VERSION; |
5695
|
|
|
|
|
|
|
|
5696
|
|
|
|
|
|
|
($version) = |
5697
|
|
|
|
|
|
|
grep { $SOAP::Constants::SOAP_VERSIONS{$_}->{NS_ENV} eq $version } |
5698
|
|
|
|
|
|
|
keys %SOAP::Constants::SOAP_VERSIONS |
5699
|
|
|
|
|
|
|
unless exists $SOAP::Constants::SOAP_VERSIONS{$version}; |
5700
|
|
|
|
|
|
|
|
5701
|
|
|
|
|
|
|
die qq!$SOAP::Constants::WRONG_VERSION Supported versions:\n@{[ |
5702
|
|
|
|
|
|
|
join "\n", map {" $_ ($SOAP::Constants::SOAP_VERSIONS{$_}->{NS_ENV})"} keys %SOAP::Constants::SOAP_VERSIONS |
5703
|
|
|
|
|
|
|
]}\n! |
5704
|
|
|
|
|
|
|
unless defined($version) |
5705
|
|
|
|
|
|
|
&& defined( my $def = $SOAP::Constants::SOAP_VERSIONS{$version} ); |
5706
|
|
|
|
|
|
|
|
5707
|
|
|
|
|
|
|
foreach ( keys %$def ) { |
5708
|
|
|
|
|
|
|
eval |
5709
|
|
|
|
|
|
|
"\$SOAP::Constants::$_ = '$SOAP::Constants::SOAP_VERSIONS{$version}->{$_}'"; |
5710
|
|
|
|
|
|
|
} |
5711
|
|
|
|
|
|
|
|
5712
|
|
|
|
|
|
|
$SOAP::Constants::SOAP_VERSION = $version; |
5713
|
|
|
|
|
|
|
$self; |
5714
|
|
|
|
|
|
|
} |
5715
|
|
|
|
|
|
|
|
5716
|
|
|
|
|
|
|
BEGIN { WSRF::Lite->soapversion(1.1) } |
5717
|
|
|
|
|
|
|
|
5718
|
|
|
|
|
|
|
sub import { |
5719
|
|
|
|
|
|
|
my $pkg = shift; |
5720
|
|
|
|
|
|
|
my $caller = caller; |
5721
|
|
|
|
|
|
|
no strict 'refs'; |
5722
|
|
|
|
|
|
|
|
5723
|
|
|
|
|
|
|
# emulate 'use SOAP::Lite 0.99' behavior |
5724
|
|
|
|
|
|
|
$pkg->require_version(shift) if defined $_[0] && $_[0] =~ /^\d/; |
5725
|
|
|
|
|
|
|
|
5726
|
|
|
|
|
|
|
while (@_) { |
5727
|
|
|
|
|
|
|
my $command = shift; |
5728
|
|
|
|
|
|
|
|
5729
|
|
|
|
|
|
|
my @parameters = |
5730
|
|
|
|
|
|
|
UNIVERSAL::isa( $_[0] => 'ARRAY' ) ? @{ shift() } : shift |
5731
|
|
|
|
|
|
|
if @_ && $command ne 'autodispatch'; |
5732
|
|
|
|
|
|
|
if ( $command eq 'autodispatch' || $command eq 'dispatch_from' ) { |
5733
|
|
|
|
|
|
|
$soap = ( $soap || $pkg )->new; |
5734
|
|
|
|
|
|
|
no strict 'refs'; |
5735
|
|
|
|
|
|
|
foreach ( $command eq 'autodispatch' ? 'UNIVERSAL' : @parameters ) { |
5736
|
|
|
|
|
|
|
my $sub = "${_}::AUTOLOAD"; |
5737
|
|
|
|
|
|
|
defined &{*$sub} |
5738
|
|
|
|
|
|
|
? ( \&{*$sub} eq \&{*SOAP::AUTOLOAD} |
5739
|
|
|
|
|
|
|
? () |
5740
|
|
|
|
|
|
|
: Carp::croak |
5741
|
|
|
|
|
|
|
"$sub already assigned and won't work with DISPATCH. Died" |
5742
|
|
|
|
|
|
|
) |
5743
|
|
|
|
|
|
|
: ( *$sub = *SOAP::AUTOLOAD ); |
5744
|
|
|
|
|
|
|
} |
5745
|
|
|
|
|
|
|
} elsif ( $command eq 'service' ) { |
5746
|
|
|
|
|
|
|
foreach ( |
5747
|
|
|
|
|
|
|
keys %{ SOAP::Schema->schema_url( shift(@parameters) ) |
5748
|
|
|
|
|
|
|
->parse(@parameters)->load->services |
5749
|
|
|
|
|
|
|
} |
5750
|
|
|
|
|
|
|
) |
5751
|
|
|
|
|
|
|
{ |
5752
|
|
|
|
|
|
|
$_->export_to_level( 1, undef, ':all' ); |
5753
|
|
|
|
|
|
|
} |
5754
|
|
|
|
|
|
|
} elsif ( $command eq 'debug' || $command eq 'trace' ) { |
5755
|
|
|
|
|
|
|
SOAP::Trace->import( @parameters ? @parameters : 'all' ); |
5756
|
|
|
|
|
|
|
} elsif ( $command eq 'import' ) { |
5757
|
|
|
|
|
|
|
local $^W; # supress warnings about redefining |
5758
|
|
|
|
|
|
|
my $package = shift(@parameters); |
5759
|
|
|
|
|
|
|
$package->export_to_level( 1, undef, |
5760
|
|
|
|
|
|
|
@parameters ? @parameters : ':all' ) |
5761
|
|
|
|
|
|
|
if $package; |
5762
|
|
|
|
|
|
|
} else { |
5763
|
|
|
|
|
|
|
Carp::carp |
5764
|
|
|
|
|
|
|
"Odd (wrong?) number of parameters in import(), still continue" |
5765
|
|
|
|
|
|
|
if $^W && !( @parameters & 1 ); |
5766
|
|
|
|
|
|
|
$soap = ( $soap || $pkg )->$command(@parameters); |
5767
|
|
|
|
|
|
|
} |
5768
|
|
|
|
|
|
|
} |
5769
|
|
|
|
|
|
|
} |
5770
|
|
|
|
|
|
|
|
5771
|
|
|
|
|
|
|
sub DESTROY { SOAP::Trace::objects('()') } |
5772
|
|
|
|
|
|
|
|
5773
|
|
|
|
|
|
|
sub new { |
5774
|
|
|
|
|
|
|
my $self = shift; |
5775
|
|
|
|
|
|
|
return $self if ref $self; |
5776
|
|
|
|
|
|
|
unless ( ref $self ) { |
5777
|
|
|
|
|
|
|
my $class = ref($self) || $self; |
5778
|
|
|
|
|
|
|
|
5779
|
|
|
|
|
|
|
# Check whether we can clone. Only the SAME class allowed, no inheritance |
5780
|
|
|
|
|
|
|
$self = ref($soap) eq $class ? $soap->clone : { |
5781
|
|
|
|
|
|
|
_transport => SOAP::Transport->new, |
5782
|
|
|
|
|
|
|
_serializer => WSRF::WSRFSerializer->new, |
5783
|
|
|
|
|
|
|
_deserializer => WSRF::Deserializer->new, |
5784
|
|
|
|
|
|
|
_packager => SOAP::Packager::MIME->new, |
5785
|
|
|
|
|
|
|
_schema => undef, |
5786
|
|
|
|
|
|
|
_wsaddress => undef, |
5787
|
|
|
|
|
|
|
_autoresult => 0, |
5788
|
|
|
|
|
|
|
_on_action => sub { sprintf '"%s#%s"', shift || '', shift }, |
5789
|
|
|
|
|
|
|
_on_fault => sub { |
5790
|
|
|
|
|
|
|
ref $_[1] ? return $_[1] |
5791
|
|
|
|
|
|
|
: Carp::croak $_[0]->transport->is_success ? $_[1] |
5792
|
|
|
|
|
|
|
: $_[0]->transport->status; |
5793
|
|
|
|
|
|
|
}, |
5794
|
|
|
|
|
|
|
}; |
5795
|
|
|
|
|
|
|
bless $self => $class; |
5796
|
|
|
|
|
|
|
$self->on_nonserialized( $self->on_nonserialized |
5797
|
|
|
|
|
|
|
|| $self->serializer->on_nonserialized ); |
5798
|
|
|
|
|
|
|
SOAP::Trace::objects('()'); |
5799
|
|
|
|
|
|
|
} |
5800
|
|
|
|
|
|
|
|
5801
|
|
|
|
|
|
|
Carp::carp "Odd (wrong?) number of parameters in new()" |
5802
|
|
|
|
|
|
|
if $^W && ( @_ & 1 ); |
5803
|
|
|
|
|
|
|
while (@_) { |
5804
|
|
|
|
|
|
|
my ( $method, $params ) = splice( @_, 0, 2 ); |
5805
|
|
|
|
|
|
|
$self->can($method) |
5806
|
|
|
|
|
|
|
? $self->$method( ref $params eq 'ARRAY' ? @$params : $params ) |
5807
|
|
|
|
|
|
|
: $^W && Carp::carp "Unrecognized parameter '$method' in new()"; |
5808
|
|
|
|
|
|
|
} |
5809
|
|
|
|
|
|
|
|
5810
|
|
|
|
|
|
|
return $self; |
5811
|
|
|
|
|
|
|
} |
5812
|
|
|
|
|
|
|
|
5813
|
|
|
|
|
|
|
sub init_context { |
5814
|
|
|
|
|
|
|
my $self = shift->new; |
5815
|
|
|
|
|
|
|
$self->{'_deserializer'}->{'_context'} = $self; |
5816
|
|
|
|
|
|
|
$self->{'_serializer'}->{'_context'} = $self; |
5817
|
|
|
|
|
|
|
} |
5818
|
|
|
|
|
|
|
|
5819
|
|
|
|
|
|
|
sub destroy_context { |
5820
|
|
|
|
|
|
|
my $self = shift; |
5821
|
|
|
|
|
|
|
delete( $self->{'_deserializer'}->{'_context'} ); |
5822
|
|
|
|
|
|
|
delete( $self->{'_serializer'}->{'_context'} ); |
5823
|
|
|
|
|
|
|
} |
5824
|
|
|
|
|
|
|
|
5825
|
|
|
|
|
|
|
# Naming? wsdl_parser |
5826
|
|
|
|
|
|
|
sub schema { |
5827
|
|
|
|
|
|
|
my $self = shift; |
5828
|
|
|
|
|
|
|
if (@_) { |
5829
|
|
|
|
|
|
|
$self->{'_schema'} = shift; |
5830
|
|
|
|
|
|
|
return $self; |
5831
|
|
|
|
|
|
|
} else { |
5832
|
|
|
|
|
|
|
if ( !defined $self->{'_schema'} ) { |
5833
|
|
|
|
|
|
|
$self->{'_schema'} = SOAP::Schema->new; |
5834
|
|
|
|
|
|
|
} |
5835
|
|
|
|
|
|
|
return $self->{'_schema'}; |
5836
|
|
|
|
|
|
|
} |
5837
|
|
|
|
|
|
|
} |
5838
|
|
|
|
|
|
|
|
5839
|
|
|
|
|
|
|
sub BEGIN { |
5840
|
|
|
|
|
|
|
no strict 'refs'; |
5841
|
|
|
|
|
|
|
for my $method (qw(serializer deserializer)) { |
5842
|
|
|
|
|
|
|
my $field = '_' . $method; |
5843
|
|
|
|
|
|
|
*$method = sub { |
5844
|
|
|
|
|
|
|
my $self = shift->new; |
5845
|
|
|
|
|
|
|
if (@_) { |
5846
|
|
|
|
|
|
|
my $context = |
5847
|
|
|
|
|
|
|
$self->{$field}->{'_context'}; # save the old context |
5848
|
|
|
|
|
|
|
$self->{$field} = shift; |
5849
|
|
|
|
|
|
|
$self->{$field}->{'_context'} = |
5850
|
|
|
|
|
|
|
$context; # restore the old context |
5851
|
|
|
|
|
|
|
return $self; |
5852
|
|
|
|
|
|
|
} else { |
5853
|
|
|
|
|
|
|
return $self->{$field}; |
5854
|
|
|
|
|
|
|
} |
5855
|
|
|
|
|
|
|
} |
5856
|
|
|
|
|
|
|
} |
5857
|
|
|
|
|
|
|
for my $method ( |
5858
|
|
|
|
|
|
|
qw(endpoint transport outputxml autoresult packager wsaddress)) |
5859
|
|
|
|
|
|
|
{ |
5860
|
|
|
|
|
|
|
my $field = '_' . $method; |
5861
|
|
|
|
|
|
|
*$method = sub { |
5862
|
|
|
|
|
|
|
my $self = shift->new; |
5863
|
|
|
|
|
|
|
@_ |
5864
|
|
|
|
|
|
|
? ( $self->{$field} = shift, return $self ) |
5865
|
|
|
|
|
|
|
: return $self->{$field}; |
5866
|
|
|
|
|
|
|
} |
5867
|
|
|
|
|
|
|
} |
5868
|
|
|
|
|
|
|
for my $method (qw(on_action on_fault on_nonserialized)) { |
5869
|
|
|
|
|
|
|
my $field = '_' . $method; |
5870
|
|
|
|
|
|
|
*$method = sub { |
5871
|
|
|
|
|
|
|
my $self = shift->new; |
5872
|
|
|
|
|
|
|
return $self->{$field} unless @_; |
5873
|
|
|
|
|
|
|
local $@; |
5874
|
|
|
|
|
|
|
|
5875
|
|
|
|
|
|
|
# commented out because that 'eval' was unsecure |
5876
|
|
|
|
|
|
|
# > ref $_[0] eq 'CODE' ? shift : eval shift; |
5877
|
|
|
|
|
|
|
# Am I paranoid enough? |
5878
|
|
|
|
|
|
|
$self->{$field} = shift; |
5879
|
|
|
|
|
|
|
Carp::croak $@ if $@; |
5880
|
|
|
|
|
|
|
Carp::croak |
5881
|
|
|
|
|
|
|
"$method() expects subroutine (CODE) or string that evaluates into subroutine (CODE)" |
5882
|
|
|
|
|
|
|
unless ref $self->{$field} eq 'CODE'; |
5883
|
|
|
|
|
|
|
return $self; |
5884
|
|
|
|
|
|
|
} |
5885
|
|
|
|
|
|
|
} |
5886
|
|
|
|
|
|
|
|
5887
|
|
|
|
|
|
|
# SOAP::Transport Shortcuts |
5888
|
|
|
|
|
|
|
# TODO - deprecate proxy() in favor of new language endpoint_url() |
5889
|
|
|
|
|
|
|
for my $method (qw(proxy)) { |
5890
|
|
|
|
|
|
|
*$method = sub { |
5891
|
|
|
|
|
|
|
my $self = shift->new; |
5892
|
|
|
|
|
|
|
if (@_) { |
5893
|
|
|
|
|
|
|
my $endpoint = shift @_; |
5894
|
|
|
|
|
|
|
if ( UNIVERSAL::isa( $endpoint => 'WSRF::WS_Address' ) ) { |
5895
|
|
|
|
|
|
|
$self->{_wsaddress} = $endpoint; |
5896
|
|
|
|
|
|
|
$endpoint = $endpoint->Address(); |
5897
|
|
|
|
|
|
|
} |
5898
|
|
|
|
|
|
|
$self->transport->$method( $endpoint, @_ ); |
5899
|
|
|
|
|
|
|
return $self; |
5900
|
|
|
|
|
|
|
} |
5901
|
|
|
|
|
|
|
return $self->transport->$method(); |
5902
|
|
|
|
|
|
|
} |
5903
|
|
|
|
|
|
|
} |
5904
|
|
|
|
|
|
|
|
5905
|
|
|
|
|
|
|
# SOAP::Seriailizer Shortcuts |
5906
|
|
|
|
|
|
|
for my $method ( |
5907
|
|
|
|
|
|
|
qw(autotype readable envprefix encodingStyle |
5908
|
|
|
|
|
|
|
encprefix multirefinplace encoding typelookup uri |
5909
|
|
|
|
|
|
|
header maptype xmlschema use_prefix ns default_ns) |
5910
|
|
|
|
|
|
|
) |
5911
|
|
|
|
|
|
|
{ |
5912
|
|
|
|
|
|
|
*$method = sub { |
5913
|
|
|
|
|
|
|
my $self = shift->new; |
5914
|
|
|
|
|
|
|
@_ |
5915
|
|
|
|
|
|
|
? ( $self->serializer->$method(@_), return $self ) |
5916
|
|
|
|
|
|
|
: return $self->serializer->$method(); |
5917
|
|
|
|
|
|
|
} |
5918
|
|
|
|
|
|
|
} |
5919
|
|
|
|
|
|
|
|
5920
|
|
|
|
|
|
|
# SOAP::Schema Shortcuts |
5921
|
|
|
|
|
|
|
for my $method (qw(cache_dir cache_ttl)) { |
5922
|
|
|
|
|
|
|
*$method = sub { |
5923
|
|
|
|
|
|
|
my $self = shift->new; |
5924
|
|
|
|
|
|
|
@_ |
5925
|
|
|
|
|
|
|
? ( $self->schema->$method(@_), return $self ) |
5926
|
|
|
|
|
|
|
: return $self->schema->$method(); |
5927
|
|
|
|
|
|
|
} |
5928
|
|
|
|
|
|
|
} |
5929
|
|
|
|
|
|
|
} |
5930
|
|
|
|
|
|
|
|
5931
|
|
|
|
|
|
|
sub parts { |
5932
|
|
|
|
|
|
|
my $self = shift; |
5933
|
|
|
|
|
|
|
$self->packager->parts(@_); |
5934
|
|
|
|
|
|
|
return $self; |
5935
|
|
|
|
|
|
|
} |
5936
|
|
|
|
|
|
|
|
5937
|
|
|
|
|
|
|
# Naming? wsdl |
5938
|
|
|
|
|
|
|
sub service { |
5939
|
|
|
|
|
|
|
my $self = shift->new; |
5940
|
|
|
|
|
|
|
return $self->{'_service'} unless @_; |
5941
|
|
|
|
|
|
|
$self->schema->schema_url( $self->{'_service'} = shift ); |
5942
|
|
|
|
|
|
|
my %services = %{ $self->schema->parse(@_)->load->services }; |
5943
|
|
|
|
|
|
|
|
5944
|
|
|
|
|
|
|
Carp::croak |
5945
|
|
|
|
|
|
|
"More than one service in service description. Service and port names have to be specified\n" |
5946
|
|
|
|
|
|
|
if keys %services > 1; |
5947
|
|
|
|
|
|
|
my $service = ( keys %services )[0]->new; |
5948
|
|
|
|
|
|
|
return $service; |
5949
|
|
|
|
|
|
|
} |
5950
|
|
|
|
|
|
|
|
5951
|
|
|
|
|
|
|
sub AUTOLOAD { |
5952
|
|
|
|
|
|
|
my $method = substr( $AUTOLOAD, rindex( $AUTOLOAD, '::' ) + 2 ); |
5953
|
|
|
|
|
|
|
return if $method eq 'DESTROY'; |
5954
|
|
|
|
|
|
|
|
5955
|
|
|
|
|
|
|
ref $_[0] |
5956
|
|
|
|
|
|
|
or Carp::croak qq!Can\'t locate class method "$method" via package \"! |
5957
|
|
|
|
|
|
|
. __PACKAGE__ . '\"'; |
5958
|
|
|
|
|
|
|
|
5959
|
|
|
|
|
|
|
no strict 'refs'; |
5960
|
|
|
|
|
|
|
*$AUTOLOAD = sub { |
5961
|
|
|
|
|
|
|
my $self = shift; |
5962
|
|
|
|
|
|
|
my $som = $self->call( $method => @_ ); |
5963
|
|
|
|
|
|
|
return $self->autoresult |
5964
|
|
|
|
|
|
|
&& UNIVERSAL::isa( $som => 'SOAP::SOM' ) |
5965
|
|
|
|
|
|
|
? wantarray ? $som->paramsall : $som->result |
5966
|
|
|
|
|
|
|
: $som; |
5967
|
|
|
|
|
|
|
}; |
5968
|
|
|
|
|
|
|
goto &$AUTOLOAD; |
5969
|
|
|
|
|
|
|
} |
5970
|
|
|
|
|
|
|
|
5971
|
|
|
|
|
|
|
sub call { |
5972
|
|
|
|
|
|
|
SOAP::Trace::trace('()'); |
5973
|
|
|
|
|
|
|
my $self = shift; |
5974
|
|
|
|
|
|
|
|
5975
|
|
|
|
|
|
|
if ( |
5976
|
|
|
|
|
|
|
!( |
5977
|
|
|
|
|
|
|
defined $self->proxy |
5978
|
|
|
|
|
|
|
&& UNIVERSAL::isa( $self->proxy => 'SOAP::Client' ) |
5979
|
|
|
|
|
|
|
) |
5980
|
|
|
|
|
|
|
&& defined( $self->wsaddress ) |
5981
|
|
|
|
|
|
|
&& UNIVERSAL::isa( $self->wsaddress => 'WSRF::WS_Address' ) |
5982
|
|
|
|
|
|
|
) |
5983
|
|
|
|
|
|
|
{ |
5984
|
|
|
|
|
|
|
$self->proxy( $self->wsaddress->Address() ); |
5985
|
|
|
|
|
|
|
} |
5986
|
|
|
|
|
|
|
|
5987
|
|
|
|
|
|
|
# Why is this here? Can't call be null? Indicating that there are no input arguments? |
5988
|
|
|
|
|
|
|
#return $self->{_call} unless @_; |
5989
|
|
|
|
|
|
|
die |
5990
|
|
|
|
|
|
|
"A service address has not been specified either by using SOAP::Lite->proxy() or a service description)\n" |
5991
|
|
|
|
|
|
|
unless defined $self->proxy |
5992
|
|
|
|
|
|
|
&& UNIVERSAL::isa( $self->proxy => 'SOAP::Client' ); |
5993
|
|
|
|
|
|
|
|
5994
|
|
|
|
|
|
|
$self->init_context(); |
5995
|
|
|
|
|
|
|
my $serializer = $self->serializer; |
5996
|
|
|
|
|
|
|
$serializer->on_nonserialized( $self->on_nonserialized ); |
5997
|
|
|
|
|
|
|
if ( defined $self->wsaddress ) { |
5998
|
|
|
|
|
|
|
my $header = |
5999
|
|
|
|
|
|
|
"" |
6000
|
|
|
|
|
|
|
. scalar( $self->on_action->( $serializer->uriformethod( $_[0] ) ) ) |
6001
|
|
|
|
|
|
|
. ""; |
6002
|
|
|
|
|
|
|
$header .= |
6003
|
|
|
|
|
|
|
"" . $self->wsaddress->Address() . ""; |
6004
|
|
|
|
|
|
|
$header .= |
6005
|
|
|
|
|
|
|
"" |
6006
|
|
|
|
|
|
|
. $self->wsaddress->MessageID() |
6007
|
|
|
|
|
|
|
. ""; |
6008
|
|
|
|
|
|
|
$header .= |
6009
|
|
|
|
|
|
|
$self->wsaddress->serializeReferenceParameters() |
6010
|
|
|
|
|
|
|
? $self->wsaddress->serializeReferenceParameters() |
6011
|
|
|
|
|
|
|
: ''; |
6012
|
|
|
|
|
|
|
|
6013
|
|
|
|
|
|
|
#bug fix - John Newman |
6014
|
|
|
|
|
|
|
$header .= |
6015
|
|
|
|
|
|
|
"$WSRF::Constants::WSA_ANON"; |
6016
|
|
|
|
|
|
|
@_ = ( @_, SOAP::Header->value($header)->type('xml') ); |
6017
|
|
|
|
|
|
|
} |
6018
|
|
|
|
|
|
|
|
6019
|
|
|
|
|
|
|
my $response = $self->transport->send_receive( |
6020
|
|
|
|
|
|
|
context => $self, # this is provided for context |
6021
|
|
|
|
|
|
|
endpoint => $self->endpoint, |
6022
|
|
|
|
|
|
|
action => |
6023
|
|
|
|
|
|
|
scalar( $self->on_action->( $serializer->uriformethod( $_[0] ) ) ), |
6024
|
|
|
|
|
|
|
|
6025
|
|
|
|
|
|
|
# leave only parameters so we can later update them if required |
6026
|
|
|
|
|
|
|
envelope => $serializer->envelope( method => shift, @_ ), |
6027
|
|
|
|
|
|
|
|
6028
|
|
|
|
|
|
|
# envelope => $serializer->envelope(method => shift, @_), |
6029
|
|
|
|
|
|
|
encoding => $serializer->encoding, |
6030
|
|
|
|
|
|
|
parts => @{ $self->packager->parts } ? $self->packager->parts : undef, |
6031
|
|
|
|
|
|
|
); |
6032
|
|
|
|
|
|
|
|
6033
|
|
|
|
|
|
|
#BUG fix by Luke AT yahoo.com |
6034
|
|
|
|
|
|
|
#return $response if $self->outputxml; |
6035
|
|
|
|
|
|
|
# if ( $self->outputxml ) { $self->destroy_context(); return $response; } |
6036
|
|
|
|
|
|
|
|
6037
|
|
|
|
|
|
|
# deserialize and store result |
6038
|
|
|
|
|
|
|
my $result = $self->{'_call'} = |
6039
|
|
|
|
|
|
|
eval { $self->deserializer->deserialize($response) } |
6040
|
|
|
|
|
|
|
if $response; |
6041
|
|
|
|
|
|
|
|
6042
|
|
|
|
|
|
|
if ( |
6043
|
|
|
|
|
|
|
!$self->transport->is_success || # transport fault |
6044
|
|
|
|
|
|
|
$@ || # not deserializible |
6045
|
|
|
|
|
|
|
# fault message even if transport OK |
6046
|
|
|
|
|
|
|
# or no transport error (for example, fo TCP, POP3, IO implementations) |
6047
|
|
|
|
|
|
|
UNIVERSAL::isa( $result => 'SOAP::SOM' ) && $result->fault |
6048
|
|
|
|
|
|
|
) |
6049
|
|
|
|
|
|
|
{ |
6050
|
|
|
|
|
|
|
return $self->{'_call'} = |
6051
|
|
|
|
|
|
|
( $self->on_fault->( $self, $@ ? $@ . ( $response || '' ) : $result ) |
6052
|
|
|
|
|
|
|
|| $result ); |
6053
|
|
|
|
|
|
|
} |
6054
|
|
|
|
|
|
|
|
6055
|
|
|
|
|
|
|
return unless $response; # nothing to do for one-ways |
6056
|
|
|
|
|
|
|
|
6057
|
|
|
|
|
|
|
# little bit tricky part that binds in/out parameters |
6058
|
|
|
|
|
|
|
if ( UNIVERSAL::isa( $result => 'SOAPSOM' ) |
6059
|
|
|
|
|
|
|
&& ( $result->paramsout || $result->headers ) |
6060
|
|
|
|
|
|
|
&& $serializer->signature ) |
6061
|
|
|
|
|
|
|
{ |
6062
|
|
|
|
|
|
|
my $num = 0; |
6063
|
|
|
|
|
|
|
my %signatures = map { $_ => $num++ } @{ $serializer->signature }; |
6064
|
|
|
|
|
|
|
for ( $result->dataof(SOAP::SOM::paramsout), |
6065
|
|
|
|
|
|
|
$result->dataof(SOAP::SOM::headers) ) |
6066
|
|
|
|
|
|
|
{ |
6067
|
|
|
|
|
|
|
my $signature = join $;, $_->name, $_->type || ''; |
6068
|
|
|
|
|
|
|
if ( exists $signatures{$signature} ) { |
6069
|
|
|
|
|
|
|
my $param = $signatures{$signature}; |
6070
|
|
|
|
|
|
|
my ($value) = $_->value; # take first value |
6071
|
|
|
|
|
|
|
UNIVERSAL::isa( $_[$param] => 'SOAP::Data' ) |
6072
|
|
|
|
|
|
|
? $_[$param]->SOAP::Data::value($value) |
6073
|
|
|
|
|
|
|
: UNIVERSAL::isa( $_[$param] => 'ARRAY' ) |
6074
|
|
|
|
|
|
|
? ( @{ $_[$param] } = @$value ) |
6075
|
|
|
|
|
|
|
: UNIVERSAL::isa( $_[$param] => 'HASH' ) |
6076
|
|
|
|
|
|
|
? ( %{ $_[$param] } = %$value ) |
6077
|
|
|
|
|
|
|
: UNIVERSAL::isa( $_[$param] => 'SCALAR' ) |
6078
|
|
|
|
|
|
|
? ( ${ $_[$param] } = $$value ) |
6079
|
|
|
|
|
|
|
: ( $_[$param] = $value ); |
6080
|
|
|
|
|
|
|
} |
6081
|
|
|
|
|
|
|
} |
6082
|
|
|
|
|
|
|
} |
6083
|
|
|
|
|
|
|
$self->destroy_context(); |
6084
|
|
|
|
|
|
|
|
6085
|
|
|
|
|
|
|
if ( $self->outputxml ) { |
6086
|
|
|
|
|
|
|
return ($result, $response); |
6087
|
|
|
|
|
|
|
} else { |
6088
|
|
|
|
|
|
|
return $result; |
6089
|
|
|
|
|
|
|
} |
6090
|
|
|
|
|
|
|
} # end of call() |
6091
|
|
|
|
|
|
|
|
6092
|
|
|
|
|
|
|
# ====================================================================== |
6093
|
|
|
|
|
|
|
|
6094
|
|
|
|
|
|
|
package WSRF::WSS; |
6095
|
|
|
|
|
|
|
|
6096
|
|
|
|
|
|
|
=pod |
6097
|
|
|
|
|
|
|
|
6098
|
|
|
|
|
|
|
=head1 WSRF::WSS |
6099
|
|
|
|
|
|
|
|
6100
|
|
|
|
|
|
|
Provides support for digitally signing SOAP messages according to the |
6101
|
|
|
|
|
|
|
WS-Security specification. |
6102
|
|
|
|
|
|
|
|
6103
|
|
|
|
|
|
|
=head2 METHODS |
6104
|
|
|
|
|
|
|
|
6105
|
|
|
|
|
|
|
=over |
6106
|
|
|
|
|
|
|
|
6107
|
|
|
|
|
|
|
=item sign |
6108
|
|
|
|
|
|
|
|
6109
|
|
|
|
|
|
|
=item verify |
6110
|
|
|
|
|
|
|
|
6111
|
|
|
|
|
|
|
=back |
6112
|
|
|
|
|
|
|
|
6113
|
|
|
|
|
|
|
=cut |
6114
|
|
|
|
|
|
|
|
6115
|
|
|
|
|
|
|
%WSRF::WSS::ASNMTAP = (); |
6116
|
|
|
|
|
|
|
$WSRF::WSS::ASNMTAP{UsernameToken} = undef; |
6117
|
|
|
|
|
|
|
$WSRF::WSS::ASNMTAP{SAML} = undef; |
6118
|
|
|
|
|
|
|
$WSRF::WSS::ASNMTAP{Assertion} = undef; |
6119
|
|
|
|
|
|
|
$WSRF::WSS::ASNMTAP{SAMLAssertionID} = undef; |
6120
|
|
|
|
|
|
|
|
6121
|
|
|
|
|
|
|
%WSRF::WSS::ID = (); |
6122
|
|
|
|
|
|
|
$WSRF::WSS::ID{X509Token} = "X509Token-" . time(); |
6123
|
|
|
|
|
|
|
$WSRF::WSS::ID{TimeStamp} = "TimeStamp-" . time(); |
6124
|
|
|
|
|
|
|
$WSRF::WSS::ID{myBody} = "myBody-" . time(); |
6125
|
|
|
|
|
|
|
|
6126
|
|
|
|
|
|
|
%WSRF::WSS::Sign = (); |
6127
|
|
|
|
|
|
|
$WSRF::WSS::Sign{BinarySecurityToken} = 1; |
6128
|
|
|
|
|
|
|
$WSRF::WSS::Sign{Timestamp} = 1; |
6129
|
|
|
|
|
|
|
$WSRF::WSS::Sign{MessageID} = 1; |
6130
|
|
|
|
|
|
|
$WSRF::WSS::Sign{To} = 1; |
6131
|
|
|
|
|
|
|
$WSRF::WSS::Sign{Action} = 1; |
6132
|
|
|
|
|
|
|
$WSRF::WSS::Sign{From} = 1; |
6133
|
|
|
|
|
|
|
$WSRF::WSS::Sign{RelatesTo} = 1; |
6134
|
|
|
|
|
|
|
$WSRF::WSS::Sign{ReplyTo} = 1; |
6135
|
|
|
|
|
|
|
$WSRF::WSS::Sign{Body} = 1; |
6136
|
|
|
|
|
|
|
|
6137
|
|
|
|
|
|
|
%WSRF::WSS::ID_Xpath = (); |
6138
|
|
|
|
|
|
|
|
6139
|
|
|
|
|
|
|
#XPaths to the parts of the SOAP message we want to sign |
6140
|
|
|
|
|
|
|
$WSRF::WSS::sec_xpath = |
6141
|
|
|
|
|
|
|
'(//. | //@* | //namespace::*)[ancestor-or-self::wsse:BinarySecurityToken]'; |
6142
|
|
|
|
|
|
|
|
6143
|
|
|
|
|
|
|
#$WSRF::WSS::sec_xpath = |
6144
|
|
|
|
|
|
|
# '
6145
|
|
|
|
|
|
|
# . $WSRF::Constants::WSSE |
6146
|
|
|
|
|
|
|
# . '">(//. | //@* | //namespace::*)[ancestor-or-self::wsse:BinarySecurityToken]'; |
6147
|
|
|
|
|
|
|
|
6148
|
|
|
|
|
|
|
$WSRF::WSS::si_xpath = |
6149
|
|
|
|
|
|
|
# '(//. | //@* | //namespace::*)[ancestor-or-self::ds:SignedInfo]'; |
6150
|
|
|
|
|
|
|
'(//. | //@* | //namespace::*)[ancestor-or-self::ds:SignedInfo]'; |
6151
|
|
|
|
|
|
|
$WSRF::WSS::timestamp_xpath = |
6152
|
|
|
|
|
|
|
# '
6153
|
|
|
|
|
|
|
# . $WSRF::Constants::WSU |
6154
|
|
|
|
|
|
|
# . '">(//. | //@* | //namespace::*)[ancestor-or-self::wsu:Timestamp]'; |
6155
|
|
|
|
|
|
|
'(//. | //@* | //namespace::*)[ancestor-or-self::wsu:Timestamp]'; |
6156
|
|
|
|
|
|
|
|
6157
|
|
|
|
|
|
|
$WSRF::WSS::ID_Xpath{MessageID} = |
6158
|
|
|
|
|
|
|
# '
6159
|
|
|
|
|
|
|
# . $WSRF::Constants::WSA |
6160
|
|
|
|
|
|
|
# . '">(//. | //@* | //namespace::*)[ancestor-or-self::wsa:MessageID]'; |
6161
|
|
|
|
|
|
|
'(//. | //@* | //namespace::*)[ancestor-or-self::wsa:MessageID]'; |
6162
|
|
|
|
|
|
|
|
6163
|
|
|
|
|
|
|
$WSRF::WSS::ID_Xpath{To} = |
6164
|
|
|
|
|
|
|
# '
6165
|
|
|
|
|
|
|
# . $WSRF::Constants::WSA |
6166
|
|
|
|
|
|
|
# . '">(//. | //@* | //namespace::*)[ancestor-or-self::wsa:To]'; |
6167
|
|
|
|
|
|
|
'(//. | //@* | //namespace::*)[ancestor-or-self::wsa:To]'; |
6168
|
|
|
|
|
|
|
|
6169
|
|
|
|
|
|
|
$WSRF::WSS::ID_Xpath{Action} = |
6170
|
|
|
|
|
|
|
# '
6171
|
|
|
|
|
|
|
# . $WSRF::Constants::WSA |
6172
|
|
|
|
|
|
|
# . '">(//. | //@* | //namespace::*)[ancestor-or-self::wsa:Action]'; |
6173
|
|
|
|
|
|
|
'(//. | //@* | //namespace::*)[ancestor-or-self::wsa:Action]'; |
6174
|
|
|
|
|
|
|
|
6175
|
|
|
|
|
|
|
$WSRF::WSS::ID_Xpath{From} = |
6176
|
|
|
|
|
|
|
# '
6177
|
|
|
|
|
|
|
# . $WSRF::Constants::WSA |
6178
|
|
|
|
|
|
|
# . '">(//. | //@* | //namespace::*)[ancestor-or-self::wsa:From]'; |
6179
|
|
|
|
|
|
|
'(//. | //@* | //namespace::*)[ancestor-or-self::wsa:From]'; |
6180
|
|
|
|
|
|
|
|
6181
|
|
|
|
|
|
|
$WSRF::WSS::ID_Xpath{ReplyTo} = |
6182
|
|
|
|
|
|
|
# '
6183
|
|
|
|
|
|
|
# . $WSRF::Constants::WSA |
6184
|
|
|
|
|
|
|
# . '">(//. | //@* | //namespace::*)[ancestor-or-self::wsa:ReplyTo]'; |
6185
|
|
|
|
|
|
|
'(//. | //@* | //namespace::*)[ancestor-or-self::wsa:ReplyTo]'; |
6186
|
|
|
|
|
|
|
|
6187
|
|
|
|
|
|
|
$WSRF::WSS::ID_Xpath{RelatesTo} = |
6188
|
|
|
|
|
|
|
# '
6189
|
|
|
|
|
|
|
# . $WSRF::Constants::WSA |
6190
|
|
|
|
|
|
|
# . '">(//. | //@* | //namespace::*)[ancestor-or-self::wsa:RelatesTo]'; |
6191
|
|
|
|
|
|
|
'(//. | //@* | //namespace::*)[ancestor-or-self::wsa:RelatesTo]'; |
6192
|
|
|
|
|
|
|
|
6193
|
|
|
|
|
|
|
$WSRF::WSS::body_xpath = |
6194
|
|
|
|
|
|
|
#"" |
6195
|
|
|
|
|
|
|
# . '(//. | //@* | //namespace::*)' |
6196
|
|
|
|
|
|
|
# . "[ancestor-or-self::$SOAP::Constants::PREFIX_ENV:Body]"; |
6197
|
|
|
|
|
|
|
'(//. | //@* | //namespace::*)' . "[ancestor-or-self::$SOAP::Constants::PREFIX_ENV:Body]"; |
6198
|
|
|
|
|
|
|
|
6199
|
|
|
|
|
|
|
$WSRF::WSS::priv_key = undef; |
6200
|
|
|
|
|
|
|
$WSRF::WSS::pub_key = undef; |
6201
|
|
|
|
|
|
|
|
6202
|
|
|
|
|
|
|
sub load_priv_key { |
6203
|
|
|
|
|
|
|
|
6204
|
|
|
|
|
|
|
if ( defined($WSRF::WSS::priv_key) ) { |
6205
|
|
|
|
|
|
|
if ( ref($WSRF::WSS::priv_key) eq 'CODE' ) { |
6206
|
|
|
|
|
|
|
return $WSRF::WSS::priv_key->(); |
6207
|
|
|
|
|
|
|
} else { |
6208
|
|
|
|
|
|
|
return $WSRF::WSS::priv_key; |
6209
|
|
|
|
|
|
|
} |
6210
|
|
|
|
|
|
|
} |
6211
|
|
|
|
|
|
|
|
6212
|
|
|
|
|
|
|
eval { require Crypt::OpenSSL::RSA }; |
6213
|
|
|
|
|
|
|
die "Failed to access class Crypt::OpenSSL::RSA: $@" if $@; |
6214
|
|
|
|
|
|
|
|
6215
|
|
|
|
|
|
|
my $key_file_name = |
6216
|
|
|
|
|
|
|
$ENV{HTTPS_KEY_FILE} ? $ENV{HTTPS_KEY_FILE} : die "No Private Key\n"; |
6217
|
|
|
|
|
|
|
open( PRIVKEY, $key_file_name ) |
6218
|
|
|
|
|
|
|
|| die("Could not open file $key_file_name"); |
6219
|
|
|
|
|
|
|
my $privkey = join "", ; |
6220
|
|
|
|
|
|
|
close(PRIVKEY); |
6221
|
|
|
|
|
|
|
Crypt::OpenSSL::RSA->new_private_key($privkey); |
6222
|
|
|
|
|
|
|
} |
6223
|
|
|
|
|
|
|
|
6224
|
|
|
|
|
|
|
#returns the cert block between the begin and end delimiters |
6225
|
|
|
|
|
|
|
sub load_cert { |
6226
|
|
|
|
|
|
|
|
6227
|
|
|
|
|
|
|
if ( defined($WSRF::WSS::pub_key) ) { |
6228
|
|
|
|
|
|
|
if ( ref($WSRF::WSS::pub_key) eq 'CODE' ) { |
6229
|
|
|
|
|
|
|
return $WSRF::WSS::pub_key->(); |
6230
|
|
|
|
|
|
|
} else { |
6231
|
|
|
|
|
|
|
return $WSRF::WSS::pub_key; |
6232
|
|
|
|
|
|
|
} |
6233
|
|
|
|
|
|
|
} |
6234
|
|
|
|
|
|
|
|
6235
|
|
|
|
|
|
|
my $cert_file_name = |
6236
|
|
|
|
|
|
|
$ENV{HTTPS_CERT_FILE} ? $ENV{HTTPS_CERT_FILE} : die "No Public Key\n"; |
6237
|
|
|
|
|
|
|
open( CERT, $cert_file_name ) |
6238
|
|
|
|
|
|
|
|| die("Could not open certificate file $cert_file_name"); |
6239
|
|
|
|
|
|
|
my $start = 0; |
6240
|
|
|
|
|
|
|
my $cert = ""; |
6241
|
|
|
|
|
|
|
while () { |
6242
|
|
|
|
|
|
|
if ( !m/-----END CERTIFICATE-----/ && $start == 1 ) { |
6243
|
|
|
|
|
|
|
$cert = $cert . $_; |
6244
|
|
|
|
|
|
|
} |
6245
|
|
|
|
|
|
|
if (/-----BEGIN CERTIFICATE-----/) { |
6246
|
|
|
|
|
|
|
$start = 1; |
6247
|
|
|
|
|
|
|
} |
6248
|
|
|
|
|
|
|
} |
6249
|
|
|
|
|
|
|
close(CERT); |
6250
|
|
|
|
|
|
|
return $cert; |
6251
|
|
|
|
|
|
|
} |
6252
|
|
|
|
|
|
|
|
6253
|
|
|
|
|
|
|
sub sign { |
6254
|
|
|
|
|
|
|
my $envelope = shift; |
6255
|
|
|
|
|
|
|
|
6256
|
|
|
|
|
|
|
eval { require XML::LibXML }; |
6257
|
|
|
|
|
|
|
die "Failed to access class XML::LibXML: $@" if $@; |
6258
|
|
|
|
|
|
|
eval { require MIME::Base64 }; |
6259
|
|
|
|
|
|
|
die "Failed to access class MIME::Base64: $@" if $@; |
6260
|
|
|
|
|
|
|
|
6261
|
|
|
|
|
|
|
#Get Certificate |
6262
|
|
|
|
|
|
|
my $certificate = WSRF::WSS::load_cert(); |
6263
|
|
|
|
|
|
|
|
6264
|
|
|
|
|
|
|
my $header = ""; |
6265
|
|
|
|
|
|
|
|
6266
|
|
|
|
|
|
|
my $for_signing = |
6267
|
|
|
|
|
|
|
'' |
6268
|
|
|
|
|
|
|
. '' |
6269
|
|
|
|
|
|
|
. ''; |
6270
|
|
|
|
|
|
|
|
6271
|
|
|
|
|
|
|
#search through the envelope for things to sign |
6272
|
|
|
|
|
|
|
foreach my $key ( keys(%WSRF::WSS::ID_Xpath) ) { |
6273
|
|
|
|
|
|
|
next unless (defined $WSRF::WSS::ID_Xpath{$key}); |
6274
|
|
|
|
|
|
|
$for_signing .= |
6275
|
|
|
|
|
|
|
WSRF::WSS::make_token( $envelope, $WSRF::WSS::ID_Xpath{$key}, $key ) |
6276
|
|
|
|
|
|
|
if defined( $WSRF::WSS::Sign{$key} ); |
6277
|
|
|
|
|
|
|
my $parser = XML::LibXML->new(); |
6278
|
|
|
|
|
|
|
my $doc = $parser->parse_string($envelope); |
6279
|
|
|
|
|
|
|
my $canon = undef; |
6280
|
|
|
|
|
|
|
eval {$canon = $doc->toStringEC14N( 0, $WSRF::WSS::ID_Xpath{$key}, [''] );}; |
6281
|
|
|
|
|
|
|
$header .= defined($canon) ? $canon : ""; |
6282
|
|
|
|
|
|
|
} |
6283
|
|
|
|
|
|
|
|
6284
|
|
|
|
|
|
|
$for_signing .= |
6285
|
|
|
|
|
|
|
WSRF::WSS::make_token( $envelope, $WSRF::WSS::body_xpath, $WSRF::WSS::ID{myBody} ) |
6286
|
|
|
|
|
|
|
if defined( $WSRF::WSS::Sign{Body} ); |
6287
|
|
|
|
|
|
|
|
6288
|
|
|
|
|
|
|
#create a security token using the certificate |
6289
|
|
|
|
|
|
|
my $sec_token = |
6290
|
|
|
|
|
|
|
'' |
6291
|
|
|
|
|
|
|
. $certificate |
6292
|
|
|
|
|
|
|
. ''; |
6293
|
|
|
|
|
|
|
if ( defined( $WSRF::WSS::Sign{BinarySecurityToken} ) |
6294
|
|
|
|
|
|
|
&& defined($WSRF::WSS::sec_xpath) ) |
6295
|
|
|
|
|
|
|
{ |
6296
|
|
|
|
|
|
|
$for_signing .= |
6297
|
|
|
|
|
|
|
WSRF::WSS::make_token( $sec_token, $WSRF::WSS::sec_xpath, |
6298
|
|
|
|
|
|
|
$WSRF::WSS::ID{X509Token} ); |
6299
|
|
|
|
|
|
|
} |
6300
|
|
|
|
|
|
|
|
6301
|
|
|
|
|
|
|
#create a timestamp |
6302
|
|
|
|
|
|
|
my $timestamp = ''; |
6303
|
|
|
|
|
|
|
if ( defined($WSRF::WSS::timestamp_xpath) ) { |
6304
|
|
|
|
|
|
|
$timestamp = |
6305
|
|
|
|
|
|
|
''; |
6306
|
|
|
|
|
|
|
$timestamp .= |
6307
|
|
|
|
|
|
|
'' |
6308
|
|
|
|
|
|
|
. WSRF::Time::ConvertEpochTimeToString(time) |
6309
|
|
|
|
|
|
|
. ''; |
6310
|
|
|
|
|
|
|
$timestamp .= |
6311
|
|
|
|
|
|
|
'' |
6312
|
|
|
|
|
|
|
. WSRF::Time::ConvertEpochTimeToString( time + ($WSRF::TIME::EXPIRES_IN ? $WSRF::TIME::EXPIRES_IN : 60)) |
6313
|
|
|
|
|
|
|
. ''; |
6314
|
|
|
|
|
|
|
|
6315
|
|
|
|
|
|
|
#$timestamp .= '2004-02-07T14:31:59Z'; |
6316
|
|
|
|
|
|
|
#$timestamp .= '2006-02-07T14:36:59Z'; |
6317
|
|
|
|
|
|
|
$timestamp .= ''; |
6318
|
|
|
|
|
|
|
|
6319
|
|
|
|
|
|
|
#canonicalize,digest + Base64 the timestamp |
6320
|
|
|
|
|
|
|
$for_signing .= |
6321
|
|
|
|
|
|
|
WSRF::WSS::make_token( $timestamp, $WSRF::WSS::timestamp_xpath, |
6322
|
|
|
|
|
|
|
$WSRF::WSS::ID{TimeStamp} ) |
6323
|
|
|
|
|
|
|
if defined( $WSRF::WSS::Sign{Timestamp} ); |
6324
|
|
|
|
|
|
|
} |
6325
|
|
|
|
|
|
|
|
6326
|
|
|
|
|
|
|
$for_signing .= ''; |
6327
|
|
|
|
|
|
|
|
6328
|
|
|
|
|
|
|
my $parser = XML::LibXML->new(); |
6329
|
|
|
|
|
|
|
my $doc = $parser->parse_string($for_signing); |
6330
|
|
|
|
|
|
|
my $can_signed_info = $doc->toStringEC14N( 0, $WSRF::WSS::si_xpath, [''] ); |
6331
|
|
|
|
|
|
|
|
6332
|
|
|
|
|
|
|
# print ">>>can_signed>>>>".MIME::Base64::encode(sha1($can_signed_info))."<<<<
|
6333
|
|
|
|
|
|
|
# print ">>>can_signed_info>>>>\n$can_signed_info\n<<<<
|
6334
|
|
|
|
|
|
|
|
6335
|
|
|
|
|
|
|
my $rsa_priv = WSRF::WSS::load_priv_key(); |
6336
|
|
|
|
|
|
|
my $signature = $rsa_priv->sign($can_signed_info); |
6337
|
|
|
|
|
|
|
$signature = MIME::Base64::encode($signature); |
6338
|
|
|
|
|
|
|
|
6339
|
|
|
|
|
|
|
my $sec_token_reference = ''; |
6340
|
|
|
|
|
|
|
|
6341
|
|
|
|
|
|
|
if ( defined $WSRF::WSS::ASNMTAP{Assertion} and $WSRF::WSS::ASNMTAP{SAMLAssertionID} ) { |
6342
|
|
|
|
|
|
|
$sec_token = $WSRF::WSS::ASNMTAP{Assertion}; |
6343
|
|
|
|
|
|
|
$WSRF::WSS::ASNMTAP{Assertion} =~ $WSRF::WSS::ASNMTAP{SAMLAssertionID}; |
6344
|
|
|
|
|
|
|
$sec_token_reference = '' . ( defined $1 ? $1 : '?' ) . ''; |
6345
|
|
|
|
|
|
|
} |
6346
|
|
|
|
|
|
|
|
6347
|
|
|
|
|
|
|
my $extraheader = |
6348
|
|
|
|
|
|
|
'
|
6349
|
|
|
|
|
|
|
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">' |
6350
|
|
|
|
|
|
|
. $sec_token . "\n" |
6351
|
|
|
|
|
|
|
. '' |
6352
|
|
|
|
|
|
|
. $can_signed_info . '' |
6353
|
|
|
|
|
|
|
. $signature . '' |
6354
|
|
|
|
|
|
|
. '' . $sec_token_reference . '' |
6355
|
|
|
|
|
|
|
. ''; |
6356
|
|
|
|
|
|
|
|
6357
|
|
|
|
|
|
|
$extraheader .= $WSRF::WSS::ASNMTAP{UsernameToken} if ( $WSRF::WSS::ASNMTAP{UsernameToken} ); |
6358
|
|
|
|
|
|
|
|
6359
|
|
|
|
|
|
|
if ( defined($WSRF::WSS::timestamp_xpath) ) { |
6360
|
|
|
|
|
|
|
$extraheader .= $timestamp; |
6361
|
|
|
|
|
|
|
} |
6362
|
|
|
|
|
|
|
$extraheader .= ''; |
6363
|
|
|
|
|
|
|
$header = $extraheader . $header; |
6364
|
|
|
|
|
|
|
|
6365
|
|
|
|
|
|
|
$doc = $parser->parse_string($envelope); |
6366
|
|
|
|
|
|
|
my $Body = $doc->toStringEC14N( 0, $WSRF::WSS::body_xpath, ((defined $WSRF::WSS::ASNMTAP{SAML}) ? ['saml', 'samlp'] : [''])); |
6367
|
|
|
|
|
|
|
# TODO: replace ['saml', 'samlp'] with the array created from the content of $WSRF::WSS::ASNMTAP{SAML}!!! |
6368
|
|
|
|
|
|
|
#my $Body = $doc->toStringEC14N( 0, $WSRF::WSS::body_xpath, [''] ); |
6369
|
|
|
|
|
|
|
#my $Body = $doc->toStringC14N(0,$WSRF::WSS::body_xpath); |
6370
|
|
|
|
|
|
|
|
6371
|
|
|
|
|
|
|
#print ">>>header newline body>>>>\n$header\n\n$Body\n<<<< |
6372
|
|
|
|
|
|
|
return $header, $Body; |
6373
|
|
|
|
|
|
|
} |
6374
|
|
|
|
|
|
|
|
6375
|
|
|
|
|
|
|
sub make_token { |
6376
|
|
|
|
|
|
|
my ( $XML, $Path, $ID ) = @_; |
6377
|
|
|
|
|
|
|
|
6378
|
|
|
|
|
|
|
eval { require XML::LibXML }; |
6379
|
|
|
|
|
|
|
die "Failed to access class XML::LibXML: $@" if $@; |
6380
|
|
|
|
|
|
|
eval { require Digest::SHA1 }; |
6381
|
|
|
|
|
|
|
die "Failed to access class Digest::SHA1: $@" if $@; |
6382
|
|
|
|
|
|
|
eval { require MIME::Base64 }; |
6383
|
|
|
|
|
|
|
die "Failed to access class MIME::Base64: $@" if $@; |
6384
|
|
|
|
|
|
|
|
6385
|
|
|
|
|
|
|
# print "make_token $ID\n"; |
6386
|
|
|
|
|
|
|
# print "Xpath=> $Path\n"; |
6387
|
|
|
|
|
|
|
my $parser = XML::LibXML->new(); |
6388
|
|
|
|
|
|
|
my $doc = $parser->parse_string($XML); |
6389
|
|
|
|
|
|
|
my $can_token = undef; |
6390
|
|
|
|
|
|
|
eval {$can_token = $doc->toStringEC14N( 0, $Path, [''] );}; |
6391
|
|
|
|
|
|
|
return '' unless $can_token; |
6392
|
|
|
|
|
|
|
|
6393
|
|
|
|
|
|
|
# print ">>>token-$ID>>>\n$can_token\n<<
|
6394
|
|
|
|
|
|
|
|
6395
|
|
|
|
|
|
|
#take digest of token |
6396
|
|
|
|
|
|
|
my $token_digest = Digest::SHA1::sha1($can_token); |
6397
|
|
|
|
|
|
|
|
6398
|
|
|
|
|
|
|
#base64 encode digest |
6399
|
|
|
|
|
|
|
$token_digest = MIME::Base64::encode($token_digest); |
6400
|
|
|
|
|
|
|
chomp($token_digest); |
6401
|
|
|
|
|
|
|
|
6402
|
|
|
|
|
|
|
#print ">>>>token-$ID-digest>>>".$token_digest."<<
|
6403
|
|
|
|
|
|
|
|
6404
|
|
|
|
|
|
|
return '' |
6405
|
|
|
|
|
|
|
. '' |
6406
|
|
|
|
|
|
|
. '' |
6407
|
|
|
|
|
|
|
#. '' |
6408
|
|
|
|
|
|
|
. '' |
6409
|
|
|
|
|
|
|
. '' |
6410
|
|
|
|
|
|
|
. '' |
6411
|
|
|
|
|
|
|
. $token_digest |
6412
|
|
|
|
|
|
|
. '' |
6413
|
|
|
|
|
|
|
. ''; |
6414
|
|
|
|
|
|
|
|
6415
|
|
|
|
|
|
|
} |
6416
|
|
|
|
|
|
|
|
6417
|
|
|
|
|
|
|
%WSRF::WSS::ThingsThatShouldBeSigned = (); |
6418
|
|
|
|
|
|
|
|
6419
|
|
|
|
|
|
|
$WSRF::WSS::ThingsThatShouldBeSigned{Body} = $SOAP::Constants::NS_ENV; |
6420
|
|
|
|
|
|
|
$WSRF::WSS::Xpath{Body} = $WSRF::WSS::body_xpath; |
6421
|
|
|
|
|
|
|
|
6422
|
|
|
|
|
|
|
$WSRF::WSS::ThingsThatShouldBeSigned{To} = $WSRF::Constants::WSA; |
6423
|
|
|
|
|
|
|
$WSRF::WSS::Xpath{To} = $WSRF::WSS::ID_Xpath{To}; |
6424
|
|
|
|
|
|
|
|
6425
|
|
|
|
|
|
|
$WSRF::WSS::ThingsThatShouldBeSigned{MessageID} = $WSRF::Constants::WSA; |
6426
|
|
|
|
|
|
|
$WSRF::WSS::Xpath{MessageID} = $WSRF::WSS::ID_Xpath{MessageID}; |
6427
|
|
|
|
|
|
|
|
6428
|
|
|
|
|
|
|
$WSRF::WSS::ThingsThatShouldBeSigned{ReplyTo} = $WSRF::Constants::WSA; |
6429
|
|
|
|
|
|
|
$WSRF::WSS::Xpath{ReplyTo} = $WSRF::WSS::ID_Xpath{ReplyTo}; |
6430
|
|
|
|
|
|
|
|
6431
|
|
|
|
|
|
|
$WSRF::WSS::ThingsThatShouldBeSigned{Action} = $WSRF::Constants::WSA; |
6432
|
|
|
|
|
|
|
$WSRF::WSS::Xpath{Action} = $WSRF::WSS::ID_Xpath{Action}; |
6433
|
|
|
|
|
|
|
|
6434
|
|
|
|
|
|
|
$WSRF::WSS::ThingsThatShouldBeSigned{Timestamp} = $WSRF::Constants::WSU; |
6435
|
|
|
|
|
|
|
$WSRF::WSS::Xpath{Timestamp} = $WSRF::WSS::timestamp_xpath; |
6436
|
|
|
|
|
|
|
|
6437
|
|
|
|
|
|
|
$WSRF::WSS::ThingsThatShouldBeSigned{BinarySecurityToken} = |
6438
|
|
|
|
|
|
|
$WSRF::Constants::WSSE; |
6439
|
|
|
|
|
|
|
$WSRF::WSS::Xpath{BinarySecurityToken} = $WSRF::WSS::sec_xpath; |
6440
|
|
|
|
|
|
|
|
6441
|
|
|
|
|
|
|
$WSRF::WSS::ThingsThatShouldBeSigned{From} = $WSRF::Constants::WSA; |
6442
|
|
|
|
|
|
|
$WSRF::WSS::Xpath{From} = $WSRF::WSS::ID_Xpath{From}; |
6443
|
|
|
|
|
|
|
|
6444
|
|
|
|
|
|
|
$WSRF::WSS::ThingsThatShouldBeSigned{RelatesTo} = $WSRF::Constants::WSA; |
6445
|
|
|
|
|
|
|
$WSRF::WSS::Xpath{RelatesTo} = $WSRF::WSS::ID_Xpath{RelatesTo}; |
6446
|
|
|
|
|
|
|
|
6447
|
|
|
|
|
|
|
sub verify { |
6448
|
|
|
|
|
|
|
my $envelope = shift; |
6449
|
|
|
|
|
|
|
|
6450
|
|
|
|
|
|
|
eval { require XML::LibXML }; |
6451
|
|
|
|
|
|
|
die "Failed to access class XML::LibXML: $@" if $@; |
6452
|
|
|
|
|
|
|
eval { require Digest::SHA1 }; |
6453
|
|
|
|
|
|
|
die "Failed to access class Digest::SHA1: $@" if $@; |
6454
|
|
|
|
|
|
|
eval { require Crypt::OpenSSL::RSA }; |
6455
|
|
|
|
|
|
|
die "Failed to access class Crypt::OpenSSL::RSA: $@" if $@; |
6456
|
|
|
|
|
|
|
eval { require Crypt::OpenSSL::X509 }; |
6457
|
|
|
|
|
|
|
die "Failed to access class Crypt::OpenSSL::X509: $@" if $@; |
6458
|
|
|
|
|
|
|
eval { require MIME::Base64 }; |
6459
|
|
|
|
|
|
|
die "Failed to access class MIME::Base64: $@" if $@; |
6460
|
|
|
|
|
|
|
|
6461
|
|
|
|
|
|
|
my %results = (); |
6462
|
|
|
|
|
|
|
|
6463
|
|
|
|
|
|
|
#get Security Token |
6464
|
|
|
|
|
|
|
my $Token = |
6465
|
|
|
|
|
|
|
$envelope->match( |
6466
|
|
|
|
|
|
|
"/Envelope/Header/Security/{$WSRF::Constants::WSSE}BinarySecurityToken") |
6467
|
|
|
|
|
|
|
? $envelope->valueof( |
6468
|
|
|
|
|
|
|
"/Envelope/Header/Security/{$WSRF::Constants::WSSE}BinarySecurityToken") |
6469
|
|
|
|
|
|
|
: die "WSRF::WSS::verify Fault - No Security Token in SOAP Header\n"; |
6470
|
|
|
|
|
|
|
|
6471
|
|
|
|
|
|
|
$Token =~ s/\s+$//; |
6472
|
|
|
|
|
|
|
$Token = |
6473
|
|
|
|
|
|
|
"-----BEGIN CERTIFICATE-----\n" . $Token . "\n-----END CERTIFICATE-----"; |
6474
|
|
|
|
|
|
|
|
6475
|
|
|
|
|
|
|
# print ">>>>Token>>>\n$Token\n<<<
|
6476
|
|
|
|
|
|
|
|
6477
|
|
|
|
|
|
|
#create an X509 object from the string - this will die if it is not an X509 cert |
6478
|
|
|
|
|
|
|
my $x509 = Crypt::OpenSSL::X509->new_from_string($Token); |
6479
|
|
|
|
|
|
|
|
6480
|
|
|
|
|
|
|
#if we get here then $Token IS a X509 cert |
6481
|
|
|
|
|
|
|
$results{X509} = $Token; |
6482
|
|
|
|
|
|
|
|
6483
|
|
|
|
|
|
|
my $rsa_pub = Crypt::OpenSSL::RSA->new_public_key( $x509->pubkey() ); |
6484
|
|
|
|
|
|
|
|
6485
|
|
|
|
|
|
|
#get the piece of XML that has been signed |
6486
|
|
|
|
|
|
|
my $parser = XML::LibXML->new(); |
6487
|
|
|
|
|
|
|
my $doc = $parser->parse_string( $envelope->raw_xml ); |
6488
|
|
|
|
|
|
|
my $can_signed_info = $doc->toStringEC14N( 0, $WSRF::WSS::si_xpath, [''] ); |
6489
|
|
|
|
|
|
|
|
6490
|
|
|
|
|
|
|
#get the Signature value |
6491
|
|
|
|
|
|
|
my $SignatureValue = |
6492
|
|
|
|
|
|
|
$envelope->match( |
6493
|
|
|
|
|
|
|
"/Envelope/Header//{$WSRF::Constants::DS}SignatureValue") |
6494
|
|
|
|
|
|
|
? $envelope->valueof( |
6495
|
|
|
|
|
|
|
"/Envelope/Header//{$WSRF::Constants::DS}SignatureValue") |
6496
|
|
|
|
|
|
|
: die "WSRF::WSS::verify Fault - No Signature Value in SOAP Header\n"; |
6497
|
|
|
|
|
|
|
|
6498
|
|
|
|
|
|
|
$SignatureValue = MIME::Base64::decode($SignatureValue); |
6499
|
|
|
|
|
|
|
|
6500
|
|
|
|
|
|
|
if ( $rsa_pub->verify( $can_signed_info, $SignatureValue ) ) { |
6501
|
|
|
|
|
|
|
$results{Signed} = 'true'; |
6502
|
|
|
|
|
|
|
|
6503
|
|
|
|
|
|
|
#print STDERR "WSRF::WSS::verify Message Signature is Correct\n"; |
6504
|
|
|
|
|
|
|
} else { |
6505
|
|
|
|
|
|
|
die "WSRF::WSS::verify Fault - Message Signature is NOT Correct\n"; |
6506
|
|
|
|
|
|
|
} |
6507
|
|
|
|
|
|
|
|
6508
|
|
|
|
|
|
|
my $i = 1; |
6509
|
|
|
|
|
|
|
my %SignedStuff = (); |
6510
|
|
|
|
|
|
|
while ( |
6511
|
|
|
|
|
|
|
$envelope->match("/Envelope/Header/Security/Signature/SignedInfo/[$i]") |
6512
|
|
|
|
|
|
|
) |
6513
|
|
|
|
|
|
|
{ |
6514
|
|
|
|
|
|
|
my $data = |
6515
|
|
|
|
|
|
|
$envelope->dataof( |
6516
|
|
|
|
|
|
|
"/Envelope/Header/Security/Signature/SignedInfo/[$i]"); |
6517
|
|
|
|
|
|
|
if ( $data->name eq "Reference" ) { |
6518
|
|
|
|
|
|
|
my $attr = $data->attr; |
6519
|
|
|
|
|
|
|
my $name = $attr->{URI}; |
6520
|
|
|
|
|
|
|
my $DigestValue = |
6521
|
|
|
|
|
|
|
$envelope->match( |
6522
|
|
|
|
|
|
|
"/Envelope/Header/Security/Signature/SignedInfo/[$i]//{$WSRF::Constants::DS}DigestValue" |
6523
|
|
|
|
|
|
|
) |
6524
|
|
|
|
|
|
|
? $envelope->valueof( |
6525
|
|
|
|
|
|
|
"/Envelope/Header/Security/Signature/SignedInfo/[$i]//{$WSRF::Constants::DS}DigestValue" |
6526
|
|
|
|
|
|
|
) |
6527
|
|
|
|
|
|
|
: die "WSRF::WSS::verify No DigestValue for $name"; |
6528
|
|
|
|
|
|
|
|
6529
|
|
|
|
|
|
|
#strip the # that is part of the XLink stuff for pointing to other parts of the XML doc |
6530
|
|
|
|
|
|
|
$name =~ s/^\#//o; |
6531
|
|
|
|
|
|
|
$SignedStuff{$name} = $DigestValue; |
6532
|
|
|
|
|
|
|
} |
6533
|
|
|
|
|
|
|
$i++; |
6534
|
|
|
|
|
|
|
} |
6535
|
|
|
|
|
|
|
|
6536
|
|
|
|
|
|
|
my %Signed = (); |
6537
|
|
|
|
|
|
|
foreach my $key ( keys %WSRF::WSS::ThingsThatShouldBeSigned ) { |
6538
|
|
|
|
|
|
|
if ( |
6539
|
|
|
|
|
|
|
$envelope->match( |
6540
|
|
|
|
|
|
|
"/Envelope//{$WSRF::WSS::ThingsThatShouldBeSigned{$key}}$key") |
6541
|
|
|
|
|
|
|
) |
6542
|
|
|
|
|
|
|
{ |
6543
|
|
|
|
|
|
|
my $data = |
6544
|
|
|
|
|
|
|
$envelope->dataof( |
6545
|
|
|
|
|
|
|
"/Envelope//{$WSRF::WSS::ThingsThatShouldBeSigned{$key}}$key"); |
6546
|
|
|
|
|
|
|
my $attr = $data->attr; |
6547
|
|
|
|
|
|
|
my $ID = $attr->{"{$WSRF::Constants::WSU}Id"}; |
6548
|
|
|
|
|
|
|
$Signed{$key} = $ID; |
6549
|
|
|
|
|
|
|
} |
6550
|
|
|
|
|
|
|
} |
6551
|
|
|
|
|
|
|
|
6552
|
|
|
|
|
|
|
foreach my $key ( keys %Signed ) { |
6553
|
|
|
|
|
|
|
my $parser = XML::LibXML->new(); |
6554
|
|
|
|
|
|
|
my $doc = $parser->parse_string( $envelope->raw_xml ); |
6555
|
|
|
|
|
|
|
my $CanonicalForm = |
6556
|
|
|
|
|
|
|
$doc->toStringEC14N( 0, $WSRF::WSS::Xpath{$key}, [''] ); |
6557
|
|
|
|
|
|
|
die "Could not get the Canonicalize $key from Envelope\n" |
6558
|
|
|
|
|
|
|
unless $CanonicalForm; |
6559
|
|
|
|
|
|
|
my $token_digest = Digest::SHA1::sha1($CanonicalForm); |
6560
|
|
|
|
|
|
|
$token_digest = MIME::Base64::encode($token_digest); |
6561
|
|
|
|
|
|
|
chomp($token_digest); |
6562
|
|
|
|
|
|
|
if ( $SignedStuff{ $Signed{$key} } eq $token_digest ) { |
6563
|
|
|
|
|
|
|
|
6564
|
|
|
|
|
|
|
#print "WSRF::WSS::verify Message \"$key\" is signed\n"; |
6565
|
|
|
|
|
|
|
$results{PartsSigned}{$key} = 'true'; |
6566
|
|
|
|
|
|
|
} else { |
6567
|
|
|
|
|
|
|
die "WSRF::WSS::verify $key digest hashs do not match\n"; |
6568
|
|
|
|
|
|
|
} |
6569
|
|
|
|
|
|
|
} |
6570
|
|
|
|
|
|
|
|
6571
|
|
|
|
|
|
|
$results{Created} = |
6572
|
|
|
|
|
|
|
$envelope->match( |
6573
|
|
|
|
|
|
|
"/Envelope/Header/Security/Timestamp/{$WSRF::Constants::WSU}Created") |
6574
|
|
|
|
|
|
|
? $envelope->valueof( |
6575
|
|
|
|
|
|
|
"/Envelope/Header/Security/Timestamp/{$WSRF::Constants::WSU}Created") |
6576
|
|
|
|
|
|
|
: undef; |
6577
|
|
|
|
|
|
|
|
6578
|
|
|
|
|
|
|
#print STDERR "WSRF::WSS::verify Message Created at $results{Created} (should be GMT)\n" if $results{Created}; |
6579
|
|
|
|
|
|
|
|
6580
|
|
|
|
|
|
|
$results{Expires} = |
6581
|
|
|
|
|
|
|
$envelope->match( |
6582
|
|
|
|
|
|
|
"/Envelope/Header/Security/Timestamp/{$WSRF::Constants::WSU}Expires") |
6583
|
|
|
|
|
|
|
? $envelope->valueof( |
6584
|
|
|
|
|
|
|
"/Envelope/Header/Security/Timestamp/{$WSRF::Constants::WSU}Expires") |
6585
|
|
|
|
|
|
|
: undef; |
6586
|
|
|
|
|
|
|
|
6587
|
|
|
|
|
|
|
#print STDERR "WSRF::WSS::verify Message Expires at \"$results{Expires}\" (should be GMT)\n" if $results{Expires}; |
6588
|
|
|
|
|
|
|
|
6589
|
|
|
|
|
|
|
return %results; |
6590
|
|
|
|
|
|
|
} |
6591
|
|
|
|
|
|
|
|
6592
|
|
|
|
|
|
|
1; |