Project

General

Profile

« Previous | Next » 

Revision 6088

Changes in the DataONE ObjectFormat class deprecate the convert() method, and we're now using Metacat's ObjectFormatService to look up object format attributes. The following changes replace ObjectFormat.convert() with ObjectFormatService.getFormat() in several classes.

Also added a few methods to ObjectFormatService where doRefresh() calls populateObjectFormatList(), which in turn calls either getCachedList() or falls back to getListFromDisk() in the case of a CN, or will call cn.listFormats() from the D1 libclient if the Metacat installation is an MN.

Added the ObjectFormatService.objectFormatMap as a static hash used for lookups of object formats based on their canonical identifier. This is populated from the ObjectFormatService.objectFormatList.

Added deserializeObjectFormatList(InputStream) to return the ObjectFormatList from the XML serialization (from Metacat or disk).

View differences:

ObjectFormatService.java
1 1
/**
2 2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements session utility methods 
3
 *    Purpose: Implements a service for managing object formats
4 4
 *  Copyright: 2011 Regents of the University of California and the
5 5
 *             National Center for Ecological Analysis and Synthesis
6 6
 *    Authors: Christopher Jones
......
26 26

  
27 27
package edu.ucsb.nceas.metacat.service;
28 28

  
29
import org.apache.commons.io.IOUtils;
30
import org.apache.log4j.Logger;
29
import java.io.ByteArrayInputStream;
30
import java.io.FileInputStream;
31
import java.io.FileNotFoundException;
32
import java.io.InputStream;
33
import java.sql.SQLException;
34
import java.util.HashMap;
35
import java.util.List;
31 36

  
37
import edu.ucsb.nceas.metacat.DBUtil;
38
import edu.ucsb.nceas.metacat.DocumentImpl;
39
import edu.ucsb.nceas.metacat.McdbException;
32 40
import edu.ucsb.nceas.metacat.properties.PropertyService;
41
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
33 42
import edu.ucsb.nceas.metacat.shared.BaseService;
34 43
import edu.ucsb.nceas.metacat.shared.ServiceException;
44
import edu.ucsb.nceas.metacat.util.SystemUtil;
45
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
35 46

  
47
import org.apache.log4j.Logger;
48

  
49
import org.dataone.client.CNode;
50
import org.dataone.client.D1Client;
51
import org.dataone.service.exceptions.InsufficientResources;
52
import org.dataone.service.exceptions.InvalidRequest;
53
import org.dataone.service.exceptions.NotFound;
54
import org.dataone.service.exceptions.NotImplemented;
55
import org.dataone.service.exceptions.ServiceFailure;
56
import org.dataone.service.types.Identifier;
57
import org.dataone.service.types.ObjectFormat;
58
import org.dataone.service.types.ObjectFormatList;
59
import org.dataone.service.types.util.ServiceTypeUtil;
60
import org.jibx.runtime.JiBXException;
61

  
36 62
/**
37 63
 *  The ObjectFormatService manages the list of object formats registered
38 64
 *  within Metacat.  This includes schema types, mime types, and other
......
42 68
 */
