Project

General

Profile

Revision 6475

Added by Matt Jones about 9 years ago

Reformatted to correct indentation to make class readable.

View differences:

src/edu/ucsb/nceas/metacat/dataone/MNodeService.java
118 118
 * MNReplication.replicate()
119 119
 * 
120 120
 */
121
public class MNodeService extends D1NodeService implements MNAuthorization,
122
  MNCore, MNRead, MNReplication, MNStorage {
121
public class MNodeService extends D1NodeService implements MNAuthorization, MNCore, MNRead, MNReplication, MNStorage {
123 122

  
124
  /* the instance of the MNodeService object */
125
  private static MNodeService instance = null;
126
  
127
  /* the logger instance */
128
  private Logger logMetacat = null;
123
    /* the instance of the MNodeService object */
124
    private static MNodeService instance = null;
129 125

  
130
  /**
131
   * Singleton accessor to get an instance of MNodeService.
132
   * 
133
   * @return instance - the instance of MNodeService
134
   */
135
  public static MNodeService getInstance() {
136
    if (instance == null) {
126
    /* the logger instance */
127
    private Logger logMetacat = null;
137 128

  
138
      instance = new MNodeService();
139
      
129
    /**
130
     * Singleton accessor to get an instance of MNodeService.
131
     * 
132
     * @return instance - the instance of MNodeService
133
     */
134
    public static MNodeService getInstance() {
135
        if (instance == null) {
136
            instance = new MNodeService();
137
        }
138
        return instance;
140 139
    }
141
    
142
    return instance;
143
  }
144
  
145
  /**
146
   * Constructor, private for singleton access
147
   */
148
  private MNodeService() {
149
    super();
150
    logMetacat = Logger.getLogger(MNodeService.class);
151
        
152
  }
153
    
154
  /**
155
   * Deletes an object from the Member Node, where the object is either a 
156
   * data object or a science metadata object.
157
   * 
158
   * @param session - the Session object containing the credentials for the Subject
159
   * @param pid - The object identifier to be deleted
160
   * 
161
   * @return pid - the identifier of the object used for the deletion
162
   * 
163
   * @throws InvalidToken
164
   * @throws ServiceFailure
165
   * @throws NotAuthorized
166
   * @throws NotFound
167
   * @throws NotImplemented
168
   * @throws InvalidRequest
169
   */
170
  @Override
171
  public Identifier delete(Session session, Identifier pid) 
172
    throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
173
    NotImplemented, InvalidRequest {
174 140

  
175
    String localId = null;
176
    boolean allowed = false;
177
    String username = Constants.PUBLIC_SUBJECT;
178
    String[] groupnames = null;
179
    if (session != null ) {
180
    	username = session.getSubject().getValue();
181
    	if (session.getSubjectList() != null) {
182
    		List<Group> groupList = session.getSubjectList().getGroupList();
183
    		if (groupList != null) {
184
    			groupnames = new String[groupList.size()];
185
    			for (int i = 0; i > groupList.size(); i++ ) {
186
    				groupnames[i] = groupList.get(i).getGroupName();
187
    			}
188
    		}
189
    	}
141
    /**
142
     * Constructor, private for singleton access
143
     */
144
    private MNodeService() {
145
        super();
146
        logMetacat = Logger.getLogger(MNodeService.class);
190 147
    }
191
    
192
    // do we have a valid pid?
193
    if ( pid == null || pid.getValue().trim().equals("") ) {
194
      throw new InvalidRequest("1322", "The provided identifier was invalid.");
148

  
149
    /**
150
     * Deletes an object from the Member Node, where the object is either a 
151
     * data object or a science metadata object.
152
     * 
153
     * @param session - the Session object containing the credentials for the Subject
154
     * @param pid - The object identifier to be deleted
155
     * 
156
     * @return pid - the identifier of the object used for the deletion
157
     * 
158
     * @throws InvalidToken
159
     * @throws ServiceFailure
160
     * @throws NotAuthorized
161
     * @throws NotFound
162
     * @throws NotImplemented
163
     * @throws InvalidRequest
164
     */
165
    @Override
166
    public Identifier delete(Session session, Identifier pid) 
167
        throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest {
168

  
169
        String localId = null;
170
        boolean allowed = false;
171
        String username = Constants.PUBLIC_SUBJECT;
172
        String[] groupnames = null;
173
        if (session != null) {
174
            username = session.getSubject().getValue();
175
            if (session.getSubjectList() != null) {
176
                List<Group> groupList = session.getSubjectList().getGroupList();
177
                if (groupList != null) {
178
                    groupnames = new String[groupList.size()];
179
                    for (int i = 0; i > groupList.size(); i++) {
180
                        groupnames[i] = groupList.get(i).getGroupName();
181
                    }
182
                }
183
            }
184
        }
185

  
186
        // do we have a valid pid?
187
        if (pid == null || pid.getValue().trim().equals("")) {
188
            throw new InvalidRequest("1322", "The provided identifier was invalid.");
189
        }
190

  
191
        // check for the existing identifier
192
        try {
193
            localId = IdentifierManager.getInstance().getLocalId(pid.getValue());
194
        } catch (McdbDocNotFoundException e) {
195
            throw new InvalidRequest("1322", "The object with the provided " + "identifier was not found.");
196
        }
197

  
198
        // does the subject have DELETE (a D1 CHANGE_PERMISSION level) priveleges on the pid?
199
        allowed = isAuthorized(session, pid, Permission.CHANGE_PERMISSION);
200

  
201
        if (allowed) {
202
            try {
203
                // delete the document
204
                DocumentImpl.delete(localId, username, groupnames, null);
205
                EventLog.getInstance().log(metacatUrl, username, localId, Event.DELETE.xmlValue());
206

  
207
            } catch (McdbDocNotFoundException e) {
208
                throw new InvalidRequest("1322", "The provided identifier was invalid.");
209

  
210
            } catch (SQLException e) {
211
                throw new ServiceFailure("1350", "There was a problem deleting the object." + "The error message was: " + e.getMessage());
212

  
213
            } catch (InsufficientKarmaException e) {
214
                throw new NotAuthorized("1320", "The provided identity does not have " + "permission to DELETE objects on the Member Node.");
215

  
216
            } catch (Exception e) { // for some reason DocumentImpl throws a general Exception
217
                throw new ServiceFailure("1350", "There was a problem deleting the object." + "The error message was: " + e.getMessage());
218
            }
219

  
220
        } else {
221
            throw new NotAuthorized("1320", "The provided identity does not have " + "permission to DELETE objects on the Member Node.");
222
        }
223

  
224
        return pid;
195 225
    }
196 226

  
197
    // check for the existing identifier
198
    try {
199
      localId = IdentifierManager.getInstance().getLocalId(pid.getValue());
200
    
201
    } catch (McdbDocNotFoundException e) {
202
      throw new InvalidRequest("1322", "The object with the provided " +
203
        "identifier was not found.");
227
    /**
228
     * Updates an existing object by creating a new object identified by 
229
     * newPid on the Member Node which explicitly obsoletes the object 
230
     * identified by pid through appropriate changes to the SystemMetadata 
231
     * of pid and newPid
232
     * 
233
     * @param session - the Session object containing the credentials for the Subject
234
     * @param pid - The identifier of the object to be updated
235
     * @param object - the new object bytes
236
     * @param sysmeta - the new system metadata describing the object
237
     * 
238
     * @return newPid - the identifier of the new object
239
     * 
240
     * @throws InvalidToken
241
     * @throws ServiceFailure
242
     * @throws NotAuthorized
243
     * @throws NotFound
244
     * @throws NotImplemented
245
     * @throws IdentifierNotUnique
246
     * @throws UnsupportedType
247
     * @throws InsufficientResources
248
     * @throws InvalidSystemMetadata
249
     * @throws InvalidRequest
250
     */
251
    @Override
252
    public Identifier update(Session session, Identifier pid, InputStream object, Identifier newPid, SystemMetadata sysmeta) throws InvalidToken,
253
            ServiceFailure, NotAuthorized, IdentifierNotUnique, UnsupportedType, InsufficientResources, NotFound, InvalidSystemMetadata, NotImplemented,
254
            InvalidRequest {
204 255

  
256
        // check if the pid has been reserved
257
        try {
258
            boolean hasReservation = D1Client.getCN().hasReservation(session, pid);
259
            if (!hasReservation) {
260
                throw new NotAuthorized("", "No reservation for pid: " + pid.getValue());
261
            }
262
        } catch (NotFound e) {
263
            // okay to continue
264
        }
265

  
266
        String localId = null;
267
        boolean allowed = false;
268
        boolean isScienceMetadata = false;
269
        Subject subject = session.getSubject();
270

  
271
        // do we have a valid pid?
272
        if (pid == null || pid.getValue().trim().equals("")) {
273
            throw new InvalidRequest("1202", "The provided identifier was invalid.");
274
        }
275

  
276
        // check for the existing identifier
277
        try {
278
            localId = IdentifierManager.getInstance().getLocalId(pid.getValue());
279
        } catch (McdbDocNotFoundException e) {
280
            throw new InvalidRequest("1202", "The object with the provided " + "identifier was not found.");
281
        }
282

  
283
        // does the subject have WRITE ( == update) priveleges on the pid?
284
        allowed = isAuthorized(session, pid, Permission.WRITE);
285

  
286
        if (allowed) {
287

  
288
            // get the existing system metadata for the object
289
            SystemMetadata existingSysMeta = getSystemMetadata(session, pid);
290

  
291
            // add the newPid to the obsoletedBy list for the existing sysmeta
292
            existingSysMeta.setObsoletedBy(newPid);
293

  
294
            // then update the existing system metadata
295
            updateSystemMetadata(existingSysMeta);
296

  
297
            // prep the new system metadata, add pid to the affected lists
298
            sysmeta.setObsoletes(pid);
299
            //sysmeta.addDerivedFrom(pid);
300

  
301
            isScienceMetadata = isScienceMetadata(sysmeta);
302

  
303
            // do we have XML metadata or a data object?
304
            if (isScienceMetadata) {
305

  
306
                // update the science metadata XML document
307
                // TODO: handle non-XML metadata/data documents (like netCDF)
308
                // TODO: don't put objects into memory using stream to string
309
                String objectAsXML = "";
310
                try {
311
                    objectAsXML = IOUtils.toString(object, "UTF-8");
312
                    localId = insertOrUpdateDocument(objectAsXML, newPid, session, "update");
313
                    // register the newPid and the generated localId
314
                    if (newPid != null) {
315
                        IdentifierManager.getInstance().createMapping(newPid.getValue(), localId);
316

  
317
                    }
318

  
319
                } catch (IOException e) {
320
                    String msg = "The Node is unable to create the object. " + "There was a problem converting the object to XML";
321
                    logMetacat.info(msg);
322
                    throw new ServiceFailure("1310", msg + ": " + e.getMessage());
323

  
324
                }
325

  
326
            } else {
327

  
328
                // update the data object
329
                localId = insertDataObject(object, newPid, session);
330

  
331
            }
332

  
333
            // and insert the new system metadata
334
            insertSystemMetadata(sysmeta);
335

  
336
            // log the update event
337
            EventLog.getInstance().log(metacatUrl, subject.getValue(), localId, "update");
338

  
339
        } else {
340
            throw new NotAuthorized("1200", "The provided identity does not have " + "permission to UPDATE the object identified by " + pid.getValue()
341
                    + " on the Member Node.");
342
        }
343

  
344
        return newPid;
205 345
    }
206
    
207
    // does the subject have DELETE (a D1 CHANGE_PERMISSION level) priveleges on the pid?
208
    allowed = isAuthorized(session, pid, Permission.CHANGE_PERMISSION);
209
    
210
    if ( allowed ) {
211
      try {
212
        // delete the document
213
        DocumentImpl.delete(localId, username, groupnames, null);
214
        EventLog.getInstance().log(metacatUrl, username, localId, Event.DELETE.xmlValue());
215 346

  
216
      } catch (McdbDocNotFoundException e) {
217
        throw new InvalidRequest("1322", "The provided identifier was invalid.");
347
    public Identifier create(Session session, Identifier pid, InputStream object, SystemMetadata sysmeta) throws InvalidToken, ServiceFailure, NotAuthorized,
348
            IdentifierNotUnique, UnsupportedType, InsufficientResources, InvalidSystemMetadata, NotImplemented, InvalidRequest {
218 349

  
219
      } catch (SQLException e) {
220
        throw new ServiceFailure("1350", "There was a problem deleting the object." +
221
          "The error message was: " + e.getMessage());
350
        // check if the pid has been reserved
351
        try {
352
            boolean hasReservation = D1Client.getCN().hasReservation(session, pid);
353
            if (!hasReservation) {
354
                throw new NotAuthorized("", "No reservation for pid: " + pid.getValue());
355
            }
356
        } catch (NotFound e) {
357
            // okay to continue
358
        }
222 359

  
223
      } catch (InsufficientKarmaException e) {
224
        throw new NotAuthorized("1320", "The provided identity does not have " +
225
        "permission to DELETE objects on the Member Node.");
226
 
227
      } catch (Exception e) { // for some reason DocumentImpl throws a general Exception
228
        throw new ServiceFailure("1350", "There was a problem deleting the object." +
229
            "The error message was: " + e.getMessage());
360
        return super.create(session, pid, object, sysmeta);
361
    }
230 362

  
231
      }
363
    /**
364
     * Called by a Coordinating Node to request that the Member Node create a 
365
     * copy of the specified object by retrieving it from another Member 
366
     * Node and storing it locally so that it can be made accessible to 
367
     * the DataONE system.
368
     * 
369
     * @param session - the Session object containing the credentials for the Subject
370
     * @param sysmeta - Copy of the CN held system metadata for the object
371
     * @param sourceNode - A reference to node from which the content should be 
372
     *                     retrieved. The reference should be resolved by 
373
     *                     checking the CN node registry.
374
     * 
375
     * @return true if the replication succeeds
376
     * 
377
     * @throws ServiceFailure
378
     * @throws NotAuthorized
379
     * @throws NotImplemented
380
     * @throws UnsupportedType
381
     * @throws InsufficientResources
382
     * @throws InvalidRequest
383
     */
384
    @Override
385
    public boolean replicate(Session session, SystemMetadata sysmeta, NodeReference sourceNode) throws NotImplemented, ServiceFailure, NotAuthorized,
386
            InvalidRequest, InsufficientResources, UnsupportedType {
232 387

  
233
    } else {
234
      throw new NotAuthorized("1320", "The provided identity does not have " +
235
      "permission to DELETE objects on the Member Node.");
236
      
388
        boolean result = false;
389

  
390
        // TODO: check credentials
391

  
392
        // get the referenced object
393
        Identifier pid = sysmeta.getIdentifier();
394

  
395
        // get from the membernode
396
        // TODO: switch credentials for the server retrieval?
397
        MNode mn = D1Client.getMN(sourceNode);
398
        InputStream object = null;
399

  
400
        try {
401
            object = mn.get(session, pid);
402
        } catch (InvalidToken e) {
403
            e.printStackTrace();
404
            throw new ServiceFailure("2151", "Could not retrieve object to replicate (InvalidToken): " + e.getMessage());
405
        } catch (NotFound e) {
406
            e.printStackTrace();
407
            throw new ServiceFailure("2151", "Could not retrieve object to replicate (NotFound): " + e.getMessage());
408
        }
409

  
410
        // add it to local store
411
        Identifier retPid;
412
        try {
413
            retPid = create(session, pid, object, sysmeta);
414
            result = (retPid.getValue().equals(pid.getValue()));
415
        } catch (InvalidToken e) {
416
            e.printStackTrace();
417
            throw new ServiceFailure("2151", "Could not save object to local store (InvalidToken): " + e.getMessage());
418
        } catch (IdentifierNotUnique e) {
419
            e.printStackTrace();
420
            throw new ServiceFailure("2151", "Could not save object to local store (IdentifierNotUnique): " + e.getMessage());
421
        } catch (InvalidSystemMetadata e) {
422
            e.printStackTrace();
423
            throw new ServiceFailure("2151", "Could not save object to local store (InvalidSystemMetadata): " + e.getMessage());
424
        }
425

  
426
        return result;
427

  
237 428
    }
238
    
239
    return pid;
240
  }
241 429

  
430
    /**
431
     * This method provides a lighter weight mechanism than 
432
     * MN_read.getSystemMetadata() for a client to determine basic 
433
     * properties of the referenced object.
434
     * 
435
     * @param session - the Session object containing the credentials for the Subject
436
     * @param pid - the identifier of the object to be described
437
     * 
438
     * @return describeResponse - A set of values providing a basic description 
439
     *                            of the object.
440
     * 
441
     * @throws InvalidToken
442
     * @throws ServiceFailure
443
     * @throws NotAuthorized
444
     * @throws NotFound
445
     * @throws NotImplemented
446
     * @throws InvalidRequest
447
     */
448
    @Override
449
    public DescribeResponse describe(Session session, Identifier pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented,
450
            InvalidRequest {
242 451

  
243
  /**
244
   * Updates an existing object by creating a new object identified by 
245
   * newPid on the Member Node which explicitly obsoletes the object 
246
   * identified by pid through appropriate changes to the SystemMetadata 
247
   * of pid and newPid
248
   * 
249
   * @param session - the Session object containing the credentials for the Subject
250
   * @param pid - The identifier of the object to be updated
251
   * @param object - the new object bytes
252
   * @param sysmeta - the new system metadata describing the object
253
   * 
254
   * @return newPid - the identifier of the new object
255
   * 
256
   * @throws InvalidToken
257
   * @throws ServiceFailure
258
   * @throws NotAuthorized
259
   * @throws NotFound
260
   * @throws NotImplemented
261
   * @throws IdentifierNotUnique
262
   * @throws UnsupportedType
263
   * @throws InsufficientResources
264
   * @throws InvalidSystemMetadata
265
   * @throws InvalidRequest
266
   */
267
  @Override
268
  public Identifier update(Session session, Identifier pid, InputStream object,
269
    Identifier newPid, SystemMetadata sysmeta) 
270
    throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, 
271
    UnsupportedType, InsufficientResources, NotFound, InvalidSystemMetadata, 
272
    NotImplemented, InvalidRequest {
273
	  
274
	// check if the pid has been reserved
275
	try {
276
		boolean hasReservation = D1Client.getCN().hasReservation(session, pid);
277
		if (!hasReservation) {
278
			throw new NotAuthorized("", "No reservation for pid: " + pid.getValue());
279
		}
280
	} catch (NotFound e) {
281
		// okay to continue
282
	}
452
        if (session == null) {
453
            throw new InvalidToken("1370", "The session object is null");
454
        }
283 455

  
284
    String localId = null;
285
    boolean allowed = false;
286
    boolean isScienceMetadata = false;
287
    Subject subject = session.getSubject();
288
    
289
    // do we have a valid pid?
290
    if ( pid == null || pid.getValue().trim().equals("") ) {
291
      throw new InvalidRequest("1202", "The provided identifier was invalid.");
456
        if (pid == null || pid.getValue().trim().equals("")) {
457
            throw new InvalidRequest("1362", "The object identifier is null. " + "A valid identifier is required.");
458
        }
292 459

  
460
        SystemMetadata sysmeta = getSystemMetadata(session, pid);
461
        DescribeResponse describeResponse = new DescribeResponse(sysmeta.getFmtid(), sysmeta.getSize(), sysmeta.getDateSysMetadataModified(),
462
                sysmeta.getChecksum());
463

  
464
        return describeResponse;
465

  
293 466
    }
294 467

  
295
    // check for the existing identifier
296
    try {
297
      localId = IdentifierManager.getInstance().getLocalId(pid.getValue());
468
    /**
469
     * Return the object identified by the given object identifier
470
     * 
471
     * @param session - the Session object containing the credentials for the Subject
472
     * @param pid - the object identifier for the given object
473
     * 
474
     * @return inputStream - the input stream of the given object
475
     * 
476
     * @throws InvalidToken
477
     * @throws ServiceFailure
478
     * @throws NotAuthorized
479
     * @throws InvalidRequest
480
     * @throws NotImplemented
481
     */
482
    @Override
483
    public InputStream get(Session session, Identifier pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest {
298 484

  
299
    } catch (McdbDocNotFoundException e) {
300
      throw new InvalidRequest("1202", "The object with the provided " +
301
        "identifier was not found.");
485
        return super.get(session, pid);
302 486

  
303 487
    }
304 488

  
305
    // does the subject have WRITE ( == update) priveleges on the pid?
306
    allowed = isAuthorized(session, pid, Permission.WRITE);
489
    /**
490
     * Returns a Checksum for the specified object using an accepted hashing algorithm
491
     * 
492
     * @param session - the Session object containing the credentials for the Subject
493
     * @param pid - the object identifier for the given object
494
     * @param algorithm -  the name of an algorithm that will be used to compute 
495
     *                     a checksum of the bytes of the object
496
     * 
497
     * @return checksum - the checksum of the given object
498
     * 
499
     * @throws InvalidToken
500
     * @throws ServiceFailure
501
     * @throws NotAuthorized
502
     * @throws NotFound
503
     * @throws InvalidRequest
504
     * @throws NotImplemented
505
     */
506
    @Override
507
    public Checksum getChecksum(Session session, Identifier pid, String algorithm) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
508
            InvalidRequest, NotImplemented {
307 509

  
308
    if ( allowed ) {
309
      
310
      // get the existing system metadata for the object
311
      SystemMetadata existingSysMeta = getSystemMetadata(session, pid);
312
      
313
      // add the newPid to the obsoletedBy list for the existing sysmeta
314
      existingSysMeta.setObsoletedBy(newPid);
315
      
316
      // then update the existing system metadata
317
      updateSystemMetadata(existingSysMeta);
318
            
319
      // prep the new system metadata, add pid to the affected lists
320
      sysmeta.setObsoletes(pid);
321
      //sysmeta.addDerivedFrom(pid);
322
      
323
      isScienceMetadata = isScienceMetadata(sysmeta);
324
      
325
      // do we have XML metadata or a data object?
326
      if ( isScienceMetadata ) {
327
        
328
        // update the science metadata XML document
329
        // TODO: handle non-XML metadata/data documents (like netCDF)
330
        // TODO: don't put objects into memory using stream to string
331
        String objectAsXML = "";
510
        Checksum checksum = null;
511

  
512
        InputStream inputStream = get(session, pid);
513

  
332 514
        try {
333
          objectAsXML = IOUtils.toString(object, "UTF-8");
334
          localId = insertOrUpdateDocument(objectAsXML, newPid, session, "update");
335
          // register the newPid and the generated localId
336
          if ( newPid != null ) {
337
        	  IdentifierManager.getInstance().createMapping(newPid.getValue(), localId);
338
            
339
          }
340
          
515
            checksum = ChecksumUtil.checksum(inputStream, algorithm);
516

  
517
        } catch (NoSuchAlgorithmException e) {
518
            throw new ServiceFailure("1410", "The checksum for the object specified by " + pid.getValue() + "could not be returned due to an internal error: "
519
                    + e.getMessage());
341 520
        } catch (IOException e) {
342
          String msg = "The Node is unable to create the object. " +
343
          "There was a problem converting the object to XML";
344
          logMetacat.info(msg);
345
          throw new ServiceFailure("1310", msg + ": " + e.getMessage());
346
        
521
            throw new ServiceFailure("1410", "The checksum for the object specified by " + pid.getValue() + "could not be returned due to an internal error: "
522
                    + e.getMessage());
347 523
        }
348
        
349
      } else {
350
        
351
        // update the data object
352
        localId = insertDataObject(object, newPid, session);
353
       
354
      }
355
      
356
      // and insert the new system metadata
357
      insertSystemMetadata(sysmeta);
358 524

  
359
      // log the update event
360
      EventLog.getInstance().log(metacatUrl, subject.getValue(), localId, "update");
525
        if (checksum == null) {
526
            throw new ServiceFailure("1410", "The checksum for the object specified by " + pid.getValue() + "could not be returned.");
527
        }
361 528

  
362
    } else {
363
      throw new NotAuthorized("1200", "The provided identity does not have " +
364
      "permission to UPDATE the object identified by " +
365
      pid.getValue() + " on the Member Node.");
366
      
529
        return checksum;
367 530
    }
368
    
369
    return newPid;
370
  }
371
  
372
  public Identifier create(Session session, Identifier pid,
373
			InputStream object, SystemMetadata sysmeta) throws InvalidToken,
374
			ServiceFailure, NotAuthorized, IdentifierNotUnique,
375
			UnsupportedType, InsufficientResources, InvalidSystemMetadata,
376
			NotImplemented, InvalidRequest {
377 531

  
378
		// check if the pid has been reserved
379
		try {
380
			boolean hasReservation = D1Client.getCN().hasReservation(session, pid);
381
			if (!hasReservation) {
382
				throw new NotAuthorized("", "No reservation for pid: " + pid.getValue());
383
			}
384
		} catch (NotFound e) {
385
			// okay to continue
386
		}
532
    /**
533
     * Return the system metadata for a given object
534
     * 
535
     * @param session - the Session object containing the credentials for the Subject
536
     * @param pid - the object identifier for the given object
537
     * 
538
     * @return inputStream - the input stream of the given system metadata object
539
     * 
540
     * @throws InvalidToken
541
     * @throws ServiceFailure
542
     * @throws NotAuthorized
543
     * @throws NotFound
544
     * @throws InvalidRequest
545
     * @throws NotImplemented
546
     */
547
    @Override
548
    public SystemMetadata getSystemMetadata(Session session, Identifier pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest,
549
            NotImplemented {
387 550

  
388
		return super.create(session, pid, object, sysmeta);
389
	}
551
        return super.getSystemMetadata(session, pid);
552
    }
390 553

  
391
  /**
392
   * Called by a Coordinating Node to request that the Member Node create a 
393
   * copy of the specified object by retrieving it from another Member 
394
   * Node and storing it locally so that it can be made accessible to 
395
   * the DataONE system.
396
   * 
397
   * @param session - the Session object containing the credentials for the Subject
398
   * @param sysmeta - Copy of the CN held system metadata for the object
399
   * @param sourceNode - A reference to node from which the content should be 
400
   *                     retrieved. The reference should be resolved by 
401
   *                     checking the CN node registry.
402
   * 
403
   * @return true if the replication succeeds
404
   * 
405
   * @throws ServiceFailure
406
   * @throws NotAuthorized
407
   * @throws NotImplemented
408
   * @throws UnsupportedType
409
   * @throws InsufficientResources
410
   * @throws InvalidRequest
411
   */
412
  @Override
413
  public boolean replicate(Session session, SystemMetadata sysmeta, 
414
    NodeReference sourceNode)
415
    throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest,
416
    InsufficientResources, UnsupportedType {
554
    /**
555
     * Retrieve the list of objects present on the MN that match the calling parameters
556
     * 
557
     * @param session - the Session object containing the credentials for the Subject
558
     * @param startTime - Specifies the beginning of the time range from which 
559
     *                    to return object (>=)
560
     * @param endTime - Specifies the beginning of the time range from which 
561
     *                  to return object (>=)
562
     * @param objectFormat - Restrict results to the specified object format
563
     * @param replicaStatus - Indicates if replicated objects should be returned in the list
564
     * @param start - The zero-based index of the first value, relative to the 
565
     *                first record of the resultset that matches the parameters.
566
     * @param count - The maximum number of entries that should be returned in 
567
     *                the response. The Member Node may return less entries 
568
     *                than specified in this value.
569
     * 
570
     * @return objectList - the list of objects matching the criteria
571
     * 
572
     * @throws InvalidToken
573
     * @throws ServiceFailure
574
     * @throws NotAuthorized
575
     * @throws InvalidRequest
576
     * @throws NotImplemented
577
     */
578
    @Override
579
    public ObjectList listObjects(Session session, Date startTime, Date endTime, ObjectFormatIdentifier objectFormatId, Boolean replicaStatus, Integer start,
580
            Integer count) throws NotAuthorized, InvalidRequest, NotImplemented, ServiceFailure, InvalidToken {
417 581

  
418
    boolean result = false;
582
        ObjectList objectList = null;
419 583

  
420
    // TODO: check credentials
421
    
422
    // get the referenced object
423
    Identifier pid = sysmeta.getIdentifier();
424
    
425
    // get from the membernode
426
    // TODO: switch credentials for the server retrieval?
427
    MNode mn = D1Client.getMN(sourceNode);
428
    InputStream object = null;
584
        try {
585
            objectList = IdentifierManager.getInstance().querySystemMetadata(startTime, endTime, objectFormatId, replicaStatus, start, count);
586
        } catch (Exception e) {
587
            throw new ServiceFailure("1580", "Error querying system metadata: " + e.getMessage());
588
        }
429 589

  
430
	try {
431
		object = mn.get(session, pid);
432
	} catch (InvalidToken e) {
433
		e.printStackTrace();
434
		throw new ServiceFailure("2151", "Could not retrieve object to replicate (InvalidToken): " + e.getMessage());
435
	} catch (NotFound e) {
436
		e.printStackTrace();
437
		throw new ServiceFailure("2151", "Could not retrieve object to replicate (NotFound): " + e.getMessage());
438
	}
439
	
440
    // add it to local store
441
	Identifier retPid;
442
	try {
443
		retPid = create(session, pid, object, sysmeta);
444
		result = (retPid.getValue().equals(pid.getValue()));
445
	} catch (InvalidToken e) {
446
		e.printStackTrace();
447
		throw new ServiceFailure("2151", "Could not save object to local store (InvalidToken): " + e.getMessage());
448
	} catch (IdentifierNotUnique e) {
449
		e.printStackTrace();
450
		throw new ServiceFailure("2151", "Could not save object to local store (IdentifierNotUnique): " + e.getMessage());
451
	} catch (InvalidSystemMetadata e) {
452
		e.printStackTrace();
453
		throw new ServiceFailure("2151", "Could not save object to local store (InvalidSystemMetadata): " + e.getMessage());
454
	}
455
	        
456
    return result;
457
	  
458
  }
459

  
460
  /**
461
   * This method provides a lighter weight mechanism than 
462
   * MN_read.getSystemMetadata() for a client to determine basic 
463
   * properties of the referenced object.
464
   * 
465
   * @param session - the Session object containing the credentials for the Subject
466
   * @param pid - the identifier of the object to be described
467
   * 
468
   * @return describeResponse - A set of values providing a basic description 
469
   *                            of the object.
470
   * 
471
   * @throws InvalidToken
472
   * @throws ServiceFailure
473
   * @throws NotAuthorized
474
   * @throws NotFound
475
   * @throws NotImplemented
476
   * @throws InvalidRequest
477
   */
478
  @Override
479
  public DescribeResponse describe(Session session, Identifier pid)
480
    throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
481
    NotImplemented, InvalidRequest {
482
    
483
    if(session == null) {
484
      throw new InvalidToken("1370", "The session object is null");
485
      
590
        return objectList;
486 591
    }
487
    
488
    if(pid == null || pid.getValue().trim().equals(""))
489
    {
490
      throw new InvalidRequest("1362", "The object identifier is null. " +
491
        "A valid identifier is required.");
492
        
493
    }
494
    
495
    SystemMetadata sysmeta = getSystemMetadata(session, pid);
496
    DescribeResponse describeResponse = 
497
      new DescribeResponse(sysmeta.getFmtid(), 
498
      sysmeta.getSize(), sysmeta.getDateSysMetadataModified(), sysmeta.getChecksum());
499
    
500
    return describeResponse;
501 592

  
502
  }
593
    /**
594
     * Retrieve the list of objects present on the MN that match the calling parameters
595
     * 
596
     * @return node - the technical capabilities of the Member Node
597
     * 
598
     * @throws ServiceFailure
599
     * @throws NotAuthorized
600
     * @throws InvalidRequest
601
     * @throws NotImplemented
602
     */
603
    @Override
604
    public Node getCapabilities() throws NotImplemented, NotAuthorized, ServiceFailure, InvalidRequest {
503 605

  
504
  /**
505
   * Return the object identified by the given object identifier
506
   * 
507
   * @param session - the Session object containing the credentials for the Subject
508
   * @param pid - the object identifier for the given object
509
   * 
510
   * @return inputStream - the input stream of the given object
511
   * 
512
   * @throws InvalidToken
513
   * @throws ServiceFailure
514
   * @throws NotAuthorized
515
   * @throws InvalidRequest
516
   * @throws NotImplemented
517
   */
518
  @Override
519
  public InputStream get(Session session, Identifier pid) 
520
    throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
521
    NotImplemented, InvalidRequest {
522
    
523
    return super.get(session, pid);
524
    
525
  }
606
        String nodeName = null;
607
        String nodeId = null;
608
        String nodeUrl = null;
609
        String nodeDesc = null;
610
        String nodeType = null;
611
        String mnCoreServiceVersion = null;
612
        String mnReadServiceVersion = null;
613
        String mnAuthorizationServiceVersion = null;
614
        String mnStorageServiceVersion = null;
615
        String mnReplicationServiceVersion = null;
526 616

  
527
  /**
528
   * Returns a Checksum for the specified object using an accepted hashing algorithm
529
   * 
530
   * @param session - the Session object containing the credentials for the Subject
531
   * @param pid - the object identifier for the given object
532
   * @param algorithm -  the name of an algorithm that will be used to compute 
533
   *                     a checksum of the bytes of the object
534
   * 
535
   * @return checksum - the checksum of the given object
536
   * 
537
   * @throws InvalidToken
538
   * @throws ServiceFailure
539
   * @throws NotAuthorized
540
   * @throws NotFound
541
   * @throws InvalidRequest
542
   * @throws NotImplemented
543
   */
544
  @Override
545
  public Checksum getChecksum(Session session, Identifier pid, String algorithm)
546
    throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
547
    InvalidRequest, NotImplemented {
617
        boolean nodeSynchronize = false;
618
        boolean nodeReplicate = false;
619
        boolean mnCoreServiceAvailable = false;
620
        boolean mnReadServiceAvailable = false;
621
        boolean mnAuthorizationServiceAvailable = false;
622
        boolean mnStorageServiceAvailable = false;
623
        boolean mnReplicationServiceAvailable = false;
548 624

  
549
    Checksum checksum = null;
550
    
551
    InputStream inputStream = get(session, pid);
552
    
553
    try {
554
      checksum = 
555
    	  ChecksumUtil.checksum(inputStream, algorithm);
556
    
557
    } catch (NoSuchAlgorithmException e) {
558
      throw new ServiceFailure("1410", "The checksum for the object specified by " + 
559
        pid.getValue() +
560
        "could not be returned due to an internal error: " +
561
        e.getMessage());
562
      
563
    } catch (IOException e) {
564
      throw new ServiceFailure("1410", "The checksum for the object specified by " + 
565
        pid.getValue() +
566
        "could not be returned due to an internal error: " +
567
        e.getMessage());
568
      
625
        try {
626
            // get the properties of the node based on configuration information
627
            nodeId = PropertyService.getProperty("dataone.memberNodeId");
628
            nodeName = PropertyService.getProperty("dataone.nodeName");
629
            nodeUrl = SystemUtil.getContextURL() + "/d1/";
630
            nodeDesc = PropertyService.getProperty("dataone.nodeDescription");
631
            nodeType = PropertyService.getProperty("dataone.nodeType");
632
            nodeSynchronize = new Boolean(PropertyService.getProperty("dataone.nodeSynchronize")).booleanValue();
633
            nodeReplicate = new Boolean(PropertyService.getProperty("dataone.nodeReplicate")).booleanValue();
634

  
635
            mnCoreServiceVersion = PropertyService.getProperty("dataone.mnCore.serviceVersion");
636
            mnReadServiceVersion = PropertyService.getProperty("dataone.mnRead.serviceVersion");
637
            mnAuthorizationServiceVersion = PropertyService.getProperty("dataone.mnAuthorization.serviceVersion");
638
            mnStorageServiceVersion = PropertyService.getProperty("dataone.mnStorage.serviceVersion");
639
            mnReplicationServiceVersion = PropertyService.getProperty("dataone.mnReplication.serviceVersion");
640

  
641
            mnCoreServiceAvailable = new Boolean(PropertyService.getProperty("dataone.mnCore.serviceAvailable")).booleanValue();
642
            mnReadServiceAvailable = new Boolean(PropertyService.getProperty("dataone.mnRead.serviceAvailable")).booleanValue();
643
            mnAuthorizationServiceAvailable = new Boolean(PropertyService.getProperty("dataone.mnAuthorization.serviceAvailable")).booleanValue();
644
            mnStorageServiceAvailable = new Boolean(PropertyService.getProperty("dataone.mnStorage.serviceAvailable")).booleanValue();
645
            mnReplicationServiceAvailable = new Boolean(PropertyService.getProperty("dataone.mnReplication.serviceAvailable")).booleanValue();
646

  
647
        } catch (PropertyNotFoundException pnfe) {
648
            logMetacat.error("MNodeService.getCapabilities(): " + "property not found: " + pnfe.getMessage());
649

  
650
        }
651

  
652
        // Set the properties of the node based on configuration information and
653
        // calls to current status methods
654
        Node node = new Node();
655
        node.setBaseURL(metacatUrl + "/" + nodeType);
656
        node.setDescription(nodeDesc);
657

  
658
        // set the node's health information
659
        NodeState state = NodeState.UP;
660
        node.setState(state);
661
        // set the ping response to the current value
662
        Ping canPing = new Ping();
663
        canPing.setSuccess(false);
664
        try {
665
            canPing.setSuccess(ping());
666
        } catch (InsufficientResources e) {
667
            e.printStackTrace();
668

  
669
        } catch (UnsupportedType e) {
670
            e.printStackTrace();
671

  
672
        }
673
        node.setPing(canPing);
674

  
675
        NodeReference identifier = new NodeReference();
676
        identifier.setValue(nodeId);
677
        node.setIdentifier(identifier);
678
        node.setName(nodeName + " -- WAR version WARVERSION");
679
        node.setReplicate(new Boolean(nodeReplicate).booleanValue());
680
        node.setSynchronize(new Boolean(nodeSynchronize).booleanValue());
681

  
682
        // services: MNAuthorization, MNCore, MNRead, MNReplication, MNStorage
683
        Services services = new Services();
684

  
685
        Service sMNCore = new Service();
686
        sMNCore.setName("MNCore");
687
        sMNCore.setVersion(mnCoreServiceVersion);
688
        sMNCore.setAvailable(mnCoreServiceAvailable);
689

  
690
        Service sMNRead = new Service();
691
        sMNRead.setName("MNRead");
692
        sMNRead.setVersion(mnReadServiceVersion);
693
        sMNRead.setAvailable(mnReadServiceAvailable);
694

  
695
        Service sMNAuthorization = new Service();
696
        sMNAuthorization.setName("MNAuthorization");
697
        sMNAuthorization.setVersion(mnAuthorizationServiceVersion);
698
        sMNAuthorization.setAvailable(mnAuthorizationServiceAvailable);
699

  
700
        Service sMNStorage = new Service();
701
        sMNStorage.setName("MNStorage");
702
        sMNStorage.setVersion(mnStorageServiceVersion);
703
        sMNStorage.setAvailable(mnStorageServiceAvailable);
704

  
705
        Service sMNReplication = new Service();
706
        sMNReplication.setName("MNReplication");
707
        sMNReplication.setVersion(mnReplicationServiceVersion);
708
        sMNReplication.setAvailable(mnReplicationServiceAvailable);
709

  
710
        services.addService(sMNRead);
711
        services.addService(sMNCore);
712
        services.addService(sMNAuthorization);
713
        services.addService(sMNStorage);
714
        services.addService(sMNReplication);
715
        node.setServices(services);
716

  
717
        // TODO: Determine the synchronization info without mock values
718
        Synchronization synchronization = new Synchronization();
719
        Schedule schedule = new Schedule();
720
        Date now = new Date();
721
        schedule.setYear(new SimpleDateFormat("yyyy").format(now));
722
        schedule.setMon(new SimpleDateFormat("MM").format(now));
723
        schedule.setMday(new SimpleDateFormat("dd").format(now));
724
        schedule.setWday(new SimpleDateFormat("dd").format(now));
725
        schedule.setHour(new SimpleDateFormat("HH").format(now));
726
        schedule.setMin(new SimpleDateFormat("mm").format(now));
727
        schedule.setSec(new SimpleDateFormat("ss").format(now));
728
        synchronization.setSchedule(schedule);
729
        synchronization.setLastHarvested(now);
730
        synchronization.setLastCompleteHarvest(now);
731
        node.setSynchronization(synchronization);
732
        node.setSynchronize(false);
733
        node.setType(NodeType.MN);
734

  
735
        return node;
569 736
    }
570
    
571
    if ( checksum == null ) {
572
      throw new ServiceFailure("1410", "The checksum for the object specified by " + 
573
        pid.getValue() +
574
        "could not be returned.");
575
      
576
    }
577
    
578
    return checksum;
579
  }
580 737

  
581
  /**
582
   * Return the system metadata for a given object
583
   * 
584
   * @param session - the Session object containing the credentials for the Subject
585
   * @param pid - the object identifier for the given object
586
   * 
587
   * @return inputStream - the input stream of the given system metadata object
588
   * 
589
   * @throws InvalidToken
590
   * @throws ServiceFailure
591
   * @throws NotAuthorized
592
   * @throws NotFound
593
   * @throws InvalidRequest
594
   * @throws NotImplemented
595
   */
596
  @Override
597
  public SystemMetadata getSystemMetadata(Session session, Identifier pid)
598
      throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
599
      InvalidRequest, NotImplemented {
738
    /**
739
     * Returns the number of operations that have been serviced by the node 
740
     * over time periods of one and 24 hours.
741
     * 
742
     * @param session - the Session object containing the credentials for the Subject
743
     * @param period - An ISO8601 compatible DateTime range specifying the time 
744
     *                 range for which to return operation statistics.
745
     * @param requestor - Limit to operations performed by given requestor identity.
746
     * @param event -  Enumerated value indicating the type of event being examined
747
     * @param format - Limit to events involving objects of the specified format
748
     * 
749
     * @return the desired log records
750
     * 
751
     * @throws InvalidToken
752
     * @throws ServiceFailure
753
     * @throws NotAuthorized
754
     * @throws InvalidRequest
755
     * @throws NotImplemented
756
     */
757
    @Override
758
    public MonitorList getOperationStatistics(Session session, Date startTime, Date endTime, Subject requestor, Event event, ObjectFormatIdentifier formatId)
759
            throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest, InsufficientResources, UnsupportedType {
600 760

  
601
    return super.getSystemMetadata(session, pid);
602
  }
761
        MonitorList monitorList = new MonitorList();
603 762

  
604
  /**
605
   * Retrieve the list of objects present on the MN that match the calling parameters
606
   * 
607
   * @param session - the Session object containing the credentials for the Subject
608
   * @param startTime - Specifies the beginning of the time range from which 
609
   *                    to return object (>=)
610
   * @param endTime - Specifies the beginning of the time range from which 
611
   *                  to return object (>=)
612
   * @param objectFormat - Restrict results to the specified object format
613
   * @param replicaStatus - Indicates if replicated objects should be returned in the list
614
   * @param start - The zero-based index of the first value, relative to the 
615
   *                first record of the resultset that matches the parameters.
616
   * @param count - The maximum number of entries that should be returned in 
617
   *                the response. The Member Node may return less entries 
618
   *                than specified in this value.
619
   * 
620
   * @return objectList - the list of objects matching the criteria
621
   * 
622
   * @throws InvalidToken
623
   * @throws ServiceFailure
624
   * @throws NotAuthorized
625
   * @throws InvalidRequest
626
   * @throws NotImplemented
627
   */
628
  @Override
629
  public ObjectList listObjects(Session session, Date startTime, Date endTime,
630
    ObjectFormatIdentifier objectFormatId, Boolean replicaStatus, Integer start, Integer count)
631
    throws NotAuthorized, InvalidRequest, NotImplemented, ServiceFailure,
632
    InvalidToken {
763
        try {
633 764

  
634
    ObjectList objectList = null;
635
    
636
    try {
637
	    objectList = IdentifierManager.getInstance().querySystemMetadata(startTime, endTime,
638
	        objectFormatId, replicaStatus, start, count);
639
    } catch (Exception e) {
640
		throw new ServiceFailure("1580", "Error querying system metadata: " + e.getMessage());
641
	}
642
    
643
    return objectList;
644
  }
765
            // get log records first
766
            Log logs = getLogRecords(session, startTime, endTime, event, 0, null);
645 767

  
646
  /**
647
   * Retrieve the list of objects present on the MN that match the calling parameters
648
   * 
649
   * @return node - the technical capabilities of the Member Node
650
   * 
651
   * @throws ServiceFailure
652
   * @throws NotAuthorized
653
   * @throws InvalidRequest
654
   * @throws NotImplemented
655
   */
656
  @Override
657
  public Node getCapabilities() throws NotImplemented, NotAuthorized,
658
      ServiceFailure, InvalidRequest {
659
    
660
  	String nodeName = null;
661
    String nodeId = null;
662
    String nodeUrl = null;
663
    String nodeDesc = null;
664
    String nodeType = null;
665
    String mnCoreServiceVersion = null;
666
    String mnReadServiceVersion = null;
667
    String mnAuthorizationServiceVersion = null;
668
    String mnStorageServiceVersion = null;
669
    String mnReplicationServiceVersion = null;
768
            // TODO: aggregate by day or hour -- needs clarification
769
            int count = 1;
770
            for (LogEntry logEntry : logs.getLogEntryList()) {
771
                Identifier pid = logEntry.getIdentifier();
772
                Date logDate = logEntry.getDateLogged();
773
                // if we are filtering by format
774
                if (formatId != null) {
775
                    SystemMetadata sysmeta = IdentifierManager.getInstance().getSystemMetadata(pid.getValue());
776
                    if (!sysmeta.getFmtid().getValue().equals(formatId.getValue())) {
777
                        // does not match
778
                        continue;
779
                    }
780
                }
781
                MonitorInfo item = new MonitorInfo();
782
                item.setCount(count);
783
                item.setDate(new java.sql.Date(logDate.getTime()));
784
                monitorList.addMonitorInfo(item);
670 785

  
671
    boolean nodeSynchronize = false;
672
    boolean nodeReplicate = false;
673
    boolean mnCoreServiceAvailable = false;
674
    boolean mnReadServiceAvailable = false;
675
    boolean mnAuthorizationServiceAvailable = false;
676
    boolean mnStorageServiceAvailable = false;
677
    boolean mnReplicationServiceAvailable = false;
786
            }
787
        } catch (Exception e) {
788
            e.printStackTrace();
789
            throw new ServiceFailure("2081", "Could not retrieve statistics: " + e.getMessage());
790
        }
678 791

  
679
    try
680
    {
681
    	// get the properties of the node based on configuration information
682
      nodeId = PropertyService.getProperty("dataone.memberNodeId");
683
      nodeName = PropertyService.getProperty("dataone.nodeName");
684
      nodeUrl = SystemUtil.getContextURL() + "/d1/";
685
      nodeDesc = PropertyService.getProperty("dataone.nodeDescription");
686
      nodeType = PropertyService.getProperty("dataone.nodeType");
687
      nodeSynchronize = 
688
      	new Boolean(PropertyService.getProperty(
689
      		"dataone.nodeSynchronize")).booleanValue();
690
      nodeReplicate = 
691
      	new Boolean(PropertyService.getProperty(
692
      		"dataone.nodeReplicate")).booleanValue();
693
      
694
      mnCoreServiceVersion = 
695
      	PropertyService.getProperty("dataone.mnCore.serviceVersion");
696
      mnReadServiceVersion = 
697
      	PropertyService.getProperty("dataone.mnRead.serviceVersion");
698
      mnAuthorizationServiceVersion = 
699
      	PropertyService.getProperty("dataone.mnAuthorization.serviceVersion");
700
      mnStorageServiceVersion = 
701
      	PropertyService.getProperty("dataone.mnStorage.serviceVersion");
702
      mnReplicationServiceVersion = 
703
      	PropertyService.getProperty("dataone.mnReplication.serviceVersion");
704
      
705
      mnCoreServiceAvailable = new Boolean(
706
      	PropertyService.getProperty("dataone.mnCore.serviceAvailable")).booleanValue();
707
      mnReadServiceAvailable =  new Boolean(
708
      	PropertyService.getProperty(
709
      		"dataone.mnRead.serviceAvailable")).booleanValue();
710
      mnAuthorizationServiceAvailable =  new Boolean(
711
      	PropertyService.getProperty(
712
      		"dataone.mnAuthorization.serviceAvailable")).booleanValue();
713
      mnStorageServiceAvailable =  new Boolean(
714
      	PropertyService.getProperty(
715
      	  "dataone.mnStorage.serviceAvailable")).booleanValue();
716
      mnReplicationServiceAvailable =  new Boolean(
717
      	PropertyService.getProperty(
718
      	  "dataone.mnReplication.serviceAvailable")).booleanValue();
792
        return monitorList;
719 793

  
720
    } catch(PropertyNotFoundException pnfe) {
721
        logMetacat.error("MNodeService.getCapabilities(): " +
722
          "property not found: " + pnfe.getMessage());
723
        
724 794
    }
725 795

  
726
  	// Set the properties of the node based on configuration information and
727
    // calls to current status methods
728
	  Node node = new Node();
729
	  node.setBaseURL(metacatUrl + "/" + nodeType);
730
	  node.setDescription(nodeDesc);
731
	  
732
	  // set the node's health information
733
	  NodeState state = NodeState.UP;
734
	  node.setState(state);
735
	  // set the ping response to the current value
736
	  Ping canPing = new Ping();
737
	  canPing.setSuccess(false);
738
	  try {
739
	    canPing.setSuccess(ping());
740
    } catch (InsufficientResources e) {
741
	    e.printStackTrace();
742
	    
743
    } catch (UnsupportedType e) {
744
	    e.printStackTrace();
745
	    
796
    /**
797
     * Low level “are you alive” operation. A valid ping response is 
798
     * indicated by a HTTP status of 200.
799
     * 
800
     * @return true if the service is alive
801
     * 
802
     * @throws InvalidToken
803
     * @throws ServiceFailure
804
     * @throws NotAuthorized
805
     * @throws InvalidRequest
806
     * @throws NotImplemented
807
     */
808
    @Override
809
    public boolean ping() throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest, InsufficientResources, UnsupportedType {
810

  
811
        // test if we can get a database connection
812
        boolean alive = false;
813
        int serialNumber = -1;
814
        DBConnection dbConn = null;
815
        try {
816
            dbConn = DBConnectionPool.getDBConnection("MNodeService.ping");
817
            serialNumber = dbConn.getCheckOutSerialNumber();
818
            alive = true;
819
        } catch (SQLException e) {
820
            return alive;
821
        } finally {
822
            // Return the database connection
823
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
824
        }
825

  
826
        return alive;
746 827
    }
747
	  node.setPing(canPing);
748
	  
749
	  NodeReference identifier = new NodeReference();
750
	  identifier.setValue(nodeId);
751
	  node.setIdentifier(identifier);
752
	  node.setName(nodeName + " -- WAR version WARVERSION");
753
	  node.setReplicate(new Boolean(nodeReplicate).booleanValue());
754
	  node.setSynchronize(new Boolean(nodeSynchronize).booleanValue());
755
	  
756
	  // services: MNAuthorization, MNCore, MNRead, MNReplication, MNStorage
757
	  Services services = new Services();
758 828

  
759
	  Service sMNCore = new Service();
760
	  sMNCore.setName("MNCore");
761
	  sMNCore.setVersion(mnCoreServiceVersion);
762
	  sMNCore.setAvailable(mnCoreServiceAvailable);
763
	  
764
	  Service sMNRead = new Service();
765
	  sMNRead.setName("MNRead");
766
	  sMNRead.setVersion(mnReadServiceVersion);
767
	  sMNRead.setAvailable(mnReadServiceAvailable);
768
	  
769
	  Service sMNAuthorization = new Service();
770
	  sMNAuthorization.setName("MNAuthorization");
771
	  sMNAuthorization.setVersion(mnAuthorizationServiceVersion);
772
	  sMNAuthorization.setAvailable(mnAuthorizationServiceAvailable);
773
	  
774
	  Service sMNStorage = new Service();
775
	  sMNStorage.setName("MNStorage");
776
	  sMNStorage.setVersion(mnStorageServiceVersion);
777
	  sMNStorage.setAvailable(mnStorageServiceAvailable);
778
	  
779
	  Service sMNReplication = new Service();
780
	  sMNReplication.setName("MNReplication");
781
	  sMNReplication.setVersion(mnReplicationServiceVersion);
782
	  sMNReplication.setAvailable(mnReplicationServiceAvailable);
783
	  
784
	  services.addService(sMNRead);
785
	  services.addService(sMNCore);
786
	  services.addService(sMNAuthorization);
787
	  services.addService(sMNStorage);
788
	  services.addService(sMNReplication);
789
	  node.setServices(services);
790
	  
791
	  // TODO: Determine the synchronization info without mock values
792
	  Synchronization synchronization = new Synchronization();
793
	  Schedule schedule = new Schedule();
794
	  Date now = new Date();
795
	  schedule.setYear(new SimpleDateFormat("yyyy").format(now));
796
	  schedule.setMon(new SimpleDateFormat("MM").format(now));
797
	  schedule.setMday(new SimpleDateFormat("dd").format(now));
798
	  schedule.setWday(new SimpleDateFormat("dd").format(now));
799
	  schedule.setHour(new SimpleDateFormat("HH").format(now));
800
	  schedule.setMin(new SimpleDateFormat("mm").format(now));
801
	  schedule.setSec(new SimpleDateFormat("ss").format(now));
802
	  synchronization.setSchedule(schedule);
803
	  synchronization.setLastHarvested(now);
804
	  synchronization.setLastCompleteHarvest(now);
805
	  node.setSynchronization(synchronization);
806
	  node.setSynchronize(false);
807
	  node.setType(NodeType.MN);
808
	  
809
	  return node;
810
  }
829
    /**
830
     * A callback method used by a CN to indicate to a MN that it cannot 
831
     * complete synchronization of the science metadata identified by pid.  Log
832
     * the event in the metacat event log.
833
     * 
834
     * @param session
835
     * @param syncFailed
836
     * 
837
     * @throws ServiceFailure
838
     * @throws NotAuthorized
839
     * @throws InvalidRequest
840
     * @throws NotImplemented
841
     */
842
    @Override
843
    public void synchronizationFailed(Session session, SynchronizationFailed syncFailed) throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest {
811 844

  
812
  /**
813
   * Returns the number of operations that have been serviced by the node 
814
   * over time periods of one and 24 hours.
815
   * 
816
   * @param session - the Session object containing the credentials for the Subject
817
   * @param period - An ISO8601 compatible DateTime range specifying the time 
818
   *                 range for which to return operation statistics.
819
   * @param requestor - Limit to operations performed by given requestor identity.
820
   * @param event -  Enumerated value indicating the type of event being examined
821
   * @param format - Limit to events involving objects of the specified format
822
   * 
823
   * @return the desired log records
824
   * 
825
   * @throws InvalidToken
826
   * @throws ServiceFailure
827
   * @throws NotAuthorized
828
   * @throws InvalidRequest
829
   * @throws NotImplemented
830
   */
831
  @Override
832
  public MonitorList getOperationStatistics(Session session, Date startTime,
833
  		Date endTime, Subject requestor, Event event, ObjectFormatIdentifier formatId) 
834
    throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest, 
835
    InsufficientResources, UnsupportedType {
836
    
837
	  MonitorList monitorList = new MonitorList();
838
	  
839
	  try {
845
        String localId;
840 846

  
841
		  // get log records first
842
		  Log logs = getLogRecords(session, startTime, endTime, event, 0, null);
843
		  
844
		  // TODO: aggregate by day or hour -- needs clarification
845
		  int count = 1;
846
		  for (LogEntry logEntry: logs.getLogEntryList()) {
847
			  Identifier pid = logEntry.getIdentifier();
848
			  Date logDate = logEntry.getDateLogged();
849
			  // if we are filtering by format
850
			  if (formatId != null) {
851
				  SystemMetadata sysmeta = IdentifierManager.getInstance().getSystemMetadata(pid.getValue());
852
				  if (!sysmeta.getFmtid().getValue().equals(formatId.getValue())) {
853
					  // does not match
854
					  continue;
855
				  }
856
			  }
857
			  MonitorInfo item = new MonitorInfo();
858
			  item.setCount(count);
859
			  item.setDate(new java.sql.Date(logDate.getTime()));
860
			  monitorList.addMonitorInfo(item);
861
			  
862
		  }
863
	} catch (Exception e) {
864
		e.printStackTrace();
865
		throw new ServiceFailure("2081", "Could not retrieve statistics: " + e.getMessage());
866
	}
867
	  
868
	return monitorList;
869
	  
870
  }
847
        try {
848
            localId = IdentifierManager.getInstance().getLocalId(syncFailed.getPid());
849
        } catch (McdbDocNotFoundException e) {
850
            throw new InvalidRequest("2163", "The identifier specified by " + syncFailed.getPid() + " was not found on this node.");
871 851

  
872
  /**
873
   * Low level “are you alive” operation. A valid ping response is 
874
   * indicated by a HTTP status of 200.
875
   * 
876
   * @return true if the service is alive
877
   * 
878
   * @throws InvalidToken
879
   * @throws ServiceFailure
880
   * @throws NotAuthorized
881
   * @throws InvalidRequest
882
   * @throws NotImplemented
883
   */
884
  @Override
885
  public boolean ping() 
886
    throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest, 
887
    InsufficientResources, UnsupportedType {
852
        }
853
        // TODO: update the CN URL below when the CNRead.SynchronizationFailed
854
        // method is changed to include the URL as a parameter
855
        logMetacat.debug("Synchronization for the object identified by " + syncFailed.getPid() + " failed from " + syncFailed.getNodeId()
856
                + " Logging the event to the Metacat EventLog as a 'syncFailed' event.");
857
        // TODO: use the event type enum when the SYNCHRONIZATION_FAILED event is added
858
        EventLog.getInstance().log(syncFailed.getNodeId(), session.getSubject().getValue(), localId, "synchronization_failed");
859
        //EventLog.getInstance().log("CN URL WILL GO HERE", 
860
        //  session.getSubject().getValue(), localId, Event.SYNCHRONIZATION_FAILED);
888 861

  
889
    // test if we can get a database connection
890
    boolean alive = false;
891
    int serialNumber = -1;
892
    DBConnection dbConn = null;
893
    try {
894
      dbConn = DBConnectionPool
895
      .getDBConnection("MNodeService.ping");
896
      serialNumber = dbConn.getCheckOutSerialNumber();
897
      alive = true;
898
      
899
    } catch (SQLException e) {
900
      return alive;
901
      
902
    } finally {
903
      // Return the database connection
904
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
905
    
906 862
    }
907 863

  
908
    return alive;
909
  }
864
    /**
865
     * Essentially a get() but with different logging behavior
866
     */
867
    @Override
868
    public InputStream getReplica(Session session, Identifier pid) throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented, ServiceFailure, NotFound {
910 869

  
911
  /**
912
   * A callback method used by a CN to indicate to a MN that it cannot 
913
   * complete synchronization of the science metadata identified by pid.  Log
914
   * the event in the metacat event log.
915
   * 
916
   * @param session
917
   * @param syncFailed
918
   * 
919
   * @throws ServiceFailure
920
   * @throws NotAuthorized
921
   * @throws InvalidRequest
922
   * @throws NotImplemented
923
   */
924
  @Override
925
  public void synchronizationFailed(Session session, SynchronizationFailed syncFailed)
926
      throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest {
870
        InputStream inputStream = null; // bytes to be returned
871
        handler = new MetacatHandler(new Timer());
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff