Project

General

Profile

1 1929 brooke
 #
2
 #  '$RCSfile$'
3
 #  Copyright: 2000 Regents of the University of California
4
 #
5
 #   '$Author$'
6
 #     '$Date$'
7
 # '$Revision$'
8
 #
9
 # This program is free software; you can redistribute it and/or modify
10
 # it under the terms of the GNU General Public License as published by
11
 # the Free Software Foundation; either version 2 of the License, or
12
 # (at your option) any later version.
13
 #
14
 # This program is distributed in the hope that it will be useful,
15
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 # GNU General Public License for more details.
18
 #
19
 # You should have received a copy of the GNU General Public License
20
 # along with this program; if not, write to the Free Software
21
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
 #
23
24
package Metacat;
25
26
require 5.005_62;
27
use strict;
28
use warnings;
29
30
require Exporter;
31
use AutoLoader qw(AUTOLOAD);
32
33
use LWP::UserAgent;
34 3421 walbridge
use HTTP::Request::Common qw(POST);
35 1929 brooke
use HTTP::Cookies;
36
37
our @ISA = qw(Exporter);
38
39
# Items to export into callers namespace by default. Note: do not export
40
# names by default without a very good reason. Use EXPORT_OK instead.
41
# Do not simply export all your public functions/methods/constants.
42
43
# This allows declaration	use Metacat ':all';
44
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
45
# will save memory.
46
our %EXPORT_TAGS = ( 'all' => [ qw(
47
48
) ] );
49
50
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
51
52
our @EXPORT = qw(
53
54
);
55
our $VERSION = '0.01';
56
57
58
# Preloaded methods go here.
59
60
#############################################################
61
# Constructor creates a new class instance and inits all
62
# of the instance variables to their proper default values,
63
# which can later be changed using "set_options"
64
#############################################################
65
sub new {
66 3421 walbridge
  my($type,$metacatUrl) = @_;
67 1929 brooke
  my $cookie_jar = HTTP::Cookies->new;
68
69 3421 walbridge
  my $self = {
70
    metacatUrl     => $metacatUrl,
71 1929 brooke
    message        => '',
72
    cookies        => \$cookie_jar
73
  };
74
75 3421 walbridge
  bless $self, $type;
76
  return $self;
77 1929 brooke
}
78
79
#############################################################
80
# subroutine to set options for the class, including the URL
81
# for the Metacat database to which we would connect
82
#############################################################
83
sub set_options {
84
  my $self = shift;
85
  my %newargs = ( @_ );
86
87
  my $arg;
88
  foreach $arg (keys %newargs) {
89
    $self->{$arg} = $newargs{$arg};
90
  }
91
}
92
93
#############################################################
94
# subroutine to send data to metacat and get the response
95
# return response from metacat
96
#############################################################
97
sub sendData {
98
  my $self = shift;
99
  my %postData = ( @_ );
100
101 1955 jones
  $self->{'message'} = '';
102 1929 brooke
  my $userAgent = new LWP::UserAgent;
103
  $userAgent->agent("MetacatClient/1.0");
104 3421 walbridge
105
  # determine encoding type
106
  my $contentType = 'application/x-www-form-urlencoded';
107 9712 leinfelder
  my $expect = "100-continue";
108
	if ($postData{'enctype'}) {
109 3421 walbridge
      $contentType = $postData{'enctype'};
110
      delete $postData{'enctype'};
111
  }
112 9529 cjones
113
114
  my $request;
115
  if ( $self->{'auth_token_header'} ) {
116
      # if available, set the Authorization header from the auth_token_header instance variable
117
      $request = POST("$self->{'metacatUrl'}",
118
                      Content_Type => $contentType,
119 9712 leinfelder
                      Expect => $expect,
120 9529 cjones
                      Authorization => $self->{'auth_token_header'},
121
                      Content => \%postData
122
                      );
123
124
  } else {
125
      $request = POST("$self->{'metacatUrl'}",
126
                      Content_Type => $contentType,
127 9712 leinfelder
                      Expect => $expect,
128 9529 cjones
                      Content => \%postData
129
                      );
130
  }
131 3421 walbridge
132
  # set cookies on UA object
133 1929 brooke
  my $cookie_jar = $self->{'cookies'};
134
  $$cookie_jar->add_cookie_header($request);
135 5029 daigle
  #print "Content_type:text/html\n\n";
136 3421 walbridge
  #print "request: " . $request->as_string();
137 1929 brooke
138
  my $response = $userAgent->request($request);
139 3421 walbridge
  #print "response: " . $response->as_string();
140
141 1929 brooke
  if ($response->is_success) {
142
    # save the cookies
143
    $$cookie_jar->extract_cookies($response);
144
    # save the metacat response message
145
    $self->{'message'} = $response->content;
146
  } else {
147
    #print "SendData content is: ", $response->content, "\n";
148
    return 0;
149
  }
150
  return $response;
151
}
152
153
#############################################################
154
# subroutine to log into Metacat and save the cookie if the
155 2684 sgarg
# login is valid.  If not valid, return 0. If valid then send
156
# following values to indicate user status
157
# 1 - user
158
# 2 - moderator
159
# 3 - administrator
160
# 4 - moderator and administrator
161 1929 brooke
#############################################################
162
sub login {
163
  my $self = shift;
164
  my $username = shift;
165
  my $password = shift;
166
167
  my $returnval = 0;
168
169
  my %postData = ( action => 'login',
170
                   qformat => 'xml',
171
                   username => $username,
172
                   password => $password
173
                 );
174
  my $response = $self->sendData(%postData);
175
  if (($response) && $response->content =~ /<login>/) {
176
    $returnval = 1;
177
  }
178
179 2684 sgarg
  if (($response) && $response->content =~ /<isAdministrator>/) {
180
	if (($response) && $response->content =~ /<isModerator>/) {
181
    		$returnval = 4;
182
	} else {
183
		$returnval = 3;
184
	}
185
  } elsif (($response) && $response->content =~ /<isModerator>/){
186
	$returnval = 2;
187
  }
188
189 1929 brooke
  return $returnval;
190
}
191
192
#############################################################
193 9228 leinfelder
# subroutine to logout of Metacat
194
#############################################################
195
sub logout {
196
    my $self = shift;
197
198
    my %postData = (action => 'logout');
199
200
    my $response = $self->sendData(%postData);
201
202 9234 leinfelder
    my $returnval = 1;
203
    if (($response) && $response->content =~ /<logout>/) {
204
    	$returnval = 0;
205
  	}
206
207 9228 leinfelder
    # clear the cookie
208
    my $cookie_jar = $self->{'cookies'};
209
    $$cookie_jar->clear();
210
211 9234 leinfelder
    return $returnval;
212 9228 leinfelder
}
213
214
#############################################################
215 9712 leinfelder
# subroutine to log into Metacat and get user and group
216
# information xml for a logged in user
217 5311 daigle
#############################################################
218
sub getUserInfo {
219
	my $self = shift;
220
221 9712 leinfelder
	my %postData = (action => 'validatesession');
222 5311 daigle
223
	my $response = $self->sendData(%postData);
224
225
	return $response->content;
226
}
227
228
#############################################################
229 1929 brooke
# subroutine to insert an XML document into Metacat
230
# If success, return 1, else return 0
231
#############################################################
232
sub insert {
233
  my $self = shift;
234
  my $docid = shift;
235
  my $xmldocument = shift;
236
  my $dtd = shift;
237
238
  my $returnval = 0;
239
240
  my %postData = ( action => 'insert',
241
                   docid => $docid,
242
                   doctext => $xmldocument
243
                 );
244
  if ($dtd) {
245
    $postData{'dtdtext'} = $dtd;
246
  }
247
248
  my $response = $self->sendData(%postData);
249
  if (($response) && $response->content =~ /<success>/) {
250
    $returnval = 1;
251
  } elsif (($response)) {
252
    $returnval = 0;
253
    #print "Error response from sendData!\n";
254
    #print $response->content, "\n";
255
  } else {
256
    $returnval = 0;
257
    #print "Invalid response from sendData!\n";
258
  }
259
260
  return $returnval;
261
}
262
263
#############################################################
264
# subroutine to update an XML document in Metacat
265
# If success, return 1, else return 0
266
#############################################################
267
sub update {
268
  my $self = shift;
269
  my $docid = shift;
270
  my $xmldocument = shift;
271
  my $dtd = shift;
272
273
  my $returnval = 0;
274
275
  my %postData = ( action => 'update',
276
                   docid => $docid,
277
                   doctext => $xmldocument
278
                 );
279
  if ($dtd) {
280
    $postData{'dtdtext'} = $dtd;
281
  }
282
283
  my $response = $self->sendData(%postData);
284
  if (($response) && $response->content =~ /<success>/) {
285
    $returnval = 1;
286
  }
287
288
  return $returnval;
289
}
290
291 3421 walbridge
############################################################
292
# subroutine to upload an XML document in Metacat
293
# If success, return 1, else return 0
294 1929 brooke
#############################################################
295 3421 walbridge
sub upload {
296
  my $self = shift;
297
  my $docid = shift;
298
  my $datafile = shift;
299 7820 leinfelder
  my $filename = shift;
300 3421 walbridge
301
  my $returnval = 0;
302
303
  my %postData = ( action => 'upload',
304
                   docid => $docid,
305 7821 leinfelder
                   datafile => [$datafile, $filename],
306 9535 cjones
                   enctype => 'multipart/form-data'
307 3421 walbridge
                 );
308
309
  my $response = $self->sendData(%postData);
310
  #print "response is: $response";
311
  #
312
  if (($response) && $response->content =~ /<success>/) {
313
    $returnval = $response->content;
314
  }
315
316
  return $returnval;
317
}
318
319
320
#############################################################
321 1929 brooke
# subroutine to delete an XML document in Metacat
322
# If success, return 1, else return 0
323
#############################################################
324
sub delete {
325
  my $self = shift;
326
  my $docid = shift;
327
328
  my $returnval = 0;
329
330
  my %postData = ( action => 'delete',
331
                   docid => $docid
332
                 );
333
334
  my $response = $self->sendData(%postData);
335
  if (($response) && $response->content =~ /<success>/) {
336
    $returnval = 1;
337
  }
338
339
  return $returnval;
340
}
341
342
#############################################################
343 2846 sgarg
# subroutine to set access for an XML document in Metacat
344
# If success, return 1, else return 0
345
#############################################################
346
sub setaccess {
347
  my $self = shift;
348
  my $docid = shift;
349
  my $principal = shift;
350
  my $permission = shift;
351
  my $permType = shift;
352
  my $permOrder = shift;
353
354
  my $returnval = 0;
355
356
  my %postData = ( action => 'setaccess',
357
                   docid => $docid,
358
		   principal => $principal,
359
		   permission => $permission,
360
		   permType => $permType,
361
		   permOrder => $permOrder
362
                 );
363
364
  my $response = $self->sendData(%postData);
365
  if (($response) && $response->content =~ /<success>/) {
366
    $returnval = 1;
367
  }
368
369
  return $returnval;
370
}
371
372 9645 leinfelder
#############################################################
373
# subroutine to get access info from Metacat
374
# returns access XML block from Metacat
375
#############################################################
376
sub getaccess {
377
    my $self = shift;
378
    my $docid = shift;
379
380 9729 leinfelder
    my %postData = ( action => 'getaccesscontrol',
381 9645 leinfelder
    docid => $docid
382
    );
383
384
    my $response = $self->sendData(%postData);
385
386
    my $returnval = 0;
387
    if ($response) {
388
        $returnval = $response;
389
    }
390
391
    return $returnval;
392
}
393 2846 sgarg
394
#############################################################
395 1929 brooke
# subroutine to read an XML document from Metacat
396
# returns the XML from Metacat, which may be an error response
397
#############################################################
398
sub read {
399
  my $self = shift;
400
  my $docid = shift;
401
402
  my %postData = ( action => 'read',
403
                   qformat => 'xml',
404
                   docid => $docid
405
                 );
406
407
  my $response = $self->sendData(%postData);
408
409
  my $returnval = 0;
410
  if ($response) {
411
    $returnval = $response;
412
  }
413
414
  return $returnval;
415
}
416
417
#############################################################
418
# subroutine to query metacat using a structured path query
419
# returns the XML from Metacat, which may be an error response
420
#############################################################
421
sub squery {
422
  my $self = shift;
423
  my $query = shift;
424
425
  my %postData = ( action => 'squery',
426
                   qformat => 'xml',
427
                   query => $query
428
                 );
429
430
  my $response = $self->sendData(%postData);
431
432
  my $returnval = 0;
433
  if ($response) {
434
    $returnval = $response;
435
  }
436
437
  return $returnval;
438
}
439
440
#############################################################
441 1953 jones
# subroutine to get the maximimum id in a series
442
# If success, return max id, else return 0
443
#############################################################
444
sub getLastId {
445
  my $self = shift;
446
  my $scope = shift;
447
448
  my $returnval = 0;
449
450
  my %postData = ( action => 'getlastdocid',
451
                   scope => $scope
452
                 );
453
454
  my $response = $self->sendData(%postData);
455 5201 daigle
  if (($response) && $response->content =~  /<docid>(.*)<\/docid>/s) {
456 1953 jones
      $returnval = "$1";
457
  } elsif (($response)) {
458
    $returnval = 0;
459
    #print "Error response from sendData!\n";
460
    #print $response->content, "\n";
461
  } else {
462
    $returnval = 0;
463
    #print "Invalid response from sendData!\n";
464
  }
465
466
  return $returnval;
467
}
468 5201 daigle
469 1953 jones
#############################################################
470 5201 daigle
# subroutine to get the maximimum id in a series
471
# If success, return max id, else return 0
472
#############################################################
473
sub getLastRevision {
474
  my $self = shift;
475
  my $docid = shift;
476
477
  my $returnval = 0;
478
479
  my %postData = ( action => 'getrevisionanddoctype',
480
                   docid => $docid
481
                 );
482
483
  my $response = $self->sendData(%postData);
484
  if (($response) && $response->content =~ /(.*);(.*)/s)  {
485
      $returnval = "$1";
486
  } elsif (($response)) {
487
    $returnval = 0;
488
    #print "Error response from sendData!\n";
489
    #print $response->content, "\n";
490
  } else {
491
    $returnval = 0;
492
    #print "Invalid response from sendData!\n";
493
  }
494
495
  return $returnval;
496
}
497
498
#############################################################
499 7695 leinfelder
# subroutine to get the docid for a given PID
500
# If success, return docid, else return -1
501
#############################################################
502
sub getDocid {
503
  my $self = shift;
504
  my $pid = shift;
505
506
  my $returnval = 0;
507
508
  my %postData = ( action => 'getdocid',
509
                   pid => $pid
510
                 );
511
512
  my $response = $self->sendData(%postData);
513
  if (($response) && $response->content =~  /<docid>(.*)<\/docid>/s) {
514
      $returnval = "$1";
515
  } elsif (($response)) {
516
    $returnval = -1;
517
    #print "Error response from sendData!\n";
518
    #print $response->content, "\n";
519
  } else {
520
    $returnval = -1;
521
    #print "Invalid response from sendData!\n";
522
  }
523
524
  return $returnval;
525
}
526
527
#############################################################
528 1929 brooke
# subroutine to get the message returned from the last executed
529
# metacat action.  These are generally XML formatted messages.
530
#############################################################
531
sub getMessage {
532
  my $self = shift;
533
534
  return $self->{'message'};
535
}
536
537
#############################################################
538
# subroutine to get the cookies returned from the metacat
539
# server to establish (and pass on) session info (JSESSIONID).
540
#############################################################
541
sub getCookies {
542
  my $self = shift;
543
544
  return $self->{'cookies'};
545
}
546
547
# Autoload methods go after =cut, and are processed by the autosplit program.
548
549
1;
550
__END__
551
# Below is stub documentation for your module. You better edit it!
552
553
=head1 NAME
554
555
Metacat - Perl extension for communicating with the Metacat XML database
556
557
=head1 SYNOPSIS
558
559
  use Metacat;