43 69
public class ObjectFormatService extends BaseService {
44 70
  
45
  
46 71
  /* The instance of the logging class */
47 72
  private static Logger logMetacat = Logger.getLogger(ObjectFormatService.class);
48 73
  
49 74
  /* The singleton instance of the object format service */
50
  private ObjectFormatService objectFormatService = null;
75
  private static ObjectFormatService objectFormatService = null;
51 76
  
52 77
  /* The scope of the object formats docid used as the metacat identifier */
53
  private static final String OBJECT_FORMATS_SCOPE = "OBJECT_FORMAT_LIST.1";
78
  private final String OBJECT_FORMAT_DOCID = "OBJECT_FORMAT_LIST.103";
54 79
  
55 80
  /* The revision of the object formats document */
56 81
  private int rev;
57 82
  
83
  /* The separator of the object formats document */
84
  private String separator = ".";
85

  
86
  /* The accession number of the object formats document */
87
  private String accNumber = null;
88

  
89
  /* The list of object formats */
90
  private static ObjectFormatList objectFormatList = null;
91
  
92
  /* the searchable map of object formats */
93
  private static HashMap<String, ObjectFormat> objectFormatMap = 
94
    new HashMap<String, ObjectFormat>();
95
  
96
  /* A hash map of object format identifiers
97
  /* The D1 coordinating node reference object used for object format lookups */
98
  private String coordinatingNodeBaseURL = null;
99
  
100
  /* The D1 coordinating node reference object used for object format lookups */
101
  private CNode cn = null;
102

  
103
  /* The D1 node type for this instance of metacat */
104
  private String nodeType;
105
  
58 106
  /*
59 107
   * Constructor: Creates an instance of the object format service. Since
60 108
   * this uses a singleton pattern, use getInstance() to gain the instance.
......
62 110
  private ObjectFormatService() {
63 111
    
64 112
    super();
65
    this._serviceName="ObjectFormatService";
113
    _serviceName="ObjectFormatService";
66 114
    
67 115
    try {
68 116
      doRefresh();
......
81 129
   *
82 130
   * @return objectFormatService - The instance of the object format service
83 131
   */
84
  public ObjectFormatService getInstance(){
132
  public static ObjectFormatService getInstance(){
85 133
    
86
    if ( this.objectFormatService == null ) {
134
    if ( objectFormatService == null ) {
87 135
      
88
      this.objectFormatService = new ObjectFormatService();
136
      objectFormatService = new ObjectFormatService();
89 137
      
90 138
    }
91
    return this.objectFormatService;
139
    return objectFormatService;
92 140
  }
93 141
  
94 142
  /**
......
97 145
   */
98 146
  public void doRefresh() throws ServiceException {
99 147
    
100
    // stub only
101
    logMetacat.debug("ObjectFormatService.doRefresh() called. " +
102
                     "Refreshing the object format service.");
148
    logMetacat.debug("ObjectFormatService.doRefresh() called.");
149
    logMetacat.info("Refreshing the object format list.");
103 150
    
151
    // create the in-memory list of object formats
152
    populateObjectFormatList();
153
    
104 154
    return;
105 155
  }
106 156
  
107 157
  /**
158
   * Populate the ObjectFormatService's objectFormatList. If this metacat
159
   * installation is a D1 Coordinating Node, object formats are populated
160
   * from a cached document in the Metacat database. Otherwise, if it is 
161
   * a Member Node, it attempts to get the authoritative list from the
162
   * defined Coordinating Node, failing back to a cached version.
163
   * 
164
   * @throws ServiceException
165
   */
166
  private void populateObjectFormatList() throws ServiceException {
167
    
168
    try {
169
      
170
      coordinatingNodeBaseURL = 
171
        PropertyService.getProperty("dataone.coordinatingNodeBaseURL");
172
      nodeType = 
173
        PropertyService.getProperty("dataone.nodeType");
174
      
175
      
176
    } catch ( PropertyNotFoundException pnfe ) {
177
      
178
      String message = "There was a problem finding the coordinating node " +
179
                       "URL in the properties file.  The message was: "     +
180
                       pnfe.getMessage();
181
      logMetacat.error(message);
182
      throw new ServiceException(message);
183
    }
184
    
185
    // For DataONE Member Nodes, get the authoritative list from the 
186
    // Coordinating Node, otherwise, get the cached list
187
    if ( this.nodeType.equals("mn") ) {
188
      
189
      /*
190
       *try {
191
       *  
192
       *  // try to get the authoritative list remotely
193
       *  D1Client d1Client = new D1Client(coordinatingNodeBaseURL);
194
       *  this.cn = D1Client.getCN();
195
       *  this.objectFormatList = cn.listFormats();
196
       *
197
       *} catch (ServiceFailure e) {
198
       *  
199
       *  logMetacat.debug("There was a getting the object format list from " +
200
       *    "the coordinating node. The message was: " +
201
       *    e.getMessage());
202
       *  this.getCachedList();  
203
       *  
204
       *} catch (NotImplemented e) {
205
       *  
206
       *  logMetacat.debug("There was a getting the object format list from " +
207
       *    "the coordinating node. The message was: " + e.getMessage());
208
       *  this.getCachedList();  
209
       *  
210
       *} catch (InvalidRequest e) {
211
       *  
212
       *  logMetacat.debug("There was a getting the object format list from " +
213
       *    "the coordinating node. The message was: " + e.getMessage());
214
       *  this.getCachedList();  
215
       *  
216
       *} catch (NotFound e) {
217
       *  
218
       *  logMetacat.debug("There was a getting the object format list from " +
219
       *    "the coordinating node. The message was: " + e.getMessage());
220
       *  this.getCachedList();  
221
       *  
222
       *} catch (InsufficientResources e) {
223
       *  
224
       *  logMetacat.debug("There was a getting the object format list from " +
225
       *    "the coordinating node. The message was: " + e.getMessage());
226
       *  this.getCachedList();  
227
       *  
228
       *}
229
       */
230
      
231
      // this will be replaced with external lookup code above
232
      this.getCachedList();
233
      
234
    } else if ( this.nodeType.equals("cn") ) {
235
      
236
      // get the list from the local metacat database
237
      this.getCachedList();  
238

  
239
    } else {
240
      
241
      // the node type is not recognized
242
      throw new ServiceException("An error occurred in initializing the " +
243
        "ObjectFormatService. The DataONE node type needs to be either "  +
244
        "'cn' or 'mn', but instead was: " + this.nodeType);
245
    }
246
    
247
    // index the object format list based on the format identifier
248
    int listSize = ObjectFormatService.objectFormatList.sizeObjectFormats();
249
    
250
    for (int i = 0; i < listSize; i++ ) {
251
      
252
      ObjectFormat objectFormat = 
253
        ObjectFormatService.objectFormatList.getObjectFormat(i);
254
      String identifier = objectFormat.getFmtid();
255
      ObjectFormatService.objectFormatMap.put(identifier, objectFormat);
256
      
257
    }
258
        
259

  
260
    
261
  }
262

  
263
  /**
108 264
   * Indicate whether or not this service is refreshable.  In this case it is,
109 265
   * where the ObjectFormatService can manually get the latest object format
110 266
   * document from Metacat.
......
125 281
    // stub only 
126 282
    return;
127 283
  }
128
   
129
}
284
  
285
  /**
286
   * List the object formats registered with the object format service.
287
   * 
288
   * @return objectFormatList - the list of object formats
289
   */
290
  public ObjectFormatList listFormats() {
291
    
292
    return ObjectFormatService.objectFormatList;
293
    
294
  }
295
  
296
  /**
297
   * Get the object format based on the given identifier as a string.
298
   * 
299
   * @param format - the object format as a string
300
   * @return objectFormat - the ObjectFormat represented by the format string
301
   */
302
  public static ObjectFormat getFormat(String format) {
303
    
304
    ObjectFormat objectFormat = null;
305
    objectFormat = ObjectFormatService.objectFormatMap.get(format);
306
    
307
    return objectFormat;
308
    
309
  }
310
  /**
311
   * Get the object format list cached in Metacat, or on failure, via a
312
   * cached file on disk
313
   * 
314
   * @return objectFormatList - the cached object format list
315
   */
316
  private void getCachedList()
317
    throws ServiceException {
318
          
319
    try {
320
      
321
      // reset the accession number separator in case it is 
322
      // different than the default
323
      try {
324
        
325
        this.separator = PropertyService.getProperty("document.accNumSeparator");
326
        
327
      } catch ( PropertyNotFoundException pnfe ) {
328
        
329
        // use the default separator, but log the issue
330
        logMetacat.debug("There was a problem finding the document " +
331
          "separator property. The error message was: " + pnfe.getMessage());
332
      }
333
      
334
      // get the latest accession number if it is in Metacat
335
      this.rev = 
336
        DBUtil.getLatestRevisionInDocumentTable(this.OBJECT_FORMAT_DOCID);
337
      
338
      if ( this.rev != -1 ) {
339
        this.accNumber = this.OBJECT_FORMAT_DOCID + 
340
                         this.separator + 
341
                         this.rev;
342
        DocumentImpl objectFormatsDocument = new DocumentImpl(accNumber, false);
343
        ByteArrayInputStream bais = 
344
          new ByteArrayInputStream(objectFormatsDocument.toString().getBytes());
345
        ObjectFormatService.objectFormatList = 
346
          this.deserializeObjectFormatList(bais);
347

  
348
      } else {
349
        
350
        logMetacat.info("The latest revision number of "   + 
351
          this.OBJECT_FORMAT_DOCID                         +
352
          " could not be found. Reverting to the on-disk " +
353
          "object format list");
354
        try {
355
          
356
          ObjectFormatService.objectFormatList = this.getListFromDisk();
357
        
358
        } catch (ServiceException se) {
359
          
360
          throw new ServiceException(se.getMessage());
361
        
362
        }
363
  
364
      }
365
      
366
    } catch ( SQLException sqle ) {
367
      
368
      // we either have a metacat error or the docid was not inserted yet
369
      logMetacat.info("The latest revision number of "   + 
370
        this.OBJECT_FORMAT_DOCID                         +
371
        " could not be found. Reverting to the on-disk " +
372
        "object format list");
373
      
374
      try {
375
        
376
        ObjectFormatService.objectFormatList = this.getListFromDisk();
377
      
378
      } catch (ServiceException se) {
379
        
380
        throw se; 
381
        
382
      }
383
      
384
    } catch (McdbException mcdbe) {
385
      
386
      // we have a metacat doc not found error
387
      logMetacat.info( this.OBJECT_FORMAT_DOCID          +
388
        " could not be found. Reverting to the on-disk " +
389
        "object format list");
390
      
391
      try {
392
        
393
        ObjectFormatService.objectFormatList = this.getListFromDisk();
394
      
395
      } catch (ServiceException se) {
396
        
397
        throw se; 
398
        
399
      }
400
      
401

  
402
    }
403

  
404
    return;
405
    
406
  }
407

  
408
  /**
409
   * Get the object format list cached on disk as stated in the metacat
410
   * properties file.
411
   * 
412
   * @return objectFormatList - the on-disk object format list
413
   * @throws ServiceException
414
   */
415
  private ObjectFormatList getListFromDisk() 
416
    throws ServiceException {
417
    
418
    // the filesystem location of the object format list xml file
419
    String objectFormatFilePath = null;
420
    
421
    // get the object format list from disk and parse it
422
    try {
423
      objectFormatFilePath = SystemUtil.getContextDir() + "/WEB-INF/" +
424
        PropertyService.getProperty("dataone.objectFormatListName");
425
            
426
      FileInputStream fileInputStream = new FileInputStream(objectFormatFilePath);         
427

  
428
      ObjectFormatService.objectFormatList = 
429
        this.deserializeObjectFormatList(fileInputStream);
430

  
431
    } catch (PropertyNotFoundException pnfe) {
432
      
433
      logMetacat.error("The object format list file could not be parsed. " +
434
        "The error message was: " + pnfe.getMessage());
435
      throw new ServiceException(pnfe.getMessage());
436
      
437
    } catch ( FileNotFoundException fnfe ) {
438
      
439
      logMetacat.debug("There was an error reading the file " +
440
        objectFormatFilePath + ". The error was: "            +
441
        fnfe.getMessage());
442
      throw new ServiceException(fnfe.getMessage());
443
          
444
    }
445
    
446
    return ObjectFormatService.objectFormatList;
447
  }
448

  
449
  /**
450
   * Deserialize the object format list file to an object format list object
451
   * 
452
   * @param fileInputStream - the file input stream of the XML object format list file
453
   * @return objectFormatList - the ObjectFormatList object from the XML stream
454
   * @throws ServiceException
455
   */
456
  private ObjectFormatList deserializeObjectFormatList(InputStream inputStream) 
457
    throws ServiceException {
458
    
459
    ObjectFormatList objectFormatList;
460
    try {
461
      objectFormatList = (ObjectFormatList)
462
      ServiceTypeUtil.deserializeServiceType(ObjectFormatList.class, inputStream);
463
    
464
    } catch ( JiBXException jbxe ) {
465
      
466
      logMetacat.debug("There was an error deserializing the input stream. " +
467
        "The error was: " + jbxe.getMessage());
468
      jbxe.printStackTrace();
469
      throw new ServiceException(jbxe.getMessage());
470
    }
471
    
472
    return objectFormatList;
473
  }
474
  
475
}

Also available in: Unified diff