Project

General

Profile

1 6177 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 6569 cjones
import java.io.InputStream;
27 6567 cjones
import java.math.BigInteger;
28 6883 leinfelder
import java.util.ArrayList;
29 6567 cjones
import java.util.Calendar;
30 6177 cjones
import java.util.Date;
31 6220 leinfelder
import java.util.List;
32 6859 cjones
import java.util.concurrent.locks.Lock;
33 6177 cjones
34 6542 leinfelder
import javax.servlet.http.HttpServletRequest;
35
36 6178 cjones
import org.apache.log4j.Logger;
37 6484 cjones
import org.dataone.client.CNode;
38
import org.dataone.client.D1Client;
39 7073 cjones
import org.dataone.client.MNode;
40 6366 leinfelder
import org.dataone.service.cn.v1.CNAuthorization;
41
import org.dataone.service.cn.v1.CNCore;
42
import org.dataone.service.cn.v1.CNRead;
43
import org.dataone.service.cn.v1.CNReplication;
44 6792 cjones
import org.dataone.service.exceptions.BaseException;
45 6177 cjones
import org.dataone.service.exceptions.IdentifierNotUnique;
46
import org.dataone.service.exceptions.InsufficientResources;
47
import org.dataone.service.exceptions.InvalidRequest;
48
import org.dataone.service.exceptions.InvalidSystemMetadata;
49
import org.dataone.service.exceptions.InvalidToken;
50
import org.dataone.service.exceptions.NotAuthorized;
51
import org.dataone.service.exceptions.NotFound;
52
import org.dataone.service.exceptions.NotImplemented;
53
import org.dataone.service.exceptions.ServiceFailure;
54 6569 cjones
import org.dataone.service.exceptions.UnsupportedType;
55 6869 cjones
import org.dataone.service.exceptions.VersionMismatch;
56 6571 cjones
import org.dataone.service.types.v1.AccessPolicy;
57 6366 leinfelder
import org.dataone.service.types.v1.Checksum;
58 6803 leinfelder
import org.dataone.service.types.v1.ChecksumAlgorithmList;
59 7144 leinfelder
import org.dataone.service.types.v1.DescribeResponse;
60
import org.dataone.service.types.v1.Event;
61 6366 leinfelder
import org.dataone.service.types.v1.Identifier;
62 7144 leinfelder
import org.dataone.service.types.v1.Log;
63 6463 cjones
import org.dataone.service.types.v1.Node;
64 6366 leinfelder
import org.dataone.service.types.v1.NodeList;
65 6409 cjones
import org.dataone.service.types.v1.NodeReference;
66 6570 cjones
import org.dataone.service.types.v1.NodeType;
67 6366 leinfelder
import org.dataone.service.types.v1.ObjectFormat;
68
import org.dataone.service.types.v1.ObjectFormatIdentifier;
69
import org.dataone.service.types.v1.ObjectFormatList;
70
import org.dataone.service.types.v1.ObjectList;
71
import org.dataone.service.types.v1.ObjectLocationList;
72
import org.dataone.service.types.v1.Permission;
73
import org.dataone.service.types.v1.Replica;
74
import org.dataone.service.types.v1.ReplicationPolicy;
75
import org.dataone.service.types.v1.ReplicationStatus;
76
import org.dataone.service.types.v1.Session;
77
import org.dataone.service.types.v1.Subject;
78
import org.dataone.service.types.v1.SystemMetadata;
79 6881 leinfelder
import org.dataone.service.types.v1.util.ServiceMethodRestrictionUtil;
80 7401 cjones
import org.dataone.service.types.v1_1.QueryEngineDescription;
81
import org.dataone.service.types.v1_1.QueryEngineList;
82 6177 cjones
83 6188 leinfelder
import edu.ucsb.nceas.metacat.EventLog;
84
import edu.ucsb.nceas.metacat.IdentifierManager;
85 6446 leinfelder
import edu.ucsb.nceas.metacat.dataone.hazelcast.HazelcastService;
86 6188 leinfelder
87 6177 cjones
/**
88
 * Represents Metacat's implementation of the DataONE Coordinating Node
89 6179 cjones
 * service API. Methods implement the various CN* interfaces, and methods common
90 6177 cjones
 * to both Member Node and Coordinating Node interfaces are found in the
91
 * D1NodeService super class.
92
 *
93
 */
