Project

General

Profile

« Previous | Next » 

Revision 5329

Modify CrudService to write SystemMetadata to disk with an autogenerated localId and an autogenerated GUID. Validation depends on the DataONE schemas being setup in xml_catalog properly, so still need to check upgrade scripts to be sure these new schemas are added. Still need to handle the metadata document insert, but should be same as system metadata insert.

View differences:

src/edu/ucsb/nceas/metacat/dataone/CrudService.java
22 22
 */
23 23
package edu.ucsb.nceas.metacat.dataone;
24 24

  
25
import java.io.ByteArrayOutputStream;
25 26
import java.io.File;
26 27
import java.io.FileNotFoundException;
27 28
import java.io.FileOutputStream;
28 29
import java.io.IOException;
29 30
import java.io.InputStream;
30 31
import java.io.OutputStream;
32
import java.io.PrintWriter;
31 33
import java.sql.SQLException;
32 34
import java.util.Date;
33 35
import java.util.Enumeration;
......
57 59
import org.dataone.service.types.Identifier;
58 60
import org.dataone.service.types.LogRecordSet;
59 61
import org.dataone.service.types.SystemMetadata;
62
import org.jibx.runtime.BindingDirectory;
63
import org.jibx.runtime.IBindingFactory;
64
import org.jibx.runtime.IMarshallingContext;
65
import org.jibx.runtime.JiBXException;
60 66

  
61 67
import com.gc.iotools.stream.is.InputStreamFromOutputStream;
62 68

  
......
71 77
import edu.ucsb.nceas.metacat.properties.PropertyService;
72 78
import edu.ucsb.nceas.metacat.replication.ForceReplicationHandler;
73 79
import edu.ucsb.nceas.metacat.service.SessionService;
80
import edu.ucsb.nceas.metacat.util.DocumentUtil;
74 81
import edu.ucsb.nceas.metacat.util.SessionData;
75 82
import edu.ucsb.nceas.utilities.ParseLSIDException;
76 83
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
......
180 187

  
181 188
        logMetacat.debug("Starting CrudService.create()...");
182 189
        
183
        // TODO: authenticate & get user info
184
        String username = "GARBAGETOBEREPLACED";
185
        String[] groups = null;
190
        // authenticate & get user info
191
        SessionData sessionData = getSessionData(token);
192
        String username = sessionData.getUserName();
193
        String[] groups = sessionData.getGroupNames();
186 194

  
187 195
        // verify that guid == SystemMetadata.getIdentifier()
188 196
        logMetacat.debug("Comparing guid|sysmeta_guid: " + guid.getValue() + "|" + sysmeta.getIdentifier().getValue());
189
//        if (!guid.getIdentifier().equals(sysmeta.getIdentifier().getIdentifier())) {
190
//            throw new InvalidSystemMetadata(1180, 
191
//                "GUID in method call does not match GUID in system metadata.");
192
//        }
197
        if (!guid.getValue().equals(sysmeta.getIdentifier().getValue())) {
198
            throw new InvalidSystemMetadata(1180, 
199
                "GUID in method call does not match GUID in system metadata.");
200
        }
193 201

  
194 202
        logMetacat.debug("Checking if identifier exists...");
195 203
        // Check that the identifier does not already exist
......
203 211
        logMetacat.debug("Generating a guid/localId mapping");
204 212
        String localId = im.generateLocalId(guid.getValue(), 1);
205 213

  
206
        // TODO: generate guid/localId pair for sysmeta
207
        // TODO: update system metadata fields
208
        // TODO: insert system metadata to metacat (probably at end)
209

  
210
        // TODO: Check if we are handling metadata or data
214
        // Check if we are handling metadata or data
215
        boolean isScienceMetadata = isScienceMetadata(sysmeta);
211 216
        
212
        // TODO: CASE METADATA:
213
        // Setup and call handleInsertOrUpdate()
