Revision 5331
Added by Matt Jones over 14 years ago
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
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.