Project

General

Profile

1 6179 cjones
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2000-2011 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author:  $'
7
 *     '$Date:  $'
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 edu.ucsb.nceas.metacat.dataone;
25
26 6228 cjones
import java.io.IOException;
27 6179 cjones
import java.io.InputStream;
28 6228 cjones
import java.security.NoSuchAlgorithmException;
29 6250 cjones
import java.sql.SQLException;
30 6179 cjones
import java.util.Date;
31 6250 cjones
import java.util.List;
32 6179 cjones
33 6258 cjones
import org.apache.commons.io.IOUtils;
34 6179 cjones
import org.apache.log4j.Logger;
35
import org.dataone.service.exceptions.IdentifierNotUnique;
36
import org.dataone.service.exceptions.InsufficientResources;
37
import org.dataone.service.exceptions.InvalidRequest;
38
import org.dataone.service.exceptions.InvalidSystemMetadata;
39
import org.dataone.service.exceptions.InvalidToken;
40
import org.dataone.service.exceptions.NotAuthorized;
41
import org.dataone.service.exceptions.NotFound;
42
import org.dataone.service.exceptions.NotImplemented;
43
import org.dataone.service.exceptions.ServiceFailure;
44 6185 leinfelder
import org.dataone.service.exceptions.SynchronizationFailed;
45 6179 cjones
import org.dataone.service.exceptions.UnsupportedType;
46
import org.dataone.service.mn.tier1.MNCore;
47
import org.dataone.service.mn.tier1.MNRead;
48
import org.dataone.service.mn.tier2.MNAuthorization;
49
import org.dataone.service.mn.tier3.MNStorage;
50
import org.dataone.service.mn.tier4.MNReplication;
51
import org.dataone.service.types.AccessPolicy;
52
import org.dataone.service.types.Checksum;
53 6228 cjones
import org.dataone.service.types.ChecksumAlgorithm;
54 6179 cjones
import org.dataone.service.types.DescribeResponse;
55
import org.dataone.service.types.Event;
56 6250 cjones
import org.dataone.service.types.Group;
57 6179 cjones
import org.dataone.service.types.Identifier;
58
import org.dataone.service.types.Log;
59
import org.dataone.service.types.MonitorList;
60
import org.dataone.service.types.Node;
61
import org.dataone.service.types.NodeReference;
62
import org.dataone.service.types.ObjectFormat;
63
import org.dataone.service.types.ObjectList;
64
import org.dataone.service.types.Permission;
65
import org.dataone.service.types.Session;
66
import org.dataone.service.types.Subject;
67
import org.dataone.service.types.SystemMetadata;
68 6228 cjones
import org.dataone.service.types.util.ServiceTypeUtil;
69 6179 cjones
70 6250 cjones
import edu.ucsb.nceas.metacat.DocumentImpl;
71 6234 cjones
import edu.ucsb.nceas.metacat.EventLog;
72 6230 cjones
import edu.ucsb.nceas.metacat.IdentifierManager;
73 6234 cjones
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
74 6250 cjones
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
75 6260 cjones
import edu.ucsb.nceas.metacat.database.DBConnection;
76
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
77 6241 cjones
import edu.ucsb.nceas.metacat.properties.PropertyService;
78
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
79 6230 cjones
80 6179 cjones
/**
81
 * Represents Metacat's implementation of the DataONE Member Node
82
 * service API. Methods implement the various MN* interfaces, and methods common
83
 * to both Member Node and Coordinating Node interfaces are found in the
84
 * D1NodeService base class.
85
 */