217
        if (isScienceMetadata) {
218
            // TODO: CASE METADATA:
219
            // Setup and call handleInsertOrUpdate()
214 220

  
215
        // TODO: DEFAULT CASE: DATA
216
        try {
217
            logMetacat.debug("Case DATA: starting to write to disk.");
218
            if (DocumentImpl.getDataFileLockGrant(localId)) {
221
        } else {
222
            // TODO: DEFAULT CASE: DATA (needs to be checked and completed)
223
            try {
224
                logMetacat.debug("Case DATA: starting to write to disk.");
225
                if (DocumentImpl.getDataFileLockGrant(localId)) {
219 226

  
220
                // Save the data file to disk using "localId" as the name
221
                try {
222
                    String datafilepath = PropertyService.getProperty("application.datafilepath");
227
                    // Save the data file to disk using "localId" as the name
228
                    try {
229
                        String datafilepath = PropertyService.getProperty("application.datafilepath");
223 230

  
224
                    File dataDirectory = new File(datafilepath);
225
                    dataDirectory.mkdirs();
231
                        File dataDirectory = new File(datafilepath);
232
                        dataDirectory.mkdirs();
226 233

  
227
                    File newFile = writeStreamToFile(dataDirectory, localId, object);
234
                        File newFile = writeStreamToFile(dataDirectory, localId, object);
228 235

  
229
                    // TODO: Check that the file size matches SystemMetadata
230
                    //                        long size = newFile.length();
231
                    //                        if (size == 0) {
232
                    //                            throw new IOException("Uploaded file is 0 bytes!");
233
                    //                        }
236
                        // TODO: Check that the file size matches SystemMetadata
237
                        //                        long size = newFile.length();
238
                        //                        if (size == 0) {
239
                        //                            throw new IOException("Uploaded file is 0 bytes!");
240
                        //                        }
234 241

  
235
                    //register the file in the database (which generates an exception
236
                    // if the docid is not acceptable or other untoward things happen
237
                    try {
238
                        logMetacat.debug("Registering document...");
239
                        DocumentImpl.registerDocument(localId, "BIN", localId,
240
                                username, groups);
241
                        logMetacat.debug("Registrtion step completed.");
242
                    } catch (SQLException e) {
243
                        //newFile.delete();
244
                        logMetacat.debug("SQLE: " + e.getMessage());
245
                        e.printStackTrace(System.out);
246
                        throw new ServiceFailure(1190, "Registration failed: " + e.getMessage());
247
                    } catch (AccessionNumberException e) {
248
                        //newFile.delete();
249
                        logMetacat.debug("ANE: " + e.getMessage());
250
                        e.printStackTrace(System.out);
251
                        throw new ServiceFailure(1190, "Registration failed: " + e.getMessage());
252
                    } catch (Exception e) {
253
                        //newFile.delete();
254
                        logMetacat.debug("Exception: " + e.getMessage());
255
                        e.printStackTrace(System.out);
256
                        throw new ServiceFailure(1190, "Registration failed: " + e.getMessage());
242
                        //register the file in the database (which generates an exception
243
                        // if the docid is not acceptable or other untoward things happen
244
                        try {
245
                            logMetacat.debug("Registering document...");
246
                            DocumentImpl.registerDocument(localId, "BIN", localId,
247
                                    username, groups);
248
                            logMetacat.debug("Registrtion step completed.");
249
                        } catch (SQLException e) {
250
                            //newFile.delete();
251
                            logMetacat.debug("SQLE: " + e.getMessage());
252
                            e.printStackTrace(System.out);
253
                            throw new ServiceFailure(1190, "Registration failed: " + e.getMessage());
254
                        } catch (AccessionNumberException e) {
255
                            //newFile.delete();
256
                            logMetacat.debug("ANE: " + e.getMessage());
257
                            e.printStackTrace(System.out);
258
                            throw new ServiceFailure(1190, "Registration failed: " + e.getMessage());
259
                        } catch (Exception e) {
260
                            //newFile.delete();
261
                            logMetacat.debug("Exception: " + e.getMessage());
262
                            e.printStackTrace(System.out);
263
                            throw new ServiceFailure(1190, "Registration failed: " + e.getMessage());
264
                        }
265

  
266
                        logMetacat.debug("Logging the creation event.");
267
                        EventLog.getInstance().log(request.getRemoteAddr(),
268
                                username, localId, "create");
269

  
270
                        // Force replication this data file
271
                        // To data file, "insert" and update is same
272
                        // The fourth parameter is null. Because it is notification 
273
                        // server and this method is in MetaCatServerlet. It is
274
                        // original command, not get force replication info from 
275
                        // another metacat
276
                        // TODO: note that GUID mapping is not being replicated
277
                        logMetacat.debug("Scheduling replication.");
278
                        ForceReplicationHandler frh = new ForceReplicationHandler(
279
                                localId, "insert", false, null);
280

  
281
                    } catch (PropertyNotFoundException e) {
282
                        throw new ServiceFailure(1190, "Could not lock file for writing:" + e.getMessage());
257 283
                    }
258 284

  
259
                    logMetacat.debug("Logging the creation event.");
260
                    EventLog.getInstance().log(request.getRemoteAddr(),
261
                            username, localId, "create");
262
                    
263
                    // Force replication this data file
264
                    // To data file, "insert" and update is same
265
                    // The fourth parameter is null. Because it is notification 
266
                    // server and this method is in MetaCatServerlet. It is
267
                    // original command, not get force replication info from 
268
                    // another metacat
269
                    // TODO: note that GUID mapping is not being replicated
270
                    logMetacat.debug("Scheduling replication.");
271
                    ForceReplicationHandler frh = new ForceReplicationHandler(
272
                            localId, "insert", false, null);
273

  
274
                } catch (PropertyNotFoundException e) {
275
                    throw new ServiceFailure(1190, "Could not lock file for writing:" + e.getMessage());
276 285
                }
277

  
286
            } catch (Exception e) {
287
                // Could not get a lock on the document, so we can not update the file now
288
                throw new ServiceFailure(1190, "Failed to lock file: " + e.getMessage());
278 289
            }
279
        } catch (Exception e) {
280
            // Could not get a lock on the document, so we can not update the file now
281
            throw new ServiceFailure(1190, "Failed to lock file: " + e.getMessage());
290
            
291
            // Insert the system metadata into the object store
292
            insertSystemMetadata(sysmeta, sessionData);
282 293
        }
283 294
        
284 295
        logMetacat.debug("Returning from CrudService.create()");
......
345 356
        } catch (McdbDocNotFoundException e) {
346 357
            throw new NotFound(1020, e.getMessage());
347 358
        }
348
        
349
/*    
350
 *      Alternative approach that uses Piped streams, but requires thread handling
351
 *      which makes exception handling difficult (because exceptions fall off the
352
 *      calling thread, terminating the thread.
353
 *      
354
        // Look up the localId for this global identifier
355
        IdentifierManager im = IdentifierManager.getInstance();
356
        try {
357
            final String localId = im.getLocalId(guid.getIdentifier());
358

  
359
            // Now use that localId to read the object and return it
360
            params.put("docid", new String[] { localId });        
361
            final PipedInputStream in = new PipedInputStream();
362
            new Thread(
363
                    new Runnable() {
364
                        public void run() {
365
                            try {
366
                                PipedOutputStream out = new PipedOutputStream(in);
367
                                handler.readFromMetacat(request.getRemoteAddr(), null, 
368
                                        out, localId, "xml",
369
                                        username, groupNames, true, params);
370
                            } catch (PropertyNotFoundException e) {
371
                                throw new ServiceFailure(1030, e.getMessage());
372
                            } catch (ClassNotFoundException e) {
373
                                throw new ServiceFailure(1030, e.getMessage());
374
                            } catch (IOException e) {
375
                                throw new ServiceFailure(1030, e.getMessage());
376
                            } catch (SQLException e) {
377
                                throw new ServiceFailure(1030, e.getMessage());
378
                            } catch (McdbException e) {
379
                                throw new ServiceFailure(1030, e.getMessage());
380
                            } catch (ParseLSIDException e) {
381
                                throw new NotFound(1020, e.getMessage());
382
                            } catch (InsufficientKarmaException e) {
383
                                throw new NotAuthorized(1000, "Not authorized for get().");
384
                            }
385
                        }
386
                    }
387
            ).start();
388
            return in;
389
        } catch (McdbDocNotFoundException e) {
390
            throw new NotFound(1020, e.getMessage());
391
        }        
392
*/
393 359
    }
394 360

  
395 361
    public Checksum getChecksum(AuthToken token, Identifier guid)
......
414 380
            throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
415 381
            InvalidRequest, NotImplemented {
416 382
        
417
        // Look up ID of system metadata based on guid
418
            // Initially from document, later from entry in table?
383
        // TODO: Look up ID of system metadata based on guid
384
            // TODO: Initially from document, later from entry in table?
419 385
        
420
        // Read system metadata from disk and create SystemMetadata object
421
            // Follows same implementation plan as get()
386
        // TODO: Read system metadata from disk and create SystemMetadata object
387
            // TODO: Follows same implementation plan as get()
422 388
        
423
        // return it
389
        // TODO: return it
424 390
        throw new NotImplemented(1000, "This method not yet implemented.");
425 391
    }
426 392

  
......
473 439
//        logMetacat.debug("***********************************************");
474 440
        
475 441
        return newFile;
476
    }   
442
    }