94
public class CNodeService extends D1NodeService implements CNAuthorization,
95 6446 leinfelder
    CNCore, CNRead, CNReplication {
96 6177 cjones
97 6178 cjones
  /* the logger instance */
98
  private Logger logMetacat = null;
99 6177 cjones
100 6178 cjones
  /**
101
   * singleton accessor
102
   */
103 6542 leinfelder
  public static CNodeService getInstance(HttpServletRequest request) {
104
    return new CNodeService(request);
105 6178 cjones
  }
106
107
  /**
108
   * Constructor, private for singleton access
109
   */
110 6542 leinfelder
  private CNodeService(HttpServletRequest request) {
111
    super(request);
112 6178 cjones
    logMetacat = Logger.getLogger(CNodeService.class);
113
114
  }
115
116 6410 cjones
  /**
117
   * Set the replication policy for an object given the object identifier
118
   *
119
   * @param session - the Session object containing the credentials for the Subject
120
   * @param pid - the object identifier for the given object
121
   * @param policy - the replication policy to be applied
122
   *
123
   * @return true or false
124
   *
125
   * @throws NotImplemented
126
   * @throws NotAuthorized
127
   * @throws ServiceFailure
128
   * @throws InvalidRequest
129 6869 cjones
   * @throws VersionMismatch
130 6410 cjones
   *
131
   */
132 6471 jones
  @Override
133 6410 cjones
  public boolean setReplicationPolicy(Session session, Identifier pid,
134 6593 cjones
      ReplicationPolicy policy, long serialVersion)
135 6567 cjones
      throws NotImplemented, NotFound, NotAuthorized, ServiceFailure,
136 6869 cjones
      InvalidRequest, InvalidToken, VersionMismatch {
137 6567 cjones
138 6717 cjones
      // The lock to be used for this identifier
139 6859 cjones
      Lock lock = null;
140 6702 cjones
141 6567 cjones
      // get the subject
142
      Subject subject = session.getSubject();
143
144
      // are we allowed to do this?
145 7068 cjones
      if (!isAuthorized(session, pid, Permission.CHANGE_PERMISSION)) {
146
          throw new NotAuthorized("4881", Permission.CHANGE_PERMISSION
147
                  + " not allowed by " + subject.getValue() + " on "
148
                  + pid.getValue());
149
150 6869 cjones
      }
151
152
      SystemMetadata systemMetadata = null;
153 6567 cjones
      try {
154 6858 cjones
          lock = HazelcastService.getInstance().getLock(pid.getValue());
155
          lock.lock();
156 6867 cjones
          logMetacat.debug("Locked identifier " + pid.getValue());
157 6858 cjones
158
          try {
159
              if ( HazelcastService.getInstance().getSystemMetadataMap().containsKey(pid) ) {
160
                  systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
161
162
              }
163 6869 cjones
164
              // did we get it correctly?
165
              if ( systemMetadata == null ) {
166
                  throw new NotFound("4884", "Couldn't find an object identified by " + pid.getValue());
167
168
              }
169 6858 cjones
170
              // does the request have the most current system metadata?
171
              if ( systemMetadata.getSerialVersion().longValue() != serialVersion ) {
172
                 String msg = "The requested system metadata version number " +
173
                     serialVersion + " differs from the current version at " +
174
                     systemMetadata.getSerialVersion().longValue() +
175
                     ". Please get the latest copy in order to modify it.";
176 6869 cjones
                 throw new VersionMismatch("4886", msg);
177
178 6858 cjones
              }
179 6717 cjones
180 6869 cjones
          } catch (RuntimeException e) { // Catch is generic since HZ throws RuntimeException
181 6858 cjones
              throw new NotFound("4884", "No record found for: " + pid.getValue());
182
183 6717 cjones
          }
184 6858 cjones
185
          // set the new policy
186
          systemMetadata.setReplicationPolicy(policy);
187
188
          // update the metadata
189
          try {
190
              systemMetadata.setSerialVersion(systemMetadata.getSerialVersion().add(BigInteger.ONE));
191
              systemMetadata.setDateSysMetadataModified(Calendar.getInstance().getTime());
192
              HazelcastService.getInstance().getSystemMetadataMap().put(systemMetadata.getIdentifier(), systemMetadata);
193 7076 cjones
              notifyReplicaNodes(systemMetadata);
194
195 6869 cjones
          } catch (RuntimeException e) {
196 6858 cjones
              throw new ServiceFailure("4882", e.getMessage());
197
198 6593 cjones
          }
199
200 6869 cjones
      } catch (RuntimeException e) {
201
          throw new ServiceFailure("4882", e.getMessage());
202
203
      } finally {
204
          lock.unlock();
205
          logMetacat.debug("Unlocked identifier " + pid.getValue());
206
207
      }
208 6410 cjones
209 6567 cjones
      return true;
210 6410 cjones
  }
211 6177 cjones
212 6410 cjones
  /**
213 6881 leinfelder
   * Deletes the replica from the given Member Node
214
   * NOTE: MN.delete() may be an "archive" operation. TBD.
215
   * @param session
216
   * @param pid
217
   * @param nodeId
218
   * @param serialVersion
219
   * @return
220
   * @throws InvalidToken
221
   * @throws ServiceFailure
222
   * @throws NotAuthorized
223
   * @throws NotFound
224
   * @throws NotImplemented
225 6883 leinfelder
   * @throws VersionMismatch
226 6881 leinfelder
   */
227 6884 leinfelder
  @Override
228 6881 leinfelder
  public boolean deleteReplicationMetadata(Session session, Identifier pid, NodeReference nodeId, long serialVersion)
229 6883 leinfelder
  	throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, VersionMismatch {
230 6881 leinfelder
231 6883 leinfelder
	  	// The lock to be used for this identifier
232
		Lock lock = null;
233
234
		// get the subject
235
		Subject subject = session.getSubject();
236
237
		// are we allowed to do this?
238 7068 cjones
		boolean isAuthorized = false;
239
		try {
240
			isAuthorized = isAuthorized(session, pid, Permission.WRITE);
241
		} catch (InvalidRequest e) {
242
			throw new ServiceFailure("4882", e.getDescription());
243
		}
244
		if (!isAuthorized) {
245
			throw new NotAuthorized("4881", Permission.WRITE
246
					+ " not allowed by " + subject.getValue() + " on "
247
					+ pid.getValue());
248 6883 leinfelder
249
		}
250
251
		SystemMetadata systemMetadata = null;
252
		try {
253
			lock = HazelcastService.getInstance().getLock(pid.getValue());
254
			lock.lock();
255
			logMetacat.debug("Locked identifier " + pid.getValue());
256
257
			try {
258
				if (HazelcastService.getInstance().getSystemMetadataMap().containsKey(pid)) {
259
					systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
260
				}
261
262
				// did we get it correctly?
263
				if (systemMetadata == null) {
264
					throw new NotFound("4884", "Couldn't find an object identified by " + pid.getValue());
265
				}
266
267
				// does the request have the most current system metadata?
268
				if (systemMetadata.getSerialVersion().longValue() != serialVersion) {
269
					String msg = "The requested system metadata version number "
270
							+ serialVersion
271
							+ " differs from the current version at "
272
							+ systemMetadata.getSerialVersion().longValue()
273
							+ ". Please get the latest copy in order to modify it.";
274
					throw new VersionMismatch("4886", msg);
275
276
				}
277
278
			} catch (RuntimeException e) { // Catch is generic since HZ throws RuntimeException
279
				throw new NotFound("4884", "No record found for: " + pid.getValue());
280
281
			}
282
283
			// check permissions
284
			// TODO: is this necessary?
285
			List<Node> nodeList = D1Client.getCN().listNodes().getNodeList();
286
			boolean isAllowed = ServiceMethodRestrictionUtil.isMethodAllowed(session.getSubject(), nodeList, "CNReplication", "deleteReplicationMetadata");
287 7218 cjones
			if (!isAllowed) {
288 6883 leinfelder
				throw new NotAuthorized("4881", "Caller is not authorized to deleteReplicationMetadata");
289
			}
290
291
			// delete the replica from the given node
292 7252 cjones
			// CSJ: use CN.delete() to truly delete a replica, semantically
293
			// deleteReplicaMetadata() only modifies the sytem metadata entry.
294 7251 cjones
			//D1Client.getMN(nodeId).delete(session, pid);
295 6883 leinfelder
296
			// reflect that change in the system metadata
297
			List<Replica> updatedReplicas = new ArrayList<Replica>(systemMetadata.getReplicaList());
298
			for (Replica r: systemMetadata.getReplicaList()) {
299
				  if (r.getReplicaMemberNode().equals(nodeId)) {
300
					  updatedReplicas.remove(r);
301
					  break;
302
				  }
303
			}
304
			systemMetadata.setReplicaList(updatedReplicas);
305
306
			// update the metadata
307
			try {
308
				systemMetadata.setSerialVersion(systemMetadata.getSerialVersion().add(BigInteger.ONE));
309
				systemMetadata.setDateSysMetadataModified(Calendar.getInstance().getTime());
310
				HazelcastService.getInstance().getSystemMetadataMap().put(systemMetadata.getIdentifier(), systemMetadata);
311
			} catch (RuntimeException e) {
312
				throw new ServiceFailure("4882", e.getMessage());
313
			}
314
315
		} catch (RuntimeException e) {
316
			throw new ServiceFailure("4882", e.getMessage());
317
		} finally {
318
			lock.unlock();
319
			logMetacat.debug("Unlocked identifier " + pid.getValue());
320
		}
321
322
		return true;
323 6881 leinfelder
324
  }
325
326 6883 leinfelder
  /**
327 7077 leinfelder
   * Deletes an object from the Coordinating Node, where the object is a
328
   * a science metadata object.
329
   *
330
   * @param session - the Session object containing the credentials for the Subject
331
   * @param pid - The object identifier to be deleted
332
   *
333
   * @return pid - the identifier of the object used for the deletion
334
   *
335
   * @throws InvalidToken
336
   * @throws ServiceFailure
337
   * @throws NotAuthorized
338
   * @throws NotFound
339
   * @throws NotImplemented
340
   * @throws InvalidRequest
341
   */
342
  @Override
343
  public Identifier delete(Session session, Identifier pid)
344
      throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented {
345
346 7078 leinfelder
	  // check that it is CN/admin
347 7142 leinfelder
	  boolean allowed = isAdminAuthorized(session);
348 7077 leinfelder
349 7078 leinfelder
	  if (!allowed) {
350
		  String msg = "The subject is not allowed to call delete() on a Coordinating Node.";
351
		  logMetacat.info(msg);
352
		  throw new NotAuthorized("1320", msg);
353
	  }
354
355 7077 leinfelder
	  // defer to superclass implementation
356 7147 leinfelder
	  Identifier retId =  super.delete(session, pid);
357
358
	  // notify the replicas
359
	  SystemMetadata systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
360
	  if (systemMetadata.getReplicaList() != null) {
361
		  for (Replica replica: systemMetadata.getReplicaList()) {
362
			  NodeReference replicaNode = replica.getReplicaMemberNode();
363
			  try {
364
				  Identifier mnRetId = D1Client.getMN(replicaNode).delete(null, pid);
365
			  } catch (Exception e) {
366
				  // all we can really do is log errors and carry on with life
367
				  logMetacat.error("Error deleting pid: " +  pid.getValue() + " from replica MN: " + replicaNode.getValue(), e);
368
			}
369
370
		  }
371
	  }
372
373
	  return retId;
374
375 7077 leinfelder
  }
376
377
  /**
378 7148 leinfelder
   * Deletes an object from the Coordinating Node, where the object is a
379
   * a science metadata object.
380
   *
381
   * @param session - the Session object containing the credentials for the Subject
382
   * @param pid - The object identifier to be deleted
383
   *
384
   * @return pid - the identifier of the object used for the deletion
385
   *
386
   * @throws InvalidToken
387
   * @throws ServiceFailure
388
   * @throws NotAuthorized
389
   * @throws NotFound
390
   * @throws NotImplemented
391
   * @throws InvalidRequest
392
   */
393
  @Override
394
  public Identifier archive(Session session, Identifier pid)
395
      throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented {
396
397
	  // check that it is CN/admin
398
	  boolean allowed = isAdminAuthorized(session);
399
400
	  if (!allowed) {
401
		  String msg = "The subject is not allowed to call delete() on a Coordinating Node.";
402
		  logMetacat.info(msg);
403
		  throw new NotAuthorized("1320", msg);
404
	  }
405
406
	  // defer to superclass implementation
407
	  Identifier retId =  super.archive(session, pid);
408
409
	  // notify the replicas
410
	  SystemMetadata systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
411
	  if (systemMetadata.getReplicaList() != null) {
412
		  for (Replica replica: systemMetadata.getReplicaList()) {
413
			  NodeReference replicaNode = replica.getReplicaMemberNode();
414
			  try {
415
				  // TODO: implement in the clients
416
				  //Identifier mnRetId = D1Client.getMN(replicaNode).archive(null, pid);
417
			  } catch (Exception e) {
418
				  // all we can really do is log errors and carry on with life
419
				  logMetacat.error("Error archiving pid: " +  pid.getValue() + " from replica MN: " + replicaNode.getValue(), e);
420
			}
421
422
		  }
423
	  }
424
425
	  return retId;
426
427
  }
428
429
  /**
430 6883 leinfelder
   * Set the obsoletedBy attribute in System Metadata
431
   * @param session
432
   * @param pid
433
   * @param obsoletedByPid
434
   * @param serialVersion
435
   * @return
436
   * @throws NotImplemented
437
   * @throws NotFound
438
   * @throws NotAuthorized
439
   * @throws ServiceFailure
440
   * @throws InvalidRequest
441
   * @throws InvalidToken
442
   * @throws VersionMismatch
443
   */
444 6884 leinfelder
  @Override
445 6883 leinfelder
  public boolean setObsoletedBy(Session session, Identifier pid,
446
			Identifier obsoletedByPid, long serialVersion)
447
			throws NotImplemented, NotFound, NotAuthorized, ServiceFailure,
448
			InvalidRequest, InvalidToken, VersionMismatch {
449
450
		// The lock to be used for this identifier
451
		Lock lock = null;
452
453
		// get the subject
454
		Subject subject = session.getSubject();
455
456
		// are we allowed to do this?
457 7068 cjones
		if (!isAuthorized(session, pid, Permission.WRITE)) {
458
			throw new NotAuthorized("4881", Permission.WRITE
459
					+ " not allowed by " + subject.getValue() + " on "
460
					+ pid.getValue());
461 6883 leinfelder
462
		}
463
464 7068 cjones
465 6883 leinfelder
		SystemMetadata systemMetadata = null;
466
		try {
467
			lock = HazelcastService.getInstance().getLock(pid.getValue());
468
			lock.lock();
469
			logMetacat.debug("Locked identifier " + pid.getValue());
470
471
			try {
472
				if (HazelcastService.getInstance().getSystemMetadataMap().containsKey(pid)) {
473
					systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
474
				}
475
476
				// did we get it correctly?
477
				if (systemMetadata == null) {
478
					throw new NotFound("4884", "Couldn't find an object identified by " + pid.getValue());
479
				}
480
481
				// does the request have the most current system metadata?
482
				if (systemMetadata.getSerialVersion().longValue() != serialVersion) {
483
					String msg = "The requested system metadata version number "
484
							+ serialVersion
485
							+ " differs from the current version at "
486
							+ systemMetadata.getSerialVersion().longValue()
487
							+ ". Please get the latest copy in order to modify it.";
488
					throw new VersionMismatch("4886", msg);
489
490
				}
491
492
			} catch (RuntimeException e) { // Catch is generic since HZ throws RuntimeException
493
				throw new NotFound("4884", "No record found for: " + pid.getValue());
494
495
			}
496
497
			// set the new policy
498
			systemMetadata.setObsoletedBy(obsoletedByPid);
499
500
			// update the metadata
501
			try {
502
				systemMetadata.setSerialVersion(systemMetadata.getSerialVersion().add(BigInteger.ONE));
503
				systemMetadata.setDateSysMetadataModified(Calendar.getInstance().getTime());
504
				HazelcastService.getInstance().getSystemMetadataMap().put(systemMetadata.getIdentifier(), systemMetadata);
505
			} catch (RuntimeException e) {
506
				throw new ServiceFailure("4882", e.getMessage());
507
			}
508
509
		} catch (RuntimeException e) {
510
			throw new ServiceFailure("4882", e.getMessage());
511
		} finally {
512
			lock.unlock();
513
			logMetacat.debug("Unlocked identifier " + pid.getValue());
514
		}
515
516
		return true;
517
	}
518 6881 leinfelder
519 6883 leinfelder
520 6881 leinfelder
  /**
521 6410 cjones
   * Set the replication status for an object given the object identifier
522
   *
523
   * @param session - the Session object containing the credentials for the Subject
524
   * @param pid - the object identifier for the given object
525
   * @param status - the replication status to be applied
526
   *
527
   * @return true or false
528
   *
529
   * @throws NotImplemented
530
   * @throws NotAuthorized
531
   * @throws ServiceFailure
532
   * @throws InvalidRequest
533
   * @throws InvalidToken
534
   * @throws NotFound
535
   *
536
   */
537 6471 jones
  @Override
538 6410 cjones
  public boolean setReplicationStatus(Session session, Identifier pid,
539 6792 cjones
      NodeReference targetNode, ReplicationStatus status, BaseException failure)
540 6644 cjones
      throws ServiceFailure, NotImplemented, InvalidToken, NotAuthorized,
541
      InvalidRequest, NotFound {
542 7066 leinfelder
543
	  // cannot be called by public
544
	  if (session == null) {
545
		  throw new NotAuthorized("4720", "Session cannot be null");
546
	  }
547 6644 cjones
548 6702 cjones
      // The lock to be used for this identifier
549 6859 cjones
      Lock lock = null;
550 6702 cjones
551 6644 cjones
      boolean allowed = false;
552
      int replicaEntryIndex = -1;
553
      List<Replica> replicas = null;
554
      // get the subject
555
      Subject subject = session.getSubject();
556 6676 cjones
      logMetacat.debug("ReplicationStatus for identifier " + pid.getValue() +
557
          " is " + status.toString());
558 6644 cjones
559
      SystemMetadata systemMetadata = null;
560 6858 cjones
561
      try {
562 6703 cjones
          lock = HazelcastService.getInstance().getLock(pid.getValue());
563 6702 cjones
          lock.lock();
564 6867 cjones
          logMetacat.debug("Locked identifier " + pid.getValue());
565
566 6858 cjones
          try {
567
              systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
568 6657 cjones
569 6869 cjones
              // did we get it correctly?
570 6858 cjones
              if ( systemMetadata == null ) {
571
                  logMetacat.debug("systemMetadata is null for " + pid.getValue());
572 6869 cjones
                  throw new NotFound("4740", "Couldn't find an object identified by " + pid.getValue());
573 6858 cjones
574
              }
575
              replicas = systemMetadata.getReplicaList();
576
              int count = 0;
577 6657 cjones
578 6876 cjones
              // was there a failure? log it
579
              if ( failure != null && status == ReplicationStatus.FAILED ) {
580
                 String msg = "The replication request of the object identified by " +
581
                     pid.getValue() + " failed.  The error message was " +
582
                     failure.getMessage() + ".";
583 6858 cjones
              }
584 6869 cjones
585 6876 cjones
              if (replicas.size() > 0 && replicas != null) {
586
                  // find the target replica index in the replica list
587
                  for (Replica replica : replicas) {
588
                      String replicaNodeStr = replica.getReplicaMemberNode()
589
                              .getValue();
590
                      String targetNodeStr = targetNode.getValue();
591
                      logMetacat.debug("Comparing " + replicaNodeStr + " to "
592
                              + targetNodeStr);
593 6869 cjones
594 6876 cjones
                      if (replicaNodeStr.equals(targetNodeStr)) {
595
                          replicaEntryIndex = count;
596
                          logMetacat.debug("replica entry index is: "
597
                                  + replicaEntryIndex);
598
                          break;
599
                      }
600
                      count++;
601 6858 cjones
602
                  }
603
              }
604
              // are we allowed to do this? only CNs and target MNs are allowed
605
              CNode cn = D1Client.getCN();
606
              List<Node> nodes = cn.listNodes().getNodeList();
607 6657 cjones
608 6858 cjones
              // find the node in the node list
609
              for ( Node node : nodes ) {
610
611
                  NodeReference nodeReference = node.getIdentifier();
612
                  logMetacat.debug("In setReplicationStatus(), Node reference is: " + nodeReference.getValue());
613
614 7074 cjones
                  // allow target MN certs
615
                  if (targetNode.getValue().equals(nodeReference.getValue()) &&
616 7071 cjones
                      node.getType() == NodeType.MN) {
617 6858 cjones
                      List<Subject> nodeSubjects = node.getSubjectList();
618
619
                      // check if the session subject is in the node subject list
620
                      for (Subject nodeSubject : nodeSubjects) {
621 7071 cjones
                          logMetacat.debug("In setReplicationStatus(), comparing subjects: " +
622
                                  nodeSubject.getValue() + " and " + subject.getValue());
623 7074 cjones
                          if ( nodeSubject.equals(subject) ) { // subject of session == target node subject
624 6858 cjones
625 7179 cjones
                              // lastly limit to COMPLETED, INVALIDATED,
626
                              // and FAILED status updates from MNs only
627 7086 cjones
                              if ( status == ReplicationStatus.COMPLETED ||
628 7179 cjones
                                   status == ReplicationStatus.INVALIDATED ||
629 7086 cjones
                                   status == ReplicationStatus.FAILED) {
630 7074 cjones
                                  allowed = true;
631
                                  break;
632
633
                              }
634 6858 cjones
                          }
635
                      }
636
                  }
637
              }
638 6657 cjones
639 7071 cjones
              if ( !allowed ) {
640
                  //check for CN admin access
641
                  allowed = isAuthorized(session, pid, Permission.WRITE);
642 6858 cjones
643 7071 cjones
              }
644
645
              if ( !allowed ) {
646
                  String msg = "The subject identified by "
647
                          + subject.getValue()
648
                          + " does not have permission to set the replication status for "
649
                          + "the replica identified by "
650
                          + targetNode.getValue() + ".";
651
                  logMetacat.info(msg);
652
                  throw new NotAuthorized("4720", msg);
653
654 6858 cjones
              }
655 6876 cjones
656 6858 cjones
          } catch (RuntimeException e) { // Catch is generic since HZ throws RuntimeException
657
            throw new NotFound("4740", "No record found for: " + pid.getValue() +
658
                " : " + e.getMessage());
659
660 6644 cjones
          }
661
662 6876 cjones
          Replica targetReplica = new Replica();
663 6858 cjones
          // set the status for the replica
664
          if ( replicaEntryIndex != -1 ) {
665 6876 cjones
              targetReplica = replicas.get(replicaEntryIndex);
666 7231 cjones
667
              // don't allow status to change from COMPLETED to anything other
668
              // than INVALIDATED: prevents overwrites from race conditions
669
              if ( targetReplica.getReplicationStatus() == ReplicationStatus.COMPLETED &&
670
            	   status != ReplicationStatus.INVALIDATED) {
671
            	  throw new InvalidRequest("4730", "Status state change from " +
672
            			  targetReplica.getReplicationStatus() + " to " +
673
            			  status.toString() + "is prohibited for identifier " +
674
            			  pid.getValue() + " and target node " +
675
            			  targetReplica.getReplicaMemberNode().getValue());
676
              }
677
678 6858 cjones
              targetReplica.setReplicationStatus(status);
679 7514 cjones
680 6858 cjones
              logMetacat.debug("Set the replication status for " +
681
                  targetReplica.getReplicaMemberNode().getValue() + " to " +
682 7231 cjones
                  targetReplica.getReplicationStatus() + " for identifier " +
683
                  pid.getValue());
684 6644 cjones
685 6858 cjones
          } else {
686 6876 cjones
              // this is a new entry, create it
687
              targetReplica.setReplicaMemberNode(targetNode);
688
              targetReplica.setReplicationStatus(status);
689
              targetReplica.setReplicaVerified(Calendar.getInstance().getTime());
690
              replicas.add(targetReplica);
691
692 6644 cjones
          }
693
694 6858 cjones
          systemMetadata.setReplicaList(replicas);
695
696
          // update the metadata
697
          try {
698
              systemMetadata.setSerialVersion(systemMetadata.getSerialVersion().add(BigInteger.ONE));
699
              systemMetadata.setDateSysMetadataModified(Calendar.getInstance().getTime());
700
              HazelcastService.getInstance().getSystemMetadataMap().put(systemMetadata.getIdentifier(), systemMetadata);
701 7179 cjones
702
              if ( status != ReplicationStatus.QUEUED && status != ReplicationStatus.REQUESTED) {
703
704
                logMetacat.trace("METRICS:\tREPLICATION:\tEND REQUEST:\tPID:\t" + pid.getValue() +
705
                          "\tNODE:\t" + targetNode.getValue() +
706
                          "\tSIZE:\t" + systemMetadata.getSize().intValue());
707
708
                logMetacat.trace("METRICS:\tREPLICATION:\t" + status.toString().toUpperCase() +
709
                          "\tPID:\t"  + pid.getValue() +
710
                          "\tNODE:\t" + targetNode.getValue() +
711
                          "\tSIZE:\t" + systemMetadata.getSize().intValue());
712
              }
713
714 6858 cjones
              if ( status == ReplicationStatus.FAILED && failure != null ) {
715
                  logMetacat.warn("Replication failed for identifier " + pid.getValue() +
716
                      " on target node " + targetNode + ". The exception was: " +
717
                      failure.getMessage());
718
              }
719 7514 cjones
720
			  // update the replica nodes about the completed replica when complete
721
              if (status == ReplicationStatus.COMPLETED) {
722
				broadcastSystemMetadataChange(systemMetadata);
723
			}
724
725 6869 cjones
          } catch (RuntimeException e) {
726 6858 cjones
              throw new ServiceFailure("4700", e.getMessage());
727
728 6644 cjones
          }
729
730 6867 cjones
    } catch (RuntimeException e) {
731
        String msg = "There was a RuntimeException getting the lock for " +
732
            pid.getValue();
733
        logMetacat.info(msg);
734
735
    } finally {
736 6858 cjones
        lock.unlock();
737
        logMetacat.debug("Unlocked identifier " + pid.getValue());
738 6593 cjones
739 6858 cjones
    }
740 6676 cjones
741 6644 cjones
      return true;
742 6410 cjones
  }
743
744 7514 cjones
  /*
745
   * Inform each replica node that system metadata has changed
746
   *
747
   * @param systemMetadata  the system metadata object with the replica list
748
   */
749
  private void broadcastSystemMetadataChange(SystemMetadata systemMetadata) {
750
751
      CNode cn = null;
752
      NodeList nodeList = new NodeList();
753
      List<Node> nodes = new ArrayList<Node>();
754
755
	  List<Replica> replicaList = systemMetadata.getReplicaList();
756
757
	  // get the node list so we know the node type
758
	  try {
759
		cn = D1Client.getCN();
760
		nodeList = cn.listNodes();
761
	    nodes = nodeList.getNodeList();
762
763
	    // iterate through the replica list and inform each MN of the system metadata change
764
		for (Replica replica : replicaList) {
765
		    NodeReference nodeId = replica.getReplicaMemberNode();
766
		    try {
767
		        for (Node node : nodes) {
768
		      	    if (node.getIdentifier() == nodeId) {
769
		      		    if ( node.getType() == NodeType.MN) {
770
		      		        MNode replicaNode = D1Client.getMN(nodeId);
771
		      		        // call MN.systemMetadataChanged();
772
		      		        replicaNode.systemMetadataChanged(getSession(),
773
		      		            systemMetadata.getIdentifier(),
774
		      		            systemMetadata.getSerialVersion().longValue(),
775
		      		            systemMetadata.getDateSysMetadataModified());
776
		      		        if (logMetacat.isDebugEnabled()) {
777
								logMetacat.debug("Called systemMetadataChanged() for identifier " +
778
		      		                systemMetadata.getIdentifier().getValue() +
779
		      		                " for node " + nodeId.getValue());
780
							}
781
		      		    }
782
		      	    }
783
		        }
784
785
		    } catch (BaseException e) {
786
			    logMetacat.error("Couldn't contact " + nodeId.getValue() +
787
		            " to inform it of the system metadata change for identifier " +
788
			  	  systemMetadata.getIdentifier().getValue());
789
		    }
790
		}
791
792
	  } catch (BaseException e1) {
793
		  logMetacat.error("Couldn't get the node list from the CN to broadcast the system " +
794
				    "metadata change for identifier " + systemMetadata.getIdentifier().getValue());
795
	  }
796
797
798
}
799
800
/**
801 6410 cjones
   * Return the checksum of the object given the identifier
802
   *
803
   * @param session - the Session object containing the credentials for the Subject
804
   * @param pid - the object identifier for the given object
805
   *
806
   * @return checksum - the checksum of the object
807
   *
808
   * @throws InvalidToken
809
   * @throws ServiceFailure
810
   * @throws NotAuthorized
811
   * @throws NotFound
812
   * @throws NotImplemented
813
   */
814 6471 jones
  @Override
815 6410 cjones
  public Checksum getChecksum(Session session, Identifier pid)
816
    throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
817 6622 leinfelder
    NotImplemented {
818 7029 leinfelder
819
	boolean isAuthorized = false;
820
	try {
821
		isAuthorized = isAuthorized(session, pid, Permission.READ);
822
	} catch (InvalidRequest e) {
823
		throw new ServiceFailure("1410", e.getDescription());
824
	}
825
    if (!isAuthorized) {
826 6568 cjones
        throw new NotAuthorized("1400", Permission.READ + " not allowed on " + pid.getValue());
827 6410 cjones
    }
828 6568 cjones
829 6410 cjones
    SystemMetadata systemMetadata = null;
830 6568 cjones
    Checksum checksum = null;
831
832 6410 cjones
    try {
833 6869 cjones
        systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
834
835
        if (systemMetadata == null ) {
836
            throw new NotFound("1420", "Couldn't find an object identified by " + pid.getValue());
837
        }
838 6568 cjones
        checksum = systemMetadata.getChecksum();
839 6869 cjones
840
    } catch (RuntimeException e) {
841 6568 cjones
        throw new ServiceFailure("1410", "An error occurred getting the checksum for " +
842
            pid.getValue() + ". The error message was: " + e.getMessage());
843
844 6410 cjones
    }
845
846
    return checksum;
847
  }
848 6177 cjones
849 6410 cjones
  /**
850
   * Resolve the location of a given object
851
   *
852
   * @param session - the Session object containing the credentials for the Subject
853
   * @param pid - the object identifier for the given object
854
   *
855
   * @return objectLocationList - the list of nodes known to contain the object
856
   *
857
   * @throws InvalidToken
858
   * @throws ServiceFailure
859
   * @throws NotAuthorized
860
   * @throws NotFound
861
   * @throws NotImplemented
862
   */
863 6471 jones
  @Override
864 6410 cjones
  public ObjectLocationList resolve(Session session, Identifier pid)
865 6622 leinfelder
    throws InvalidToken, ServiceFailure, NotAuthorized,
866 6410 cjones
    NotFound, NotImplemented {
867 6177 cjones
868 6410 cjones
    throw new NotImplemented("4131", "resolve not implemented");
869 6303 leinfelder
870 6410 cjones
  }
871 6177 cjones
872 6410 cjones
  /**
873 7464 leinfelder
   * Metacat does not implement this method at the CN level
874 6410 cjones
   */
875 6471 jones
  @Override
876 6410 cjones
  public ObjectList search(Session session, String queryType, String query)
877
    throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest,
878
    NotImplemented {
879 6177 cjones
880 7464 leinfelder
		  throw new NotImplemented("4281", "Metacat does not implement CN.search");
881
882
//    ObjectList objectList = null;
883
//    try {
884
//        objectList =
885
//          IdentifierManager.getInstance().querySystemMetadata(
886
//              null, //startTime,
887
//              null, //endTime,
888
//              null, //objectFormat,
889
//              false, //replicaStatus,
890
//              0, //start,
891
//              1000 //count
892
//              );
893
//
894
//    } catch (Exception e) {
895
//      throw new ServiceFailure("4310", "Error querying system metadata: " + e.getMessage());
896
//    }
897
//
898
//      return objectList;
899
900 6410 cjones
  }
901
902
  /**
903
   * Returns the object format registered in the DataONE Object Format
904
   * Vocabulary for the given format identifier
905
   *
906
   * @param fmtid - the identifier of the format requested
907
   *
908
   * @return objectFormat - the object format requested
909
   *
910
   * @throws ServiceFailure
911
   * @throws NotFound
912
   * @throws InsufficientResources
913
   * @throws NotImplemented
914
   */
915 6471 jones
  @Override
916 6410 cjones
  public ObjectFormat getFormat(ObjectFormatIdentifier fmtid)
917 6803 leinfelder
    throws ServiceFailure, NotFound, NotImplemented {
918 6410 cjones
919
      return ObjectFormatService.getInstance().getFormat(fmtid);
920
921
  }
922 6177 cjones
923 6410 cjones
  /**
924 6177 cjones
   * Returns a list of all object formats registered in the DataONE Object
925
   * Format Vocabulary
926 6410 cjones
    *
927
   * @return objectFormatList - The list of object formats registered in
928
   *                            the DataONE Object Format Vocabulary
929
   *
930
   * @throws ServiceFailure
931
   * @throws NotImplemented
932
   * @throws InsufficientResources
933
   */
934 6471 jones
  @Override
935 6410 cjones
  public ObjectFormatList listFormats()
936 6803 leinfelder
    throws ServiceFailure, NotImplemented {
937 6177 cjones
938 6410 cjones
    return ObjectFormatService.getInstance().listFormats();
939
  }
940 6177 cjones
941 6410 cjones
  /**
942 6177 cjones
   * Returns a list of nodes that have been registered with the DataONE infrastructure
943 6410 cjones
    *
944
   * @return nodeList - List of nodes from the registry
945
   *
946
   * @throws ServiceFailure
947
   * @throws NotImplemented
948
   */
949 6471 jones
  @Override
950 6410 cjones
  public NodeList listNodes()
951
    throws NotImplemented, ServiceFailure {
952 6177 cjones
953 6410 cjones
    throw new NotImplemented("4800", "listNodes not implemented");
954
  }
955 6177 cjones
956 6410 cjones
  /**
957 6177 cjones
   * Provides a mechanism for adding system metadata independently of its
958
   * associated object, such as when adding system metadata for data objects.
959 6410 cjones
    *
960
   * @param session - the Session object containing the credentials for the Subject
961
   * @param pid - The identifier of the object to register the system metadata against
962
   * @param sysmeta - The system metadata to be registered
963
   *
964
   * @return true if the registration succeeds
965
   *
966
   * @throws NotImplemented
967
   * @throws NotAuthorized
968
   * @throws ServiceFailure
969
   * @throws InvalidRequest
970
   * @throws InvalidSystemMetadata
971
   */
972 6471 jones
  @Override
973 6575 cjones
  public Identifier registerSystemMetadata(Session session, Identifier pid,
974
      SystemMetadata sysmeta)
975
      throws NotImplemented, NotAuthorized, ServiceFailure, InvalidRequest,
976
      InvalidSystemMetadata {
977 6177 cjones
978 6702 cjones
      // The lock to be used for this identifier
979 6859 cjones
      Lock lock = null;
980 6702 cjones
981 6575 cjones
      // TODO: control who can call this?
982
      if (session == null) {
983
          //TODO: many of the thrown exceptions do not use the correct error codes
984
          //check these against the docs and correct them
985
          throw new NotAuthorized("4861", "No Session - could not authorize for registration." +
986
                  "  If you are not logged in, please do so and retry the request.");
987
      }
988
989
      // verify that guid == SystemMetadata.getIdentifier()
990
      logMetacat.debug("Comparing guid|sysmeta_guid: " + pid.getValue() +
991
          "|" + sysmeta.getIdentifier().getValue());
992
      if (!pid.getValue().equals(sysmeta.getIdentifier().getValue())) {
993
          throw new InvalidRequest("4863",
994
              "The identifier in method call (" + pid.getValue() +
995
              ") does not match identifier in system metadata (" +
996
              sysmeta.getIdentifier().getValue() + ").");
997
      }
998 6188 leinfelder
999 6575 cjones
      try {
1000 6703 cjones
          lock = HazelcastService.getInstance().getLock(sysmeta.getIdentifier().getValue());
1001 6863 cjones
          lock.lock();
1002 6867 cjones
          logMetacat.debug("Locked identifier " + pid.getValue());
1003 6863 cjones
          logMetacat.debug("Checking if identifier exists...");
1004
          // Check that the identifier does not already exist
1005
          if (HazelcastService.getInstance().getSystemMetadataMap().containsKey(pid)) {
1006
              throw new InvalidRequest("4863",
1007
                  "The identifier is already in use by an existing object.");
1008 6575 cjones
1009 6863 cjones
          }
1010
1011
          // insert the system metadata into the object store
1012
          logMetacat.debug("Starting to insert SystemMetadata...");
1013
          try {
1014
              sysmeta.setSerialVersion(BigInteger.ONE);
1015
              sysmeta.setDateSysMetadataModified(Calendar.getInstance().getTime());
1016
              HazelcastService.getInstance().getSystemMetadataMap().put(sysmeta.getIdentifier(), sysmeta);
1017
1018 6869 cjones
          } catch (RuntimeException e) {
1019 6863 cjones
            logMetacat.error("Problem registering system metadata: " + pid.getValue(), e);
1020
              throw new ServiceFailure("4862", "Error inserting system metadata: " +
1021
                  e.getClass() + ": " + e.getMessage());
1022
1023
          }
1024
1025 6869 cjones
      } catch (RuntimeException e) {
1026 6575 cjones
          throw new ServiceFailure("4862", "Error inserting system metadata: " +
1027 6863 cjones
                  e.getClass() + ": " + e.getMessage());
1028 6575 cjones
1029 6863 cjones
      }  finally {
1030
          lock.unlock();
1031
          logMetacat.debug("Unlocked identifier " + pid.getValue());
1032
1033
      }
1034 6466 cjones
1035 6575 cjones
1036
      logMetacat.debug("Returning from registerSystemMetadata");
1037
      EventLog.getInstance().log(request.getRemoteAddr(),
1038
          request.getHeader("User-Agent"), session.getSubject().getValue(),
1039
          pid.getValue(), "registerSystemMetadata");
1040
      return pid;
1041 6410 cjones
  }
1042
1043
  /**
1044 6177 cjones
   * Given an optional scope and format, reserves and returns an identifier
1045
   * within that scope and format that is unique and will not be
1046
   * used by any other sessions.
1047 6410 cjones
    *
1048
   * @param session - the Session object containing the credentials for the Subject
1049
   * @param pid - The identifier of the object to register the system metadata against
1050
   * @param scope - An optional string to be used to qualify the scope of
1051
   *                the identifier namespace, which is applied differently
1052
   *                depending on the format requested. If scope is not
1053
   *                supplied, a default scope will be used.
1054
   * @param format - The optional name of the identifier format to be used,
1055
   *                  drawn from a DataONE-specific vocabulary of identifier
1056
   *                 format names, including several common syntaxes such
1057
   *                 as DOI, LSID, UUID, and LSRN, among others. If the
1058
   *                 format is not supplied by the caller, the CN service
1059
   *                 will use a default identifier format, which may change
1060
   *                 over time.
1061
   *
1062
   * @return true if the registration succeeds
1063
   *
1064
   * @throws InvalidToken
1065
   * @throws ServiceFailure
1066
   * @throws NotAuthorized
1067
   * @throws IdentifierNotUnique
1068
   * @throws NotImplemented
1069
   */
1070 6471 jones
  @Override
1071 6622 leinfelder
  public Identifier reserveIdentifier(Session session, Identifier pid)
1072 6410 cjones
  throws InvalidToken, ServiceFailure,
1073 6378 leinfelder
        NotAuthorized, IdentifierNotUnique, NotImplemented, InvalidRequest {
1074 6177 cjones
1075 6410 cjones
    throw new NotImplemented("4191", "reserveIdentifier not implemented on this node");
1076
  }
1077
1078 6471 jones
  @Override
1079 6410 cjones
  public Identifier generateIdentifier(Session session, String scheme, String fragment)
1080
  throws InvalidToken, ServiceFailure,
1081 6378 leinfelder
        NotAuthorized, NotImplemented, InvalidRequest {
1082 6410 cjones
    throw new NotImplemented("4191", "generateIdentifier not implemented on this node");
1083
  }
1084
1085
  /**
1086
    * Checks whether the pid is reserved by the subject in the session param
1087
    * If the reservation is held on the pid by the subject, we return true.
1088
    *
1089
   * @param session - the Session object containing the Subject
1090
   * @param pid - The identifier to check
1091
   *
1092
   * @return true if the reservation exists for the subject/pid
1093
   *
1094
   * @throws InvalidToken
1095
   * @throws ServiceFailure
1096
   * @throws NotFound - when the pid is not found (in use or in reservation)
1097
   * @throws NotAuthorized - when the subject does not hold a reservation on the pid
1098
   * @throws IdentifierNotUnique - when the pid is in use
1099
   * @throws NotImplemented
1100
   */
1101 6177 cjones
1102 6471 jones
  @Override
1103 6934 leinfelder
  public boolean hasReservation(Session session, Subject subject, Identifier pid)
1104 6410 cjones
      throws InvalidToken, ServiceFailure, NotFound, NotAuthorized, IdentifierNotUnique,
1105
      NotImplemented, InvalidRequest {
1106
1107
      throw new NotImplemented("4191", "hasReservation not implemented on this node");
1108
  }
1109 6339 leinfelder
1110 6410 cjones
  /**
1111 6177 cjones
   * Changes ownership (RightsHolder) of the specified object to the
1112
   * subject specified by userId
1113 6410 cjones
    *
1114
   * @param session - the Session object containing the credentials for the Subject
1115
   * @param pid - Identifier of the object to be modified
1116
   * @param userId - The subject that will be taking ownership of the specified object.
1117
   *
1118
   * @return pid - the identifier of the modified object
1119
   *
1120
   * @throws ServiceFailure
1121
   * @throws InvalidToken
1122
   * @throws NotFound
1123
   * @throws NotAuthorized
1124
   * @throws NotImplemented
1125
   * @throws InvalidRequest
1126
   */
1127 6471 jones
  @Override
1128 6803 leinfelder
  public Identifier setRightsHolder(Session session, Identifier pid, Subject userId,
1129 6593 cjones
      long serialVersion)
1130
      throws InvalidToken, ServiceFailure, NotFound, NotAuthorized,
1131 6869 cjones
      NotImplemented, InvalidRequest, VersionMismatch {
1132 6593 cjones
1133 6702 cjones
      // The lock to be used for this identifier
1134 6859 cjones
      Lock lock = null;
1135 6702 cjones
1136 6593 cjones
      // get the subject
1137
      Subject subject = session.getSubject();
1138
1139
      // are we allowed to do this?
1140 7068 cjones
      if (!isAuthorized(session, pid, Permission.CHANGE_PERMISSION)) {
1141
          throw new NotAuthorized("4440", "not allowed by "
1142
                  + subject.getValue() + " on " + pid.getValue());
1143
1144 6869 cjones
      }
1145
1146
      SystemMetadata systemMetadata = null;
1147 6593 cjones
      try {
1148 6703 cjones
          lock = HazelcastService.getInstance().getLock(pid.getValue());
1149 7467 leinfelder
          lock.lock();
1150 6867 cjones
          logMetacat.debug("Locked identifier " + pid.getValue());
1151
1152 6858 cjones
          try {
1153
              systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
1154
1155
              // does the request have the most current system metadata?
1156
              if ( systemMetadata.getSerialVersion().longValue() != serialVersion ) {
1157
                 String msg = "The requested system metadata version number " +
1158
                     serialVersion + " differs from the current version at " +
1159
                     systemMetadata.getSerialVersion().longValue() +
1160
                     ". Please get the latest copy in order to modify it.";
1161 6869 cjones
                 throw new VersionMismatch("4443", msg);
1162 6858 cjones
              }
1163
1164 6869 cjones
          } catch (RuntimeException e) { // Catch is generic since HZ throws RuntimeException
1165 6858 cjones
              throw new NotFound("4460", "No record found for: " + pid.getValue());
1166
1167 6593 cjones
          }
1168 6858 cjones
1169
          // set the new rights holder
1170
          systemMetadata.setRightsHolder(userId);
1171 6593 cjones
1172 6858 cjones
          // update the metadata
1173
          try {
1174
              systemMetadata.setSerialVersion(systemMetadata.getSerialVersion().add(BigInteger.ONE));
1175
              systemMetadata.setDateSysMetadataModified(Calendar.getInstance().getTime());
1176
              HazelcastService.getInstance().getSystemMetadataMap().put(pid, systemMetadata);
1177 7076 cjones
              notifyReplicaNodes(systemMetadata);
1178 6858 cjones
1179 6869 cjones
          } catch (RuntimeException e) {
1180
              throw new ServiceFailure("4490", e.getMessage());
1181 6593 cjones
1182 6858 cjones
          }
1183 6593 cjones
1184 6869 cjones
      } catch (RuntimeException e) {
1185 6858 cjones
          throw new ServiceFailure("4490", e.getMessage());
1186 6644 cjones
1187
      } finally {
1188 6702 cjones
          lock.unlock();
1189 6717 cjones
          logMetacat.debug("Unlocked identifier " + pid.getValue());
1190 6858 cjones
1191 6644 cjones
      }
1192
1193 6869 cjones
      return pid;
1194 6410 cjones
  }
1195 6177 cjones
1196 6410 cjones
  /**
1197
   * Verify that a replication task is authorized by comparing the target node's
1198
   * Subject (from the X.509 certificate-derived Session) with the list of
1199
   * subjects in the known, pending replication tasks map.
1200
   *
1201
   * @param originatingNodeSession - Session information that contains the
1202
   *                                 identity of the calling user
1203
   * @param targetNodeSubject - Subject identifying the target node
1204
   * @param pid - the identifier of the object to be replicated
1205
   * @param replicatePermission - the execute permission to be granted
1206
   *
1207
   * @throws ServiceFailure
1208
   * @throws NotImplemented
1209
   * @throws InvalidToken
1210
   * @throws NotAuthorized
1211
   * @throws InvalidRequest
1212
   * @throws NotFound
1213
   */
1214 6471 jones
  @Override
1215 6409 cjones
  public boolean isNodeAuthorized(Session originatingNodeSession,
1216 6777 leinfelder
    Subject targetNodeSubject, Identifier pid)
1217 6410 cjones
    throws NotImplemented, NotAuthorized, InvalidToken, ServiceFailure,
1218
    NotFound, InvalidRequest {
1219 6702 cjones
1220 6644 cjones
    boolean isAllowed = false;
1221
    SystemMetadata sysmeta = null;
1222 6463 cjones
    NodeReference targetNode = null;
1223
1224 6644 cjones
    try {
1225
      // get the target node reference from the nodes list
1226
      CNode cn = D1Client.getCN();
1227
      List<Node> nodes = cn.listNodes().getNodeList();
1228 6665 cjones
1229 6657 cjones
      if ( nodes != null ) {
1230
        for (Node node : nodes) {
1231 6665 cjones
1232 7141 leinfelder
        	if (node.getSubjectList() != null) {
1233
1234
	            for (Subject nodeSubject : node.getSubjectList()) {
1235
1236
	                if ( nodeSubject.equals(targetNodeSubject) ) {
1237
	                    targetNode = node.getIdentifier();
1238
	                    logMetacat.debug("targetNode is : " + targetNode.getValue());
1239
	                    break;
1240
	                }
1241
	            }
1242
        	}
1243 6657 cjones
1244 6665 cjones
            if ( targetNode != null) { break; }
1245 6657 cjones
        }
1246
1247
      } else {
1248
          String msg = "Couldn't get the node list from the CN";
1249
          logMetacat.debug(msg);
1250
          throw new ServiceFailure("4872", msg);
1251
1252 6644 cjones
      }
1253 6757 cjones
1254
      // can't find a node listed with the given subject
1255
      if ( targetNode == null ) {
1256
          String msg = "There is no Member Node registered with a node subject " +
1257
              "matching " + targetNodeSubject.getValue();
1258
          logMetacat.info(msg);
1259 7062 leinfelder
          throw new NotAuthorized("4871", msg);
1260 6757 cjones
1261
      }
1262
1263 6657 cjones
      logMetacat.debug("Getting system metadata for identifier " + pid.getValue());
1264
1265 6644 cjones
      sysmeta = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
1266 6463 cjones
1267 6657 cjones
      if ( sysmeta != null ) {
1268
1269
          List<Replica> replicaList = sysmeta.getReplicaList();
1270
1271
          if ( replicaList != null ) {
1272
1273
              // find the replica with the status set to 'requested'
1274
              for (Replica replica : replicaList) {
1275
                  ReplicationStatus status = replica.getReplicationStatus();
1276
                  NodeReference listedNode = replica.getReplicaMemberNode();
1277 6757 cjones
                  if ( listedNode != null && targetNode != null ) {
1278
                      logMetacat.debug("Comparing " + listedNode.getValue()
1279
                              + " to " + targetNode.getValue());
1280
1281
                      if (listedNode.getValue().equals(targetNode.getValue())
1282
                              && status.equals(ReplicationStatus.REQUESTED)) {
1283
                          isAllowed = true;
1284
                          break;
1285 6657 cjones
1286 6757 cjones
                      }
1287 6657 cjones
                  }
1288
              }
1289 6568 cjones
          }
1290 6665 cjones
          logMetacat.debug("The " + targetNode.getValue() + " is allowed " +
1291
              "to replicate: " + isAllowed + " for " + pid.getValue());
1292
1293 6657 cjones
1294
      } else {
1295
          logMetacat.debug("System metadata for identifier " + pid.getValue() +
1296
          " is null.");
1297 6869 cjones
          throw new NotFound("4874", "Couldn't find an object identified by " + pid.getValue());
1298 6657 cjones
1299 6568 cjones
      }
1300 6484 cjones
1301 6662 cjones
    } catch (RuntimeException e) {
1302 6665 cjones
    	  ServiceFailure sf = new ServiceFailure("4872",
1303
                "Runtime Exception: Couldn't determine if node is allowed: " +
1304 7140 leinfelder
                e.getMessage());
1305 6665 cjones
    	  sf.initCause(e);
1306 6659 leinfelder
        throw sf;
1307 6636 cjones
1308 6644 cjones
    }
1309
1310
    return isAllowed;
1311 6410 cjones
1312 6384 cjones
  }
1313
1314 6569 cjones
  /**
1315 6570 cjones
   * Adds a new object to the Node, where the object is a science metadata object.
1316 6569 cjones
   *
1317
   * @param session - the Session object containing the credentials for the Subject
1318
   * @param pid - The object identifier to be created
1319
   * @param object - the object bytes
1320
   * @param sysmeta - the system metadata that describes the object
1321
   *
1322
   * @return pid - the object identifier created
1323
   *
1324
   * @throws InvalidToken
1325
   * @throws ServiceFailure
1326
   * @throws NotAuthorized
1327
   * @throws IdentifierNotUnique
1328
   * @throws UnsupportedType
1329
   * @throws InsufficientResources
1330
   * @throws InvalidSystemMetadata
1331
   * @throws NotImplemented
1332
   * @throws InvalidRequest
1333
   */
1334
  public Identifier create(Session session, Identifier pid, InputStream object,
1335
    SystemMetadata sysmeta)
1336
    throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique,
1337
    UnsupportedType, InsufficientResources, InvalidSystemMetadata,
1338
    NotImplemented, InvalidRequest {
1339 6917 cjones
1340 6702 cjones
      // The lock to be used for this identifier
1341 6859 cjones
      Lock lock = null;
1342 6917 cjones
1343 6570 cjones
      try {
1344 6869 cjones
          lock = HazelcastService.getInstance().getLock(pid.getValue());
1345
          // are we allowed?
1346 6570 cjones
          boolean isAllowed = false;
1347 7142 leinfelder
          isAllowed = isAdminAuthorized(session);
1348 6570 cjones
1349
          // proceed if we're called by a CN
1350
          if ( isAllowed ) {
1351
              // create the coordinating node version of the document
1352 6702 cjones
              lock.lock();
1353 6867 cjones
              logMetacat.debug("Locked identifier " + pid.getValue());
1354 6570 cjones
              sysmeta.setSerialVersion(BigInteger.ONE);
1355
              sysmeta.setDateSysMetadataModified(Calendar.getInstance().getTime());
1356 6917 cjones
              sysmeta.setArchived(false); // this is a create op, not update
1357
1358
              // the CN should have set the origin and authoritative member node fields
1359
              try {
1360
                  sysmeta.getOriginMemberNode().getValue();
1361
                  sysmeta.getAuthoritativeMemberNode().getValue();
1362
1363
              } catch (NullPointerException npe) {
1364
                  throw new InvalidSystemMetadata("4896",
1365
                      "Both the origin and authoritative member node identifiers need to be set.");
1366
1367
              }
1368 6570 cjones
              pid = super.create(session, pid, object, sysmeta);
1369
1370
          } else {
1371
              String msg = "The subject listed as " + session.getSubject().getValue() +
1372
                  " isn't allowed to call create() on a Coordinating Node.";
1373
              logMetacat.info(msg);
1374
              throw new NotAuthorized("1100", msg);
1375
          }
1376
1377 6676 cjones
      } catch (RuntimeException e) {
1378 6570 cjones
          // Convert Hazelcast runtime exceptions to service failures
1379
          String msg = "There was a problem creating the object identified by " +
1380
              pid.getValue() + ". There error message was: " + e.getMessage();
1381 6676 cjones
          throw new ServiceFailure("4893", msg);
1382 6570 cjones
1383
      } finally {
1384 6805 leinfelder
    	  if (lock != null) {
1385
	          lock.unlock();
1386
	          logMetacat.debug("Unlocked identifier " + pid.getValue());
1387
    	  }
1388 6570 cjones
      }
1389
1390 6569 cjones
      return pid;
1391
1392
  }
1393
1394 6571 cjones
  /**
1395
   * Set access for a given object using the object identifier and a Subject
1396
   * under a given Session.
1397
   *
1398
   * @param session - the Session object containing the credentials for the Subject
1399
   * @param pid - the object identifier for the given object to apply the policy
1400
   * @param policy - the access policy to be applied
1401
   *
1402
   * @return true if the application of the policy succeeds
1403
   * @throws InvalidToken
1404
   * @throws ServiceFailure
1405
   * @throws NotFound
1406
   * @throws NotAuthorized
1407
   * @throws NotImplemented
1408
   * @throws InvalidRequest
1409
   */
1410
  public boolean setAccessPolicy(Session session, Identifier pid,
1411 6593 cjones
      AccessPolicy accessPolicy, long serialVersion)
1412 6571 cjones
      throws InvalidToken, ServiceFailure, NotFound, NotAuthorized,
1413 6869 cjones
      NotImplemented, InvalidRequest, VersionMismatch {
1414 6571 cjones
1415 6702 cjones
      // The lock to be used for this identifier
1416 6859 cjones
      Lock lock = null;
1417 6869 cjones
      SystemMetadata systemMetadata = null;
1418 6702 cjones
1419 6571 cjones
      boolean success = false;
1420
1421
      // get the subject
1422
      Subject subject = session.getSubject();
1423
1424 7068 cjones
      // are we allowed to do this?
1425
      if (!isAuthorized(session, pid, Permission.CHANGE_PERMISSION)) {
1426
          throw new NotAuthorized("4420", "not allowed by "
1427
                  + subject.getValue() + " on " + pid.getValue());
1428 6571 cjones
      }
1429
1430
      try {
1431 6703 cjones
          lock = HazelcastService.getInstance().getLock(pid.getValue());
1432 6702 cjones
          lock.lock();
1433 6867 cjones
          logMetacat.debug("Locked identifier " + pid.getValue());
1434
1435 6858 cjones
          try {
1436
              systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
1437 6571 cjones
1438 6869 cjones
              if ( systemMetadata == null ) {
1439
                  throw new NotFound("4400", "Couldn't find an object identified by " + pid.getValue());
1440
1441
              }
1442 6858 cjones
              // does the request have the most current system metadata?
1443
              if ( systemMetadata.getSerialVersion().longValue() != serialVersion ) {
1444
                 String msg = "The requested system metadata version number " +
1445
                     serialVersion + " differs from the current version at " +
1446
                     systemMetadata.getSerialVersion().longValue() +
1447
                     ". Please get the latest copy in order to modify it.";
1448 6869 cjones
                 throw new VersionMismatch("4402", msg);
1449
1450 6858 cjones
              }
1451
1452 6869 cjones
          } catch (RuntimeException e) {
1453 6858 cjones
              // convert Hazelcast RuntimeException to NotFound
1454
              throw new NotFound("4400", "No record found for: " + pid);
1455
1456 6593 cjones
          }
1457 6858 cjones
1458
          // set the access policy
1459
          systemMetadata.setAccessPolicy(accessPolicy);
1460 6593 cjones
1461 6858 cjones
          // update the system metadata
1462
          try {
1463
              systemMetadata.setSerialVersion(systemMetadata.getSerialVersion().add(BigInteger.ONE));
1464
              systemMetadata.setDateSysMetadataModified(Calendar.getInstance().getTime());
1465
              HazelcastService.getInstance().getSystemMetadataMap().put(systemMetadata.getIdentifier(), systemMetadata);
1466 7076 cjones
              notifyReplicaNodes(systemMetadata);
1467
1468 6869 cjones
          } catch (RuntimeException e) {
1469 6858 cjones
              // convert Hazelcast RuntimeException to ServiceFailure
1470
              throw new ServiceFailure("4430", e.getMessage());
1471
1472
          }
1473 6571 cjones
1474 6869 cjones
      } catch (RuntimeException e) {
1475 6571 cjones
          throw new ServiceFailure("4430", e.getMessage());
1476 6858 cjones
1477 6571 cjones
      } finally {
1478 6702 cjones
          lock.unlock();
1479 6717 cjones
          logMetacat.debug("Unlocked identifier " + pid.getValue());
1480 6571 cjones
1481
      }
1482 6858 cjones
1483 6571 cjones
1484
    // TODO: how do we know if the map was persisted?
1485
    success = true;
1486
1487
    return success;
1488
  }
1489
1490 6578 cjones
  /**
1491
   * Full replacement of replication metadata in the system metadata for the
1492
   * specified object, changes date system metadata modified
1493
   *
1494
   * @param session - the Session object containing the credentials for the Subject
1495
   * @param pid - the object identifier for the given object to apply the policy
1496
   * @param replica - the replica to be updated
1497
   * @return
1498
   * @throws NotImplemented
1499
   * @throws NotAuthorized
1500
   * @throws ServiceFailure
1501
   * @throws InvalidRequest
1502
   * @throws NotFound
1503 6869 cjones
   * @throws VersionMismatch
1504 6578 cjones
   */
1505 6869 cjones
  @Override
1506 6578 cjones
  public boolean updateReplicationMetadata(Session session, Identifier pid,
1507 6593 cjones
      Replica replica, long serialVersion)
1508 6578 cjones
      throws NotImplemented, NotAuthorized, ServiceFailure, InvalidRequest,
1509 6869 cjones
      NotFound, VersionMismatch {
1510 6578 cjones
1511 6702 cjones
      // The lock to be used for this identifier
1512 6859 cjones
      Lock lock = null;
1513 6702 cjones
1514 6578 cjones
      // get the subject
1515
      Subject subject = session.getSubject();
1516
1517
      // are we allowed to do this?
1518
      try {
1519 7068 cjones
1520
          // what is the controlling permission?
1521
          if (!isAuthorized(session, pid, Permission.WRITE)) {
1522
              throw new NotAuthorized("4851", "not allowed by "
1523
                      + subject.getValue() + " on " + pid.getValue());
1524
          }
1525
1526 6578 cjones
1527
      } catch (InvalidToken e) {
1528
          throw new NotAuthorized("4851", "not allowed by " + subject.getValue() +
1529
                  " on " + pid.getValue());
1530
1531
      }
1532
1533
      SystemMetadata systemMetadata = null;
1534 6858 cjones
      try {
1535 6703 cjones
          lock = HazelcastService.getInstance().getLock(pid.getValue());
1536 6702 cjones
          lock.lock();
1537 6867 cjones
          logMetacat.debug("Locked identifier " + pid.getValue());
1538 6578 cjones
1539 6858 cjones
          try {
1540
              systemMetadata = HazelcastService.getInstance().getSystemMetadataMap().get(pid);
1541
1542
              // does the request have the most current system metadata?
1543
              if ( systemMetadata.getSerialVersion().longValue() != serialVersion ) {
1544
                 String msg = "The requested system metadata version number " +
1545
                     serialVersion + " differs from the current version at " +
1546
                     systemMetadata.getSerialVersion().longValue() +
1547
                     ". Please get the latest copy in order to modify it.";
1548 6869 cjones
                 throw new VersionMismatch("4855", msg);
1549 6858 cjones
              }
1550
1551 6869 cjones
          } catch (RuntimeException e) { // Catch is generic since HZ throws RuntimeException
1552
              throw new NotFound("4854", "No record found for: " + pid.getValue() +
1553
                  " : " + e.getMessage());
1554 6858 cjones
1555 6593 cjones
          }
1556 6858 cjones
1557
          // set the status for the replica
1558
          List<Replica> replicas = systemMetadata.getReplicaList();
1559
          NodeReference replicaNode = replica.getReplicaMemberNode();
1560 7231 cjones
          ReplicationStatus replicaStatus = replica.getReplicationStatus();
1561 6858 cjones
          int index = 0;
1562
          for (Replica listedReplica: replicas) {
1563
1564
              // remove the replica that we are replacing
1565
              if ( replicaNode.getValue().equals(listedReplica.getReplicaMemberNode().getValue())) {
1566 7231 cjones
                      // don't allow status to change from COMPLETED to anything other
1567
                      // than INVALIDATED: prevents overwrites from race conditions
1568
                	  if ( listedReplica.getReplicationStatus() == ReplicationStatus.COMPLETED &&
1569
            		    replicaStatus != ReplicationStatus.INVALIDATED ) {
1570
                	  throw new InvalidRequest("4853", "Status state change from " +
1571
                			  listedReplica.getReplicationStatus() + " to " +
1572
                			  replicaStatus.toString() + "is prohibited for identifier " +
1573
                			  pid.getValue() + " and target node " +
1574
                			  listedReplica.getReplicaMemberNode().getValue());
1575
1576
            	  }
1577 6858 cjones
                  replicas.remove(index);
1578
                  break;
1579
1580
              }
1581
              index++;
1582
          }
1583 6593 cjones
1584 6858 cjones
          // add the new replica item
1585
          replicas.add(replica);
1586
          systemMetadata.setReplicaList(replicas);
1587 6578 cjones
1588 6858 cjones
          // update the metadata
1589
          try {
1590
              systemMetadata.setSerialVersion(systemMetadata.getSerialVersion().add(BigInteger.ONE));
1591
              systemMetadata.setDateSysMetadataModified(Calendar.getInstance().getTime());
1592
              HazelcastService.getInstance().getSystemMetadataMap().put(systemMetadata.getIdentifier(), systemMetadata);
1593 7514 cjones
1594
              // inform replica nodes of the change if the status is complete
1595
              if ( replicaStatus == ReplicationStatus.COMPLETED ) {
1596
            	  broadcastSystemMetadataChange(systemMetadata);
1597
1598
              }
1599 6869 cjones
          } catch (RuntimeException e) {
1600
              logMetacat.info("Unknown RuntimeException thrown: " + e.getCause().getMessage());
1601 6858 cjones
              throw new ServiceFailure("4852", e.getMessage());
1602 6578 cjones
1603
          }
1604 6858 cjones
1605 6869 cjones
      } catch (RuntimeException e) {
1606
          logMetacat.info("Unknown RuntimeException thrown: " + e.getCause().getMessage());
1607
          throw new ServiceFailure("4852", e.getMessage());
1608
1609
      } finally {
1610
          lock.unlock();
1611
          logMetacat.debug("Unlocked identifier " + pid.getValue());
1612
1613
      }
1614 6578 cjones
1615
      return true;
1616
1617
  }
1618 6622 leinfelder
1619 6869 cjones
  /**
1620
   *
1621
   */
1622
  @Override
1623 6858 cjones
  public ObjectList listObjects(Session session, Date startTime,
1624
      Date endTime, ObjectFormatIdentifier formatid, Boolean replicaStatus,
1625
      Integer start, Integer count)
1626 6644 cjones
      throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented,
1627
      ServiceFailure {
1628
1629
      ObjectList objectList = null;
1630 6622 leinfelder
        try {
1631 7439 leinfelder
        	if (count == null || count > MAXIMUM_DB_RECORD_COUNT) {
1632
            	count = MAXIMUM_DB_RECORD_COUNT;
1633
            }
1634 6622 leinfelder
            objectList = IdentifierManager.getInstance().querySystemMetadata(startTime, endTime, formatid, replicaStatus, start, count);
1635
        } catch (Exception e) {
1636
            throw new ServiceFailure("1580", "Error querying system metadata: " + e.getMessage());
1637
        }
1638
1639
        return objectList;
1640 6644 cjones
  }
1641 6803 leinfelder
1642 7012 cjones
1643
 	/**
1644
 	 * Returns a list of checksum algorithms that are supported by DataONE.
1645
 	 * @return cal  the list of checksum algorithms
1646
 	 *
1647
 	 * @throws ServiceFailure
1648
 	 * @throws NotImplemented
1649
 	 */
1650 6869 cjones
  @Override
1651 7012 cjones
  public ChecksumAlgorithmList listChecksumAlgorithms()
1652 6803 leinfelder
			throws ServiceFailure, NotImplemented {
1653
		ChecksumAlgorithmList cal = new ChecksumAlgorithmList();
1654
		cal.addAlgorithm("MD5");
1655
		cal.addAlgorithm("SHA-1");
1656 7012 cjones
		return cal;
1657
1658 6803 leinfelder
	}
1659 7073 cjones
1660
  /**
1661
   * Notify replica Member Nodes of system metadata changes for a given pid
1662
   *
1663
   * @param currentSystemMetadata - the up to date system metadata
1664
   */
1665
  public void notifyReplicaNodes(SystemMetadata currentSystemMetadata) {
1666
1667
      Session session = null;
1668
      List<Replica> replicaList = currentSystemMetadata.getReplicaList();
1669
      MNode mn = null;
1670
      NodeReference replicaNodeRef = null;
1671
      CNode cn = null;
1672
      NodeType nodeType = null;
1673
      List<Node> nodeList = null;
1674
1675
      try {
1676
          cn = D1Client.getCN();
1677
          nodeList = cn.listNodes().getNodeList();
1678
1679
      } catch (Exception e) { // handle BaseException and other I/O issues
1680
1681
          // swallow errors since the call is not critical
1682
          logMetacat.error("Can't inform MNs of system metadata changes due " +
1683
              "to communication issues with the CN: " + e.getMessage());
1684
1685
      }
1686
1687
      if ( replicaList != null ) {
1688
1689
          // iterate through the replicas and inform  MN replica nodes
1690
          for (Replica replica : replicaList) {
1691
1692
              replicaNodeRef = replica.getReplicaMemberNode();
1693
              try {
1694
                  if (nodeList != null) {
1695
                      // find the node type
1696
                      for (Node node : nodeList) {
1697
                          if (node.getIdentifier().getValue() ==
1698
                              replicaNodeRef.getValue()) {
1699
                              nodeType = node.getType();
1700
                              break;
1701
1702
                          }
1703
                      }
1704
                  }
1705
1706
                  // notify only MNs
1707
                  if (nodeType != null && nodeType == NodeType.MN) {
1708
                      mn = D1Client.getMN(replicaNodeRef);
1709
                      mn.systemMetadataChanged(session,
1710
                          currentSystemMetadata.getIdentifier(),
1711
                          currentSystemMetadata.getSerialVersion().longValue(),
1712
                          currentSystemMetadata.getDateSysMetadataModified());
1713
                  }
1714
1715
              } catch (Exception e) { // handle BaseException and other I/O issues
1716
1717
                  // swallow errors since the call is not critical
1718
                  logMetacat.error("Can't inform "
1719
                          + replicaNodeRef.getValue()
1720
                          + " of system metadata changes due "
1721
                          + "to communication issues with the CN: "
1722
                          + e.getMessage());
1723
1724
              }
1725
          }
1726
      }
1727
  }
1728 7144 leinfelder
1729
	@Override
1730
	public boolean isAuthorized(Identifier pid, Permission permission)
1731
			throws ServiceFailure, InvalidToken, NotFound, NotAuthorized,
1732
			NotImplemented, InvalidRequest {
1733
1734
		return isAuthorized(null, pid, permission);
1735
	}
1736
1737
	@Override
1738
	public boolean setAccessPolicy(Identifier pid, AccessPolicy accessPolicy, long serialVersion)
1739
			throws InvalidToken, NotFound, NotImplemented, NotAuthorized,
1740
			ServiceFailure, InvalidRequest, VersionMismatch {
1741
1742
		return setAccessPolicy(null, pid, accessPolicy, serialVersion);
1743
	}
1744
1745
	@Override
1746
	public Identifier setRightsHolder(Identifier pid, Subject userId, long serialVersion)
1747
			throws InvalidToken, ServiceFailure, NotFound, NotAuthorized,
1748
			NotImplemented, InvalidRequest, VersionMismatch {
1749
1750
		return setRightsHolder(null, pid, userId, serialVersion);
1751
	}
1752
1753
	@Override
1754
	public Identifier create(Identifier pid, InputStream object, SystemMetadata sysmeta)
1755
			throws InvalidToken, ServiceFailure, NotAuthorized,
1756
			IdentifierNotUnique, UnsupportedType, InsufficientResources,
1757
			InvalidSystemMetadata, NotImplemented, InvalidRequest {
1758
1759
		return create(null, pid, object, sysmeta);
1760
	}
1761
1762
	@Override
1763
	public Identifier delete(Identifier pid) throws InvalidToken, ServiceFailure,
1764 7171 leinfelder
			NotAuthorized, NotFound, NotImplemented {
1765 7144 leinfelder
1766
		return delete(null, pid);
1767
	}
1768
1769
	@Override
1770
	public Identifier generateIdentifier(String scheme, String fragment)
1771
			throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented,
1772
			InvalidRequest {
1773
1774
		return generateIdentifier(null, scheme, fragment);
1775
	}
1776
1777
	@Override
1778
	public Log getLogRecords(Date fromDate, Date toDate, Event event, String pidFilter,
1779
			Integer start, Integer count) throws InvalidToken, InvalidRequest,
1780
			ServiceFailure, NotAuthorized, NotImplemented, InsufficientResources {
1781
1782
		return getLogRecords(null, fromDate, toDate, event, pidFilter, start, count);
1783
	}
1784
1785
	@Override
1786
	public boolean hasReservation(Subject subject, Identifier pid)
1787
			throws InvalidToken, ServiceFailure, NotFound, NotAuthorized,
1788
			NotImplemented, InvalidRequest, IdentifierNotUnique {
1789
1790
		return hasReservation(null, subject, pid);
1791
	}
1792
1793
	@Override
1794
	public Identifier registerSystemMetadata(Identifier pid, SystemMetadata sysmeta)
1795
			throws NotImplemented, NotAuthorized, ServiceFailure, InvalidRequest,
1796
			InvalidSystemMetadata, InvalidToken {
1797
1798
		return registerSystemMetadata(null, pid, sysmeta);
1799
	}
1800
1801
	@Override
1802
	public Identifier reserveIdentifier(Identifier pid) throws InvalidToken,
1803
			ServiceFailure, NotAuthorized, IdentifierNotUnique, NotImplemented,
1804
			InvalidRequest {
1805
1806
		return reserveIdentifier(null, pid);
1807
	}
1808
1809
	@Override
1810
	public boolean setObsoletedBy(Identifier pid, Identifier obsoletedByPid, long serialVersion)
1811
			throws NotImplemented, NotFound, NotAuthorized, ServiceFailure,
1812
			InvalidRequest, InvalidToken, VersionMismatch {
1813
1814
		return setObsoletedBy(null, pid, obsoletedByPid, serialVersion);
1815
	}
1816
1817
	@Override
1818
	public DescribeResponse describe(Identifier pid) throws InvalidToken,
1819
			NotAuthorized, NotImplemented, ServiceFailure, NotFound {
1820
1821
		return describe(null, pid);
1822
	}
1823
1824
	@Override
1825
	public InputStream get(Identifier pid) throws InvalidToken, ServiceFailure,
1826
			NotAuthorized, NotFound, NotImplemented {
1827
1828
		return get(null, pid);
1829
	}
1830
1831
	@Override
1832
	public Checksum getChecksum(Identifier pid) throws InvalidToken,
1833
			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
1834
1835
		return getChecksum(null, pid);
1836
	}