560
  my $metacat = Metacat->new();
561
  my $response = $metacat->login($username, $password);
562
  print $metacat->getMessage();
563
  $response = $metacat->insert($docid, $xmldoc);
564
  print $metacat->getMessage();
565
  $response = $metacat->insert($docid, $xmldoc, $dtd);
566
  print $metacat->getMessage();
567
  $response = $metacat->update($docid, $xmldoc);
568
  print $metacat->getMessage();
569 3724 jones
  $response = $metacat->upload($docid, $data);
570
  print $metacat->getMessage();
571 1929 brooke
  $htmlResponse = $metacat->read($docid);
572
  $xmldoc = $htmlResponse->content();
573
  print $xmldoc;
574
  $resultset = $metacat->squery($pathquery);
575
  print $resultset;
576
  $response = $metacat->delete($docid);
577 2846 sgarg
  $response = $metacat->setaccess($docid,$principal,$permission,$permType,$permOrder);
578 1953 jones
  my $lastid = $metacat->getLastId("obfs");
579 1929 brooke
  print $metacat->getMessage();
580
  $response = $metacat->getCookies();
581
  print $metacat->getMessage();
582
583
=head1 DESCRIPTION
584
585
This is a client library for accessing the Metacat XML database.  Metacat
586
is a Java servlet that accepts commands over HTTP and returns XML and
587
HTML responses.  See http://knb.ecoinformatics.org for details about
588
Metacat and its interface.
589
590
=head2 EXPORT
591
592
None by default.
593
594
595
=head1 AUTHOR
596
597
Matthew B. Jones, jones@nceas.ucsb.edu
598
599
=head1 SEE ALSO
600
601
perl(1).
602
603
=cut