443

  
444
    /** 
445
     * Determine if a given object should be treated as an XML science metadata
446
     * object. 
447
     * 
448
     * TODO: This test should be externalized in a configuration dictionary rather than being hardcoded.
449
     * 
450
     * @param sysmeta the SystemMetadata describig the object
451
     * @return true if the object should be treated as science metadata
452
     */
453
    private boolean isScienceMetadata(SystemMetadata sysmeta) {
454
        boolean scimeta = false;
455
        switch (sysmeta.getObjectFormat()) {
456
            case EML_2_1_0: scimeta = true; break;
457
            case EML_2_0_1: scimeta = true; break;
458
            case EML_2_0_0: scimeta = true; break;
459
            case FGDC_STD_001_1_1999: scimeta = true; break;
460
            case FGDC_STD_001_1998: scimeta = true; break;
461
            case NCML_2_2: scimeta = true; break;
462
        }
463
        
464
        return scimeta;
465
    }
466

  
467
    private void insertSystemMetadata(SystemMetadata sysmeta, SessionData sessionData) 
468
        throws ServiceFailure {
469
        logMetacat.debug("Starting to insert SystemMetadata...");
470
        IdentifierManager im = IdentifierManager.getInstance();
471
    
472
        // generate guid/localId pair for sysmeta
473
        String sysMetaGuid = DocumentUtil.generateDocumentId(1);
474
        sysmeta.setDateSysMetadataModified(new Date());
475

  
476
        String xml = new String(serializeSystemMetadata(sysmeta).toByteArray());
477
        insertDocument(xml, sysMetaGuid, sessionData);
478
    }