1837
1838
	@Override
1839
	public SystemMetadata getSystemMetadata(Identifier pid) throws InvalidToken,
1840
			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
1841
1842
		return getSystemMetadata(null, pid);
1843
	}
1844
1845
	@Override
1846
	public ObjectList listObjects(Date startTime, Date endTime,
1847
			ObjectFormatIdentifier formatid, Boolean replicaStatus, Integer start, Integer count)
1848
			throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented,
1849
			ServiceFailure {
1850
1851
		return listObjects(null, startTime, endTime, formatid, replicaStatus, start, count);
1852
	}
1853
1854
	@Override
1855
	public ObjectLocationList resolve(Identifier pid) throws InvalidToken,
1856
			ServiceFailure, NotAuthorized, NotFound, NotImplemented {
1857
1858
		return resolve(null, pid);
1859
	}
1860
1861
	@Override
1862
	public ObjectList search(String queryType, String query) throws InvalidToken,
1863
			ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented {
1864
1865
		return search(null, queryType, query);
1866
	}
1867
1868
	@Override
1869
	public boolean deleteReplicationMetadata(Identifier pid, NodeReference nodeId,
1870
			long serialVersion) throws InvalidToken, InvalidRequest, ServiceFailure,
1871
			NotAuthorized, NotFound, NotImplemented, VersionMismatch {
1872
1873
		return deleteReplicationMetadata(null, pid, nodeId, serialVersion);
1874
	}
