Project

General

Profile

« Previous | Next » 

Revision 5331

Completed main parts of CrudService.create(). Now the method writes both data and metadata objects along with their system metadata, and handles the mapping between global identifiers and local identifiers. Access control and logging still need to be dealt with to properly authenticate and then log activities.

View differences:

src/edu/ucsb/nceas/metacat/dataone/CrudService.java
94 94
    private HttpServletRequest request;
95 95
    private HttpServletResponse response;
96 96

  
97
//    private Logger logMetacat;
98 97
    private MetacatHandler handler;
99
//    private String username;
100
//    private String password;
101
//    private String sessionId;
102
//    private String[] groupNames;
103 98
    private Hashtable<String, String[]> params;
104 99
    Logger logMetacat = null;
105 100

  
......
137 132
        }
138 133
    }
139 134
    
140
    /**
141
     * 
142
     * Load user details of metacat session from the request 
143
     * 
144
     */
145
//    private void loadSessionData() {
146
//        SessionData sessionData = RequestUtil.getSessionData(request);
147
//
148
//        // TODO: validate the session before allowing these values to be set
149
//        username = sessionData.getUserName();
150
//        password = sessionData.getPassword();
151
//        groupNames = sessionData.getGroupNames();
152
//        sessionId = sessionData.getId();
153
//
154
//        if (username == null) {
155
//            username = "public";
156
//        }
157
//    }
158
    
159
    /*
160
     * Look up the information on the session using the token provided in
161
     * the AuthToken.  The Session should have all relevant user information.
162
     * If the session has expired or is invalid, the 'public' session will
163
     * be returned, giving the user anonymous access.
164
     */
165
    private static SessionData getSessionData(AuthToken token) {
166
        SessionData sessionData = null;
167
        String sessionId = "PUBLIC";
168
        if (token != null) {
169
            sessionId = token.getToken();
170
        }
171
        
172
        // if the session id is registered in SessionService, get the
173
        // SessionData for it. Otherwise, use the public session.
174
        if (SessionService.isSessionRegistered(sessionId)) {
175
            sessionData = SessionService.getRegisteredSession(sessionId);
176
        } else {
177
            sessionData = SessionService.getPublicSession();
178
        }
179
        
180
        return sessionData;
181
    }
182
    
183 135
    public Identifier create(AuthToken token, Identifier guid, 
184 136
            InputStream object, SystemMetadata sysmeta) throws InvalidToken, 
185 137
            ServiceFailure, NotAuthorized, IdentifierNotUnique, UnsupportedType, 
......
207 159
                "GUID is already in use by an existing object.");
208 160
        }
209 161

  
210
        // generate guid/localId pair for object
211
        logMetacat.debug("Generating a guid/localId mapping");
212
        String localId = im.generateLocalId(guid.getValue(), 1);
213

  
214 162
        // Check if we are handling metadata or data
215 163
        boolean isScienceMetadata = isScienceMetadata(sysmeta);
216 164
        
217 165
        if (isScienceMetadata) {
218
            // TODO: CASE METADATA:
219
            // Setup and call handleInsertOrUpdate()
166
            // CASE METADATA:
167
            try {
168
                String xml = IOUtils.toString(object);
169
                this.insertDocument(xml, guid, sessionData);
170
            } catch (IOException e) {
171
                String msg = "Could not create string from XML stream: " +
172
                    " " + e.getMessage();
173
                logMetacat.debug(msg);
174
                throw new ServiceFailure(1190, msg);
175
            }
220 176

  
221 177
        } 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)) {
178
            // DEFAULT CASE: DATA (needs to be checked and completed)
179
            insertDataObject(object, guid, sessionData);
180
            
181
        }
226 182

  
227
                    // Save the data file to disk using "localId" as the name
228
                    try {
229
                        String datafilepath = PropertyService.getProperty("application.datafilepath");
183
        // For Metadata and Data, insert the system metadata into the object store too
184
        insertSystemMetadata(sysmeta, sessionData);
230 185

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

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

  
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
                        //                        }
241

  
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());
283
                    }
284

  
285
                }
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());
289
            }
290
            
291
            // Insert the system metadata into the object store
292
            insertSystemMetadata(sysmeta, sessionData);
293
        }
294
        
295 186
        logMetacat.debug("Returning from CrudService.create()");
296 187
        return guid;