479
    
480
    private void insertDocument(String xml, String guid, SessionData sessionData) 
481
        throws ServiceFailure {
482
        logMetacat.debug("Starting to insert xml document...");
483
        IdentifierManager im = IdentifierManager.getInstance();
484

  
485
        // generate guid/localId pair for sysmeta
486
        String localId = im.generateLocalId(guid, 1);
487
        logMetacat.debug("Metadata guid|localId: " + guid + "|" +
488
                localId);
489

  
490
        // TODO: insert system metadata to metacat (probably at end)
491
        // TODO: can't pass in the out PrintWriter, as we don't want to write
492
        // error info on this stream -- need to be able to return to process
493
        // the real object.  So, need to:
494
        // TODO: refactor handleInsertOrUpdateAction() to not output XML directly
495
        // onto output stream, or alternatively, capture that and parse it to 
496
        // generate the right exceptions
497
        String[] action = new String[1];
498
        action[0] = "insert";
499
        params.put("action", action);
500
        String[] docid = new String[1];
501
        docid[0] = localId;
502
        params.put("docid", docid);
503
        String[] doctext = new String[1];
504
        doctext[0] = xml;
505
        logMetacat.debug(doctext[0]);
506
        params.put("doctext", doctext);
507
        ByteArrayOutputStream output = new ByteArrayOutputStream();
508
        PrintWriter pw = new PrintWriter(output);
509
        handler.handleInsertOrUpdateAction(request.getRemoteAddr(), response, 
510
                pw, params, sessionData.getUserName(),
511
                sessionData.getGroupNames());
512
        logMetacat.debug(new String(output.toByteArray()));
513
        logMetacat.debug("Finsihed inserting xml document.");
514
    }
515
    
516
    private ByteArrayOutputStream serializeSystemMetadata(SystemMetadata sysmeta) 
517
        throws ServiceFailure {
518
        IBindingFactory bfact;
519
        ByteArrayOutputStream sysmetaOut = null;
520
        try {
521
            bfact = BindingDirectory.getFactory(SystemMetadata.class);
522
            IMarshallingContext mctx = bfact.createMarshallingContext();
523
            sysmetaOut = new ByteArrayOutputStream();
524
            mctx.marshalDocument(sysmeta, "UTF-8", null, sysmetaOut);
525
        } catch (JiBXException e) {
526
            throw new ServiceFailure(1190, "Failed to serialize and insert SystemMetadata: " + e.getMessage());
527
        }
528
        
529
        return sysmetaOut;
530
    }
477 531
}

Also available in: Unified diff