1875
1876
	@Override
1877
	public boolean isNodeAuthorized(Subject targetNodeSubject, Identifier pid)
1878
			throws NotImplemented, NotAuthorized, InvalidToken, ServiceFailure,
1879
			NotFound, InvalidRequest {
1880
1881
		return isNodeAuthorized(null, targetNodeSubject, pid);
1882
	}
1883
1884
	@Override
1885
	public boolean setReplicationPolicy(Identifier pid, ReplicationPolicy policy,
1886
			long serialVersion) throws NotImplemented, NotFound, NotAuthorized,
1887
			ServiceFailure, InvalidRequest, InvalidToken, VersionMismatch {
1888
1889
		return setReplicationPolicy(null, pid, policy, serialVersion);
1890
	}
1891
1892
	@Override
1893
	public boolean setReplicationStatus(Identifier pid, NodeReference targetNode,
1894
			ReplicationStatus status, BaseException failure) throws ServiceFailure,
1895
			NotImplemented, InvalidToken, NotAuthorized, InvalidRequest, NotFound {
1896
1897
		return setReplicationStatus(null, pid, targetNode, status, failure);
1898
	}
1899
1900
	@Override
1901
	public boolean updateReplicationMetadata(Identifier pid, Replica replica,
1902
			long serialVersion) throws NotImplemented, NotAuthorized, ServiceFailure,
1903
			NotFound, InvalidRequest, InvalidToken, VersionMismatch {
1904
1905
		return updateReplicationMetadata(null, pid, replica, serialVersion);
1906
	}
1907 7401 cjones
1908
  @Override
1909
  public QueryEngineDescription getQueryEngineDescription(String arg0)
1910
          throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented,
1911
          NotFound {
1912
      throw new NotImplemented("4410", "getQueryEngineDescription not implemented");
1913
1914
  }
1915
1916
  @Override
1917
  public QueryEngineList listQueryEngines() throws InvalidToken, ServiceFailure,
1918
          NotAuthorized, NotImplemented {
1919
      throw new NotImplemented("4420", "listQueryEngines not implemented");
1920
1921
  }
1922
1923
  @Override
1924
  public InputStream query(String arg0, String arg1) throws InvalidToken,
1925
          ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented, NotFound {
1926
      throw new NotImplemented("4324", "query not implemented");
1927
1928
  }
1929 6177 cjones
}