297 188
    }
......
398 289
        throw new NotImplemented(1000, "This method not yet implemented.");
399 290
    }
400 291

  
292
    /*
293
     * Look up the information on the session using the token provided in
294
     * the AuthToken.  The Session should have all relevant user information.
295
     * If the session has expired or is invalid, the 'public' session will
296
     * be returned, giving the user anonymous access.
297
     */
298
    private static SessionData getSessionData(AuthToken token) {
299
        SessionData sessionData = null;
300
        String sessionId = "PUBLIC";
301
        if (token != null) {
302
            sessionId = token.getToken();
303
        }
304
        
305
        // if the session id is registered in SessionService, get the
306
        // SessionData for it. Otherwise, use the public session.
307
        if (SessionService.isSessionRegistered(sessionId)) {
308
            sessionData = SessionService.getRegisteredSession(sessionId);
309
        } else {
310
            sessionData = SessionService.getPublicSession();
311
        }
312
        
313
        return sessionData;
314
    }
315

  
316
    /** 
317
     * Determine if a given object should be treated as an XML science metadata
318
     * object. 
319
     * 
320
     * TODO: This test should be externalized in a configuration dictionary rather than being hardcoded.
321
     * 
322
     * @param sysmeta the SystemMetadata describig the object
323
     * @return true if the object should be treated as science metadata
324
     */
325
    private boolean isScienceMetadata(SystemMetadata sysmeta) {
326
        boolean scimeta = false;
327
        switch (sysmeta.getObjectFormat()) {
328
            case EML_2_1_0: scimeta = true; break;
329
            case EML_2_0_1: scimeta = true; break;
330
            case EML_2_0_0: scimeta = true; break;
331
            case FGDC_STD_001_1_1999: scimeta = true; break;
332
            case FGDC_STD_001_1998: scimeta = true; break;
333
            case NCML_2_2: scimeta = true; break;
334
        }
335
        
336
        return scimeta;
337
    }
338

  
339
    private void insertDataObject(InputStream object, Identifier guid, 
340
            SessionData sessionData) throws ServiceFailure {
341
        
342
        String username = sessionData.getUserName();
343
        String[] groups = sessionData.getGroupNames();
344

  
345
        // generate guid/localId pair for object
346
        logMetacat.debug("Generating a guid/localId mapping");
347
        IdentifierManager im = IdentifierManager.getInstance();
348
        String localId = im.generateLocalId(guid.getValue(), 1);
349

  
350
        try {
351
            logMetacat.debug("Case DATA: starting to write to disk.");
352
            if (DocumentImpl.getDataFileLockGrant(localId)) {
353
    
354
                // Save the data file to disk using "localId" as the name
355
                try {
356
                    String datafilepath = PropertyService.getProperty("application.datafilepath");
357
    
358
                    File dataDirectory = new File(datafilepath);
359
                    dataDirectory.mkdirs();
360
    
361
                    File newFile = writeStreamToFile(dataDirectory, localId, object);
362
    
363
                    // TODO: Check that the file size matches SystemMetadata
364
                    //                        long size = newFile.length();
365
                    //                        if (size == 0) {
366
                    //                            throw new IOException("Uploaded file is 0 bytes!");
367
                    //                        }
368
    
369
                    // Register the file in the database (which generates an exception
370
                    // if the localId is not acceptable or other untoward things happen
371
                    try {
372
                        logMetacat.debug("Registering document...");
373
                        DocumentImpl.registerDocument(localId, "BIN", localId,
374
                                username, groups);
375
                        logMetacat.debug("Registration step completed.");
376
                    } catch (SQLException e) {
377
                        //newFile.delete();
378
                        logMetacat.debug("SQLE: " + e.getMessage());
379
                        e.printStackTrace(System.out);
380
                        throw new ServiceFailure(1190, "Registration failed: " + e.getMessage());
381
                    } catch (AccessionNumberException e) {
382
                        //newFile.delete();
383
                        logMetacat.debug("ANE: " + e.getMessage());
384
                        e.printStackTrace(System.out);
385
                        throw new ServiceFailure(1190, "Registration failed: " + e.getMessage());
386
                    } catch (Exception e) {
387
                        //newFile.delete();
388
                        logMetacat.debug("Exception: " + e.getMessage());
389
                        e.printStackTrace(System.out);
390
                        throw new ServiceFailure(1190, "Registration failed: " + e.getMessage());
391
                    }
392
    
393
                    logMetacat.debug("Logging the creation event.");
394
                    EventLog.getInstance().log(request.getRemoteAddr(),
395
                            username, localId, "create");
396
    
397
                    // Schedule replication for this data file
398
                    logMetacat.debug("Scheduling replication.");
399
                    ForceReplicationHandler frh = new ForceReplicationHandler(
400
                            localId, "insert", false, null);
401
    
402
                } catch (PropertyNotFoundException e) {
403
                    throw new ServiceFailure(1190, "Could not lock file for writing:" + e.getMessage());
404
                }
405
    
406
            }
407
        } catch (Exception e) {
408
            // Could not get a lock on the document, so we can not update the file now
409
            throw new ServiceFailure(1190, "Failed to lock file: " + e.getMessage());
410
        }
411
    }