86
public class MNodeService extends D1NodeService implements MNAuthorization,
87
  MNCore, MNRead, MNReplication, MNStorage {
88
89 6259 cjones
  /* the instance of the MNodeService object */
90 6179 cjones
  private static MNodeService instance = null;
91
92
  /* the logger instance */
93
  private Logger logMetacat = null;
94
95
  /**
96 6241 cjones
   * Singleton accessor to get an instance of MNodeService.
97
   *
98
   * @return instance - the instance of MNodeService
99 6179 cjones
   */
100 6241 cjones
  public static MNodeService getInstance() {
101 6179 cjones
    if (instance == null) {
102 6241 cjones
103 6254 cjones
      instance = new MNodeService();
104 6241 cjones
105 6179 cjones
    }
106
107
    return instance;
108
  }
109
110
  /**
111
   * Constructor, private for singleton access
112
   */
113 6254 cjones
  private MNodeService() {
114 6259 cjones
    super();
115 6179 cjones
    logMetacat = Logger.getLogger(MNodeService.class);
116
117
  }
118
119 6259 cjones
  /**
120
   * Deletes an object from the Member Node, where the object is either a
121
   * data object or a science metadata object.
122
   *
123
   * @param session - the Session object containing the credentials for the Subject
124
   * @param pid - The object identifier to be deleted
125
   *
126
   * @return pid - the identifier of the object used for the deletion
127
   *
128
   * @throws InvalidToken
129
   * @throws ServiceFailure
130
   * @throws NotAuthorized
131
   * @throws NotFound
132
   * @throws NotImplemented
133
   * @throws InvalidRequest
134
   */
135 6179 cjones
  @Override
136 6259 cjones
  public Identifier delete(Session session, Identifier pid)
137 6179 cjones
    throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
138
    NotImplemented, InvalidRequest {
139
140 6250 cjones
    String localId = null;
141
    boolean allowed = false;
142
    Subject subject = session.getSubject();
143
    List<Group> groupList = session.getSubjectList().getGroupList();
144
    String[] groups = new String[groupList.size()];
145
    IdentifierManager im = IdentifierManager.getInstance();
146
147
    // put the group names into a string array
148
    if( session != null ) {
149
      for ( int i = 0; i > groupList.size(); i++ ) {
150 6259 cjones
        groups[i] = groupList.get(i).getGroupName();
151
152 6250 cjones
      }
153
    }
154
155
    // be sure the user is authenticated for delete()
156
    if (subject.getValue() == null ||
157
        subject.getValue().toLowerCase().equals("public") ) {
158
      throw new NotAuthorized("1320", "The provided identity does not have " +
159
        "permission to DELETE objects on the Member Node.");
160
161
    }
162
163
    // do we have a valid pid?
164
    if ( pid == null || pid.getValue().trim().equals("") ) {
165
      throw new InvalidRequest("1322", "The provided identifier was invalid.");
166
167
    }
168
169
    // check for the existing identifier
170
    try {
171 6259 cjones
      localId = im.getLocalId(pid.getValue());
172 6250 cjones
173
    } catch (McdbDocNotFoundException e) {
174
      throw new InvalidRequest("1322", "The object with the provided " +
175 6259 cjones
        "identifier was not found.");
176 6250 cjones
177
    }
178
179
    // does the subject have DELETE (a D1 CHANGE_PERMISSION level) priveleges on the pid?
180
    allowed = isAuthorized(session, pid, Permission.CHANGE_PERMISSION);
181
182
    if ( allowed ) {
183
      try {
184
        // delete the document
185 6259 cjones
        DocumentImpl.delete(localId, subject.getValue(), groups, null);
186 6258 cjones
        EventLog.getInstance().log(metacatUrl, subject.getValue(), localId, "delete");
187 6254 cjones
188 6250 cjones
      } catch (McdbDocNotFoundException e) {
189
        throw new InvalidRequest("1322", "The provided identifier was invalid.");
190
191
      } catch (SQLException e) {
192
        throw new ServiceFailure("1350", "There was a problem deleting the object." +
193 6259 cjones
          "The error message was: " + e.getMessage());
194 6250 cjones
195
      } catch (InsufficientKarmaException e) {
196
        throw new NotAuthorized("1320", "The provided identity does not have " +
197
        "permission to DELETE objects on the Member Node.");
198
199
      } catch (Exception e) { // for some reason DocumentImpl throws a general Exception
200
        throw new ServiceFailure("1350", "There was a problem deleting the object." +
201 6259 cjones
            "The error message was: " + e.getMessage());
202 6250 cjones
203
      }
204
205
    } else {
206 6251 cjones
      throw new NotAuthorized("1320", "The provided identity does not have " +
207
      "permission to DELETE objects on the Member Node.");
208 6259 cjones
209 6250 cjones
    }
210
211 6259 cjones
    return pid;
212
  }
213 6179 cjones
214 6251 cjones
215 6179 cjones
  /**
216
   * Updates an existing object by creating a new object identified by
217
   * newPid on the Member Node which explicitly obsoletes the object
218
   * identified by pid through appropriate changes to the SystemMetadata
219
   * of pid and newPid
220
   *
221 6259 cjones
   * @param session - the Session object containing the credentials for the Subject
222
   * @param pid - The identifier of the object to be updated
223
   * @param object - the new object bytes
224
   * @param sysmeta - the new system metadata describing the object
225
   *
226
   * @return newPid - the identifier of the new object
227
   *
228
   * @throws InvalidToken
229
   * @throws ServiceFailure
230
   * @throws NotAuthorized
231
   * @throws NotFound
232
   * @throws NotImplemented
233
   * @throws IdentifierNotUnique
234
   * @throws UnsupportedType
235
   * @throws InsufficientResources
236
   * @throws InvalidSystemMetadata
237
   * @throws InvalidRequest
238 6179 cjones
   */
239
  @Override
240 6259 cjones
  public Identifier update(Session session, Identifier pid, InputStream object,
241
    Identifier newPid, SystemMetadata sysmeta)
242 6179 cjones
    throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique,
243
    UnsupportedType, InsufficientResources, NotFound, InvalidSystemMetadata,
244
    NotImplemented, InvalidRequest {
245
246 6259 cjones
    String localId = null;
247
    boolean allowed = false;
248
    boolean isScienceMetadata = false;
249
    Subject subject = session.getSubject();
250
    List<Group> groupList = session.getSubjectList().getGroupList();
251
    String[] groups = new String[groupList.size()];
252
    IdentifierManager im = IdentifierManager.getInstance();
253 6258 cjones
254 6259 cjones
    // put the group names into a string array
255
    if( session != null ) {
256
      for ( int i = 0; i > groupList.size(); i++ ) {
257
        groups[i] = groupList.get(i).getGroupName();
258
259
      }
260
    }
261 6258 cjones
262 6259 cjones
    // be sure the user is authenticated for update()
263
    if (subject.getValue() == null ||
264
        subject.getValue().toLowerCase().equals("public") ) {
265
      throw new NotAuthorized("1200", "The provided identity does not have " +
266
        "permission to UPDATE objects on the Member Node.");
267
268
    }
269 6258 cjones
270 6259 cjones
    // do we have a valid pid?
271
    if ( pid == null || pid.getValue().trim().equals("") ) {
272
      throw new InvalidRequest("1202", "The provided identifier was invalid.");
273 6258 cjones
274 6259 cjones
    }
275 6258 cjones
276 6259 cjones
    // check for the existing identifier
277
    try {
278
      localId = im.getLocalId(pid.getValue());
279 6258 cjones
280 6259 cjones
    } catch (McdbDocNotFoundException e) {
281
      throw new InvalidRequest("1202", "The object with the provided " +
282
        "identifier was not found.");
283 6258 cjones
284 6259 cjones
    }
285 6258 cjones
286 6259 cjones
    // does the subject have WRITE ( == update) priveleges on the pid?
287
    allowed = isAuthorized(session, pid, Permission.WRITE);
288 6258 cjones
289 6259 cjones
    if ( allowed ) {
290
291
      // get the existing system metadata for the object
292
      SystemMetadata existingSysMeta = getSystemMetadata(session, pid);
293
294
      // add the obsoleted pid to the obsoletedBy list
295
      List<Identifier> obsoletedList = existingSysMeta.getObsoletedByList();
296
      obsoletedList.add(pid);
297
      existingSysMeta.setObsoletedByList(obsoletedList);
298
299
      // then update the existing system metadata
300
      updateSystemMetadata(existingSysMeta);
301
302
      // prep the new system metadata, add pid to the obsoletes list
303
      sysmeta.addObsolete(pid);
304
305
      // and insert the new system metadata
306
      insertSystemMetadata(sysmeta);
307
308
      isScienceMetadata = isScienceMetadata(sysmeta);
309
310
      // do we have XML metadata or a data object?
311
      if ( isScienceMetadata ) {
312
313
        // update the science metadata XML document
314
        // TODO: handle non-XML metadata/data documents (like netCDF)
315
        // TODO: don't put objects into memory using stream to string
316
        String objectAsXML = "";
317
        try {
318
          objectAsXML = IOUtils.toString(object, "UTF-8");
319
          localId = insertOrUpdateDocument(objectAsXML, newPid, session, "update");
320
          // register the newPid and the generated localId
321
          if ( newPid != null ) {
322
            im.createMapping(newPid.getValue(), localId);
323
324
          }
325
326
        } catch (IOException e) {
327
          String msg = "The Node is unable to create the object. " +
328 6258 cjones
          "There was a problem converting the object to XML";
329 6259 cjones
          logMetacat.info(msg);
330 6258 cjones
          throw new ServiceFailure("1310", msg + ": " + e.getMessage());
331 6259 cjones
332
        }
333
334
      } else {
335
336
        // update the data object
337
        localId = insertDataObject(object, newPid, session);
338
        // register the newPid and the generated localId
339
        if ( newPid != null ) {
340
          im.createMapping(newPid.getValue(), localId);
341
342
        }
343
344
      }
345
      // log the update event
346 6258 cjones
      EventLog.getInstance().log(metacatUrl, subject.getValue(), localId, "update");
347
348 6259 cjones
    } else {
349
      throw new NotAuthorized("1200", "The provided identity does not have " +
350
      "permission to UPDATE the object identified by " +
351
      pid.getValue() + " on the Member Node.");
352
353
    }
354 6254 cjones
355 6259 cjones
    return pid;
356
  }
357 6179 cjones
358
  /**
359
   * Called by a Coordinating Node to request that the Member Node create a
360
   * copy of the specified object by retrieving it from another Member
361
   * Node and storing it locally so that it can be made accessible to
362
   * the DataONE system.
363
   *
364 6259 cjones
   * @param session - the Session object containing the credentials for the Subject
365
   * @param sysmeta - Copy of the CN held system metadata for the object
366
   * @param sourceNode - A reference to node from which the content should be
367
   *                     retrieved. The reference should be resolved by
368
   *                     checking the CN node registry.
369
   *
370
   * @return true if the replication succeeds
371
   *
372
   * @throws ServiceFailure
373
   * @throws NotAuthorized
374
   * @throws NotImplemented
375
   * @throws UnsupportedType
376
   * @throws InsufficientResources
377
   * @throws InvalidRequest
378 6179 cjones
   */
379
  @Override
380 6259 cjones
  public boolean replicate(Session session, SystemMetadata sysmeta,
381
    NodeReference sourceNode)
382
    throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest,
383
    InsufficientResources, UnsupportedType {
384 6179 cjones
385 6259 cjones
    return false;
386
  }
387 6179 cjones
388
  /**
389
   * This method provides a lighter weight mechanism than
390
   * MN_read.getSystemMetadata() for a client to determine basic
391
   * properties of the referenced object.
392
   *
393 6259 cjones
   * @param session - the Session object containing the credentials for the Subject
394
   * @param pid - the identifier of the object to be described
395
   *
396
   * @return describeResponse - A set of values providing a basic description
397
   *                            of the object.
398
   *
399
   * @throws InvalidToken
400
   * @throws ServiceFailure
401
   * @throws NotAuthorized
402
   * @throws NotFound
403
   * @throws NotImplemented
404
   * @throws InvalidRequest
405 6179 cjones
   */
406
  @Override
407 6259 cjones
  public DescribeResponse describe(Session session, Identifier pid)
408
    throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
409
    NotImplemented, InvalidRequest {
410 6229 cjones
411 6259 cjones
    if(session == null) {
412 6229 cjones
      throw new InvalidToken("1370", "The session object is null");
413
414
    }
415
416
    if(pid == null || pid.getValue().trim().equals(""))
417
    {
418
      throw new InvalidRequest("1362", "The object identifier is null. " +
419
        "A valid identifier is required.");
420
421
    }
422
423
    SystemMetadata sysmeta = getSystemMetadata(session, pid);
424
    DescribeResponse describeResponse =
425 6259 cjones
      new DescribeResponse(sysmeta.getObjectFormat(),
426 6229 cjones
      sysmeta.getSize(), sysmeta.getDateSysMetadataModified(), sysmeta.getChecksum());
427
428
    return describeResponse;
429 6179 cjones
430 6259 cjones
  }
431 6179 cjones
432 6259 cjones
  /**
433
   * Return the object identified by the given object identifier
434
   *
435
   * @param session - the Session object containing the credentials for the Subject
436
   * @param pid - the object identifier for the given object
437
   *
438
   * @return inputStream - the input stream of the given object
439
   *
440
   * @throws InvalidToken
441
   * @throws ServiceFailure
442
   * @throws NotAuthorized
443
   * @throws InvalidRequest
444
   * @throws NotImplemented
445
   */
446 6179 cjones
  @Override
447 6259 cjones
  public InputStream get(Session session, Identifier pid)
448
    throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
449
    NotImplemented, InvalidRequest {
450
451
    return super.get(session, pid);
452
453
  }
454 6179 cjones
455 6259 cjones
  /**
456
   * Returns a Checksum for the specified object using an accepted hashing algorithm
457
   *
458
   * @param session - the Session object containing the credentials for the Subject
459
   * @param pid - the object identifier for the given object
460
   * @param algorithm -  the name of an algorithm that will be used to compute
461
   *                     a checksum of the bytes of the object
462
   *
463
   * @return checksum - the checksum of the given object
464
   *
465
   * @throws InvalidToken
466
   * @throws ServiceFailure
467
   * @throws NotAuthorized
468
   * @throws NotFound
469
   * @throws InvalidRequest
470
   * @throws NotImplemented
471
   */
472 6179 cjones
  @Override
473 6259 cjones
  public Checksum getChecksum(Session session, Identifier pid, String algorithm)
474
    throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
475
    InvalidRequest, NotImplemented {
476 6179 cjones
477 6259 cjones
    Checksum checksum = null;
478 6228 cjones
479 6259 cjones
    InputStream inputStream = get(session, pid);
480
481
    try {
482
      checksum =
483
        ServiceTypeUtil.checksum(inputStream, ChecksumAlgorithm.convert(algorithm));
484
485
    } catch (NoSuchAlgorithmException e) {
486 6228 cjones
      throw new ServiceFailure("1410", "The checksum for the object specified by " +
487
        pid.getValue() +
488
        "could not be returned due to an internal error: " +
489
        e.getMessage());
490
491
    } catch (IOException e) {
492
      throw new ServiceFailure("1410", "The checksum for the object specified by " +
493
        pid.getValue() +
494
        "could not be returned due to an internal error: " +
495
        e.getMessage());
496
497
    }
498 6259 cjones
499 6228 cjones
    if ( checksum == null ) {
500
      throw new ServiceFailure("1410", "The checksum for the object specified by " +
501
        pid.getValue() +
502
        "could not be returned.");
503
504
    }
505
506 6259 cjones
    return checksum;
507
  }
508 6179 cjones
509 6259 cjones
  /**
510
   * Return the system metadata for a given object
511
   *
512
   * @param session - the Session object containing the credentials for the Subject
513
   * @param pid - the object identifier for the given object
514
   *
515
   * @return inputStream - the input stream of the given system metadata object
516
   *
517
   * @throws InvalidToken
518
   * @throws ServiceFailure
519
   * @throws NotAuthorized
520
   * @throws NotFound
521
   * @throws InvalidRequest
522
   * @throws NotImplemented
523
   */
524 6179 cjones
  @Override
525 6259 cjones
  public SystemMetadata getSystemMetadata(Session session, Identifier pid)
526
      throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
527
      InvalidRequest, NotImplemented {
528 6179 cjones
529 6259 cjones
    return super.getSystemMetadata(session, pid);
530
  }
531 6179 cjones
532 6259 cjones
  /**
533
   * Retrieve the list of objects present on the MN that match the calling parameters
534
   *
535
   * @param session - the Session object containing the credentials for the Subject
536
   * @param startTime - Specifies the beginning of the time range from which
537
   *                    to return object (>=)
538
   * @param endTime - Specifies the beginning of the time range from which
539
   *                  to return object (>=)
540
   * @param objectFormat - Restrict results to the specified object format
541
   * @param replicaStatus - Indicates if replicated objects should be returned in the list
542
   * @param start - The zero-based index of the first value, relative to the
543
   *                first record of the resultset that matches the parameters.
544
   * @param count - The maximum number of entries that should be returned in
545
   *                the response. The Member Node may return less entries
546
   *                than specified in this value.
547
   *
548
   * @return objectList - the list of objects matching the criteria
549
   *
550
   * @throws InvalidToken
551
   * @throws ServiceFailure
552
   * @throws NotAuthorized
553
   * @throws InvalidRequest
554
   * @throws NotImplemented
555
   */
556 6179 cjones
  @Override
557 6259 cjones
  public ObjectList listObjects(Session session, Date startTime, Date endTime,
558
    ObjectFormat objectFormat, Boolean replicaStatus, Integer start, Integer count)
559
    throws NotAuthorized, InvalidRequest, NotImplemented, ServiceFailure,
560
    InvalidToken {
561 6179 cjones
562 6259 cjones
    ObjectList objectList = null;
563
564
    objectList = IdentifierManager.getInstance().querySystemMetadata(startTime, endTime,
565 6230 cjones
        objectFormat, replicaStatus, start, count);
566 6259 cjones
567
    if ( objectList == null ) {
568
      throw new ServiceFailure("1580", "The object list was null.");
569
    }
570
571
    return objectList;
572
  }
573 6179 cjones
574 6259 cjones
  /**
575
   * Retrieve the list of objects present on the MN that match the calling parameters
576
   *
577
   * @return node - the technical capabilities of the Member Node
578
   *
579
   * @throws ServiceFailure
580
   * @throws NotAuthorized
581
   * @throws InvalidRequest
582
   * @throws NotImplemented
583
   */
584 6179 cjones
  @Override
585 6259 cjones
  public Node getCapabilities() throws NotImplemented, NotAuthorized,
586
      ServiceFailure, InvalidRequest {
587 6179 cjones
588 6261 cjones
		throw new NotImplemented("2160", "getCapabilities() not yet implemented");
589 6259 cjones
  }
590 6179 cjones
591 6259 cjones
  /**
592
   * Returns the number of operations that have been serviced by the node
593
   * over time periods of one and 24 hours.
594
   *
595
   * @param session - the Session object containing the credentials for the Subject
596
   * @param period - An ISO8601 compatible DateTime range specifying the time
597
   *                 range for which to return operation statistics.
598
   * @param requestor - Limit to operations performed by given requestor identity.
599
   * @param event -  Enumerated value indicating the type of event being examined
600
   * @param format - Limit to events involving objects of the specified format
601
   *
602
   * @return the desired log records
603
   *
604
   * @throws InvalidToken
605
   * @throws ServiceFailure
606
   * @throws NotAuthorized
607
   * @throws InvalidRequest
608
   * @throws NotImplemented
609
   */
610 6179 cjones
  @Override
611 6259 cjones
  public MonitorList getOperationStatistics(Session session, Integer period,
612
    Subject requestor, Event event, ObjectFormat format)
613 6179 cjones
    throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest,
614
    InsufficientResources, UnsupportedType {
615
616 6261 cjones
		throw new NotImplemented("2080", "getOperationsStatistics not yet implemented");
617 6259 cjones
  }
618 6179 cjones
619
  /**
620
   * Low level “are you alive” operation. A valid ping response is
621
   * indicated by a HTTP status of 200.
622
   *
623
   * @return true if the service is alive
624
   *
625 6259 cjones
   * @throws InvalidToken
626
   * @throws ServiceFailure
627
   * @throws NotAuthorized
628
   * @throws InvalidRequest
629
   * @throws NotImplemented
630 6179 cjones
   */
631 6259 cjones
  @Override
632
  public boolean ping()
633
    throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest,
634
    InsufficientResources, UnsupportedType {
635 6179 cjones
636 6260 cjones
    // test if we can get a database connection
637
    boolean alive = false;
638
    int serialNumber = -1;
639
    DBConnection dbConn = null;
640
    try {
641
      dbConn = DBConnectionPool
642
      .getDBConnection("MNodeService.ping");
643
      serialNumber = dbConn.getCheckOutSerialNumber();
644
      alive = true;
645
646
    } catch (SQLException e) {
647
      return alive;
648
649
    } finally {
650
      // Return the database connection
651
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
652
653
    }
654
655
    return alive;
656 6259 cjones
  }
657 6179 cjones
658 6213 cjones
  /**
659
   * A callback method used by a CN to indicate to a MN that it cannot
660 6234 cjones
   * complete synchronization of the science metadata identified by pid.  Log
661
   * the event in the metacat event log.
662 6213 cjones
   *
663
   * @param session
664
   * @param syncFailed
665 6259 cjones
   *
666
   * @throws ServiceFailure
667
   * @throws NotAuthorized
668
   * @throws InvalidRequest
669
   * @throws NotImplemented
670 6213 cjones
   */
671 6259 cjones
  @Override
672 6213 cjones
  public void synchronizationFailed(Session session, SynchronizationFailed syncFailed)
673
      throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest {
674 6179 cjones
675 6259 cjones
    String localId;
676
677
    try {
678
      localId = IdentifierManager.getInstance().getLocalId(syncFailed.getPid().getValue());
679 6234 cjones
    } catch (McdbDocNotFoundException e) {
680
      throw new ServiceFailure("2161", "The identifier specified by " +
681 6259 cjones
          syncFailed.getPid().getValue() +
682
          " was not found on this node.");
683 6234 cjones
684
    }
685 6259 cjones
    // TODO: update the CN URL below when the CNRead.SynchronizationFailed
686 6234 cjones
    // method is changed to include the URL as a parameter
687
    logMetacat.debug("Synchronization for the object identified by " +
688 6259 cjones
      syncFailed.getPid().getValue() +
689
      " failed from " +
690
      "CN URL WILL GO HERE." +
691
      " Logging the event to the Metacat EventLog as a 'syncFailed' event.");
692 6234 cjones
    EventLog.getInstance().log("CN URL WILL GO HERE",
693 6259 cjones
        session.getSubject().getValue(), localId, "syncFailed");
694 6234 cjones
695 6213 cjones
  }
696 6185 leinfelder
697 6179 cjones
}