412

  
401 413
    private File writeStreamToFile(File dir, String fileName, InputStream data) 
402 414
        throws ServiceFailure {
403
//        logMetacat.debug("***********************************************");
404
//        logMetacat.debug("** FILE TEST FROM CS                         **");
405
//        logMetacat.debug("***********************************************");
406 415
        
407 416
        File newFile = new File(dir, fileName);
408 417
        logMetacat.debug("Filename for write is: " + newFile.getAbsolutePath());
409 418

  
410 419
        try {
411 420
            if (newFile.createNewFile()) {
412
//                logMetacat.debug("File doesn't yet exist, so write to it.");
413
//                logMetacat.debug("Creating file stream...");
414
                
415 421
                // write data stream to desired file
416 422
                OutputStream os = new FileOutputStream(newFile);
417
//                logMetacat.debug("Copying file stream...");
418 423
                long length = IOUtils.copyLarge(data, os);
419 424
                os.flush();
420
//                logMetacat.debug("Closing file stream...");
421 425
                os.close();
422
//                logMetacat.debug("Done with file stream...");
423 426
            } else {
424 427
                logMetacat.debug("File creation failed, or file already exists.");
425 428
                throw new ServiceFailure(1190, "File already exists: " + fileName);
......
434 437
                    + " " + e.getMessage());
435 438
        }
436 439

  
437
//        logMetacat.debug("***********************************************");
438
//        logMetacat.debug("** END FILE TEST                             **");
439
//        logMetacat.debug("***********************************************");
440
        
441 440
        return newFile;
442 441
    }
443 442

  
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 443
    private void insertSystemMetadata(SystemMetadata sysmeta, SessionData sessionData) 
468 444
        throws ServiceFailure {
469 445
        logMetacat.debug("Starting to insert SystemMetadata...");
470 446
        IdentifierManager im = IdentifierManager.getInstance();
471 447
    
472 448
        // generate guid/localId pair for sysmeta
473
        String sysMetaGuid = DocumentUtil.generateDocumentId(1);
449
        Identifier sysMetaGuid = new Identifier();
450
        sysMetaGuid.setValue(DocumentUtil.generateDocumentId(1));
474 451
        sysmeta.setDateSysMetadataModified(new Date());
475 452

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

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

  
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 467
        String[] action = new String[1];
498 468
        action[0] = "insert";
499 469
        params.put("action", action);
......
504 474
        doctext[0] = xml;
505 475
        logMetacat.debug(doctext[0]);
506 476
        params.put("doctext", doctext);
477
        
478
        // TODO: refactor handleInsertOrUpdateAction() to not output XML directly
479
        // onto output stream, or alternatively, capture that and parse it to 
480
        // generate the right exceptions
507 481
        ByteArrayOutputStream output = new ByteArrayOutputStream();
508 482
        PrintWriter pw = new PrintWriter(output);
509 483
        handler.handleInsertOrUpdateAction(request.getRemoteAddr(), response, 
510 484
                pw, params, sessionData.getUserName(),
511 485
                sessionData.getGroupNames());
512 486
        logMetacat.debug(new String(output.toByteArray()));
513
        logMetacat.debug("Finsihed inserting xml document.");
487
        logMetacat.debug("Finsished inserting xml document.");
514 488
    }
515 489
    
516 490
    private ByteArrayOutputStream serializeSystemMetadata(SystemMetadata sysmeta) 

Also available in: Unified diff