Revision 5286
Added by Matt Jones over 14 years ago
test/edu/ucsb/nceas/MCTestCase.java | ||
---|---|---|
59 | 59 |
import edu.ucsb.nceas.metacat.client.MetacatInaccessibleException; |
60 | 60 |
import edu.ucsb.nceas.metacat.properties.PropertyService; |
61 | 61 |
import edu.ucsb.nceas.metacat.shared.ServiceException; |
62 |
import edu.ucsb.nceas.metacat.util.DocumentUtil; |
|
62 | 63 |
import edu.ucsb.nceas.metacat.util.RequestUtil; |
63 | 64 |
import edu.ucsb.nceas.utilities.IOUtil; |
64 | 65 |
import edu.ucsb.nceas.utilities.PropertyNotFoundException; |
... | ... | |
515 | 516 |
} catch (InterruptedException ie) { |
516 | 517 |
debug("Could not sleep: " + ie.getMessage()); |
517 | 518 |
} |
518 |
|
|
519 |
StringBuffer docid = new StringBuffer(prefix); |
|
520 |
docid.append("."); |
|
521 | 519 |
|
522 |
// Create a calendar to get the date formatted properly |
|
523 |
String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000); |
|
524 |
SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]); |
|
525 |
pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000); |
|
526 |
pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000); |
|
527 |
Calendar calendar = new GregorianCalendar(pdt); |
|
528 |
Date trialTime = new Date(); |
|
529 |
calendar.setTime(trialTime); |
|
530 |
docid.append(calendar.get(Calendar.YEAR)); |
|
531 |
docid.append(calendar.get(Calendar.DAY_OF_YEAR)); |
|
532 |
docid.append(calendar.get(Calendar.HOUR_OF_DAY)); |
|
533 |
docid.append(calendar.get(Calendar.MINUTE)); |
|
534 |
docid.append(calendar.get(Calendar.SECOND)); |
|
535 |
|
|
536 |
return docid.toString(); |
|
520 |
return DocumentUtil.generateDocumentId(prefix, 0); |
|
537 | 521 |
} |
538 | 522 |
|
539 | 523 |
/** |
540 | 524 |
* Insert a document into metacat. The expected result is passed as result |
541 | 525 |
*/ |
542 |
|
|
543 | 526 |
protected String insertDocumentId(String docid, String docText, boolean result, |
544 | 527 |
boolean expectKarmaException) { |
545 | 528 |
debug("insertDocumentId() - docid=" + docid + " expectedResult=" + result |
test/edu/ucsb/nceas/metacattest/restservice/MetacatRestClientTest.java | ||
---|---|---|
25 | 25 |
import java.io.IOException; |
26 | 26 |
import java.io.Reader; |
27 | 27 |
import java.io.StringReader; |
28 |
import java.util.Calendar; |
|
29 |
import java.util.Date; |
|
30 |
import java.util.GregorianCalendar; |
|
31 |
import java.util.SimpleTimeZone; |
|
32 |
import java.util.TimeZone; |
|
28 | 33 |
import java.util.Vector; |
29 | 34 |
|
30 | 35 |
import junit.framework.Test; |
... | ... | |
204 | 209 |
debug("-------------------------------------------------------"); |
205 | 210 |
try { |
206 | 211 |
IdentifierManager im = IdentifierManager.getInstance(); |
207 |
String docid = insertTestDocument(); |
|
208 |
String guid = "test:"+docid; |
|
209 |
im.createMapping(guid, docid); |
|
212 |
String guid = insertTestDocument(); |
|
210 | 213 |
Reader r = m.getObject(guid, null); |
211 | 214 |
String doc = IOUtil.getAsString(r, true); |
212 | 215 |
doc = doc +"\n"; |
... | ... | |
358 | 361 |
accessBlock, null, null, |
359 | 362 |
null, null); |
360 | 363 |
String docid = generateDocumentId(); |
361 |
|
|
364 |
debug("Generated id: " + docid); |
|
362 | 365 |
StringReader sr = new StringReader(emldoc); |
363 | 366 |
m.login(username,password); |
364 | 367 |
|
... | ... | |
368 | 371 |
debug("response:\n"+response); |
369 | 372 |
assertTrue(response.indexOf("success") != -1); |
370 | 373 |
|
374 |
Thread.sleep(5000); |
|
375 |
|
|
371 | 376 |
sr = new StringReader(emldoc); |
372 | 377 |
debug("\nNow update the document..."); |
373 | 378 |
response = m.putObject(docid + ".2",sr,false); |
... | ... | |
375 | 380 |
assertTrue(response.indexOf("success") != -1); |
376 | 381 |
sr.close(); |
377 | 382 |
|
378 |
Thread.sleep(10000);
|
|
383 |
Thread.sleep(5000);
|
|
379 | 384 |
|
380 | 385 |
debug("\nFinally delete the document..."); |
381 | 386 |
response = m.deleteObject(docid + ".2"); |
... | ... | |
499 | 504 |
} |
500 | 505 |
} |
501 | 506 |
|
502 |
/** Insert a test document, returning the docid that was used. */
|
|
507 |
/** Insert a test document, returning the identifier that was used. */
|
|
503 | 508 |
private String insertTestDocument() |
504 | 509 |
{ |
505 | 510 |
String accessBlock = getAccessBlock("public", true, true, |
... | ... | |
508 | 513 |
null, "http://fake.example.com/somedata", null, |
509 | 514 |
accessBlock, null, null, |
510 | 515 |
null, null); |
511 |
String docid = generateDocumentId() + ".1"; |
|
516 |
//String docid = generateDocumentId() + ".1"; |
|
517 |
String guid = "testid:" + generateTimeString(); |
|
512 | 518 |
StringReader sr = new StringReader(emldoc); |
513 | 519 |
String response; |
514 | 520 |
try { |
515 | 521 |
m.login(username,password); |
516 |
response = m.putObject(docid,sr,true);
|
|
522 |
response = m.putObject(guid, sr, true);
|
|
517 | 523 |
debug("response:\n"+response); |
518 | 524 |
assertTrue(response.indexOf("success") != -1); |
519 | 525 |
} catch (InsufficientKarmaException e) { |
... | ... | |
527 | 533 |
} catch (MetacatAuthException e) { |
528 | 534 |
fail(e.getMessage()); |
529 | 535 |
} |
530 |
return docid;
|
|
536 |
return guid;
|
|
531 | 537 |
} |
538 |
|
|
539 |
/** Generate a timestamp for use in IDs. */ |
|
540 |
private String generateTimeString() |
|
541 |
{ |
|
542 |
StringBuffer guid = new StringBuffer(); |
|
543 |
|
|
544 |
// Create a calendar to get the date formatted properly |
|
545 |
String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000); |
|
546 |
SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]); |
|
547 |
pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000); |
|
548 |
pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000); |
|
549 |
Calendar calendar = new GregorianCalendar(pdt); |
|
550 |
Date trialTime = new Date(); |
|
551 |
calendar.setTime(trialTime); |
|
552 |
guid.append(calendar.get(Calendar.YEAR)); |
|
553 |
guid.append(calendar.get(Calendar.DAY_OF_YEAR)); |
|
554 |
guid.append(calendar.get(Calendar.HOUR_OF_DAY)); |
|
555 |
guid.append(calendar.get(Calendar.MINUTE)); |
|
556 |
guid.append(calendar.get(Calendar.SECOND)); |
|
557 |
guid.append(calendar.get(Calendar.MILLISECOND)); |
|
558 |
|
|
559 |
return guid.toString(); |
|
560 |
} |
|
532 | 561 |
} |
src/edu/ucsb/nceas/metacat/restservice/ResourceHandler.java | ||
---|---|---|
227 | 227 |
private void loadSessionData() { |
228 | 228 |
SessionData sessionData = RequestUtil.getSessionData(request); |
229 | 229 |
|
230 |
// TODO: validate the session before allowing these values to be set |
|
230 | 231 |
username = sessionData.getUserName(); |
231 | 232 |
password = sessionData.getPassword(); |
232 | 233 |
groupNames = sessionData.getGroupNames(); |
233 | 234 |
sessionId = sessionData.getId(); |
234 | 235 |
|
235 |
if (username == null) |
|
236 |
if (username == null) {
|
|
236 | 237 |
username = "public"; |
238 |
} |
|
237 | 239 |
} |
238 | 240 |
|
239 | 241 |
/** |
... | ... | |
344 | 346 |
|
345 | 347 |
/** |
346 | 348 |
* Earthgrid API > Identifier Service > isRegistered Function : calls MetacatHandler > handleIdIsRegisteredAction |
347 |
* @param identifierId
|
|
349 |
* @param guid
|
|
348 | 350 |
* @throws IOException |
349 | 351 |
*/ |
350 |
private void isRegistered(String identifierId) throws IOException { |
|
351 |
params.put("docid", new String[] { identifierId }); |
|
352 |
private void isRegistered(String guid) throws IOException |
|
353 |
{ |
|
354 |
|
|
355 |
// Look up the localId for this guid |
|
356 |
IdentifierManager im = IdentifierManager.getInstance(); |
|
357 |
String localId = ""; |
|
358 |
try { |
|
359 |
localId = im.getLocalId(guid); |
|
360 |
} catch (McdbDocNotFoundException e) { |
|
361 |
// TODO: Need to return the proper DataONE exception |
|
362 |
} |
|
363 |
|
|
364 |
params.put("docid", new String[] { localId }); |
|
352 | 365 |
PrintWriter out = response.getWriter(); |
353 | 366 |
handler.handleIdIsRegisteredAction(out, params, response); |
354 | 367 |
out.close(); |
... | ... | |
366 | 379 |
|
367 | 380 |
/** |
368 | 381 |
* Earthgrid API > Identifier Service > getNextRevision Function : calls MetacatHandler > handleGetRevisionAndDocTypeAction |
369 |
* @param identifierId
|
|
382 |
* @param guid
|
|
370 | 383 |
* @throws IOException |
371 | 384 |
*/ |
372 |
private void getNextRevision(String identifierId) throws IOException { |
|
373 |
params.put("docid", new String[] { identifierId }); |
|
385 |
private void getNextRevision(String guid) throws IOException |
|
386 |
{ |
|
387 |
params.put("docid", new String[] { guid }); |
|
374 | 388 |
PrintWriter out = response.getWriter(); |
375 | 389 |
//handler.handleGetRevisionAndDocTypeAction(out, params); |
376 | 390 |
|
377 | 391 |
try { |
378 | 392 |
// Make sure there is a docid |
379 |
if (identifierId == null || identifierId.equals("")) {
|
|
393 |
if (guid == null || guid.equals("")) {
|
|
380 | 394 |
throw new Exception("User didn't specify docid!"); |
381 |
}//if
|
|
395 |
} |
|
382 | 396 |
|
397 |
// Look up the localId for this guid |
|
398 |
IdentifierManager im = IdentifierManager.getInstance(); |
|
399 |
String localId = ""; |
|
400 |
try { |
|
401 |
localId = im.getLocalId(guid); |
|
402 |
} catch (McdbDocNotFoundException e) { |
|
403 |
// TODO: Need to return the proper DataONE exception |
|
404 |
} |
|
405 |
|
|
383 | 406 |
// Create a DBUtil object |
384 | 407 |
DBUtil dbutil = new DBUtil(); |
385 | 408 |
// Get a rev and doctype |
386 | 409 |
String revAndDocType = dbutil |
387 |
.getCurrentRevisionAndDocTypeForGivenDocument(identifierId);
|
|
410 |
.getCurrentRevisionAndDocTypeForGivenDocument(localId);
|
|
388 | 411 |
int revision = Integer.parseInt(revAndDocType.split(";")[0]) + 1; |
389 | 412 |
|
390 | 413 |
out.println("<?xml version=\"1.0\"?>"); |
... | ... | |
425 | 448 |
try { |
426 | 449 |
localId = im.getLocalId(guid); |
427 | 450 |
} catch (McdbDocNotFoundException e) { |
428 |
// Need to return the proper DataONE exception |
|
451 |
// TODO: Need to return the proper DataONE exception
|
|
429 | 452 |
} |
430 | 453 |
|
431 | 454 |
// Now use that localId to read the object and return it |
... | ... | |
454 | 477 |
private void query() throws Exception { |
455 | 478 |
/* This block commented out because of the EcoGrid circular dependency. |
456 | 479 |
* For now, query will not be supported until the circularity can be |
457 |
* resolved, probably by movind the ecogrid query syntax transformers
|
|
480 |
* resolved, probably by moving the ecogrid query syntax transformers
|
|
458 | 481 |
* directly into the Metacat codebase. MBJ 2010-02-03 |
459 | 482 |
|
460 | 483 |
try { |
... | ... | |
509 | 532 |
*/ |
510 | 533 |
private void putObject(String objectId) throws IOException { |
511 | 534 |
|
535 |
// TODO: This function lacks proper handling of authz and authn, so it |
|
536 |
// seems that anyone can insert or update; interacts with |
|
537 |
// loadSessinData(), which doesn't validate the session |
|
538 |
|
|
512 | 539 |
String action = request.getParameter(FUNCTION_KEYWORD); |
513 | 540 |
|
514 | 541 |
if (action.equals(FUNCTION_NAME_UPDATE) |
515 | 542 |
|| action.equals(FUNCTION_NAME_INSERT)) { |
516 |
// |
|
543 |
|
|
544 |
// Check if the objectId exists |
|
545 |
IdentifierManager im = IdentifierManager.getInstance(); |
|
546 |
if (im.identifierExists(objectId)) { |
|
547 |
// TODO: return IdentifierNotUnique exception |
|
548 |
} |
|
549 |
|
|
550 |
// TODO: For updates, need to check if the old id exists, and if not throw an exception |
|
551 |
|
|
517 | 552 |
// WARNING: This should not be a Reader if we are inserting data |
518 | 553 |
// Nor should it be read into a String |
519 | 554 |
// so this seems like a latent bug to me (MBJ; 16Mar2010) |
... | ... | |
524 | 559 |
buffer.append(line); |
525 | 560 |
} |
526 | 561 |
|
527 |
params.put("docid", new String[] { objectId }); |
|
562 |
String localId = im.generateLocalId(objectId, 1); |
|
563 |
params.put("docid", new String[] { localId }); |
|
528 | 564 |
params.put("doctext", new String[] { buffer.toString().trim() }); |
529 | 565 |
params.put("action", new String[] { action }); |
530 | 566 |
|
... | ... | |
534 | 570 |
params, username, groupNames); |
535 | 571 |
out.close(); |
536 | 572 |
} else { |
573 |
// TODO: throw exception to show lack of credentials |
|
537 | 574 |
printError("Permission denied for user " + username, response); |
538 | 575 |
|
539 | 576 |
} |
540 | 577 |
} else { |
578 |
// TODO: throw the proper exception to indicate an invalid request |
|
541 | 579 |
printError("Specifiy the operation type.(update or insert)", |
542 | 580 |
response); |
543 | 581 |
} |
src/edu/ucsb/nceas/metacat/util/DocumentUtil.java | ||
---|---|---|
28 | 28 |
|
29 | 29 |
import java.io.PrintWriter; |
30 | 30 |
import java.sql.SQLException; |
31 |
import java.util.Calendar; |
|
32 |
import java.util.Date; |
|
33 |
import java.util.GregorianCalendar; |
|
31 | 34 |
import java.util.Hashtable; |
35 |
import java.util.SimpleTimeZone; |
|
32 | 36 |
import java.util.Stack; |
37 |
import java.util.TimeZone; |
|
33 | 38 |
import java.util.Vector; |
34 | 39 |
|
35 | 40 |
import javax.servlet.http.HttpServletRequest; |
... | ... | |
60 | 65 |
|
61 | 66 |
private static Logger logMetacat = Logger.getLogger(DocumentUtil.class); |
62 | 67 |
private static char separator = '.'; |
63 |
|
|
68 |
private static String prefix = "autogen"; |
|
69 |
|
|
64 | 70 |
static { |
65 | 71 |
try { |
66 |
separator = PropertyService.getProperty("document.accNumSeparator").charAt(0); |
|
72 |
separator = PropertyService.getProperty("document.accNumSeparator").charAt(0);
|
|
67 | 73 |
} catch (PropertyNotFoundException pnfe) { |
68 |
logMetacat.error("DocumentUtil() - Could not retrieve account number separator. "
|
|
74 |
logMetacat.error("DocumentUtil() - Could not retrieve accession number separator. "
|
|
69 | 75 |
+ "Separator set to '.' : " + pnfe.getMessage()); |
70 | 76 |
} |
77 |
try { |
|
78 |
prefix = PropertyService.getProperty("document.accNumPrefix"); |
|
79 |
} catch (PropertyNotFoundException pnfe) { |
|
80 |
logMetacat.error("DocumentUtil() - Could not retrieve accession number prefix. " |
|
81 |
+ "Prefix set to " + prefix + ": " + pnfe.getMessage()); |
|
82 |
} |
|
71 | 83 |
} |
72 | 84 |
|
73 | 85 |
/** |
... | ... | |
486 | 498 |
|
487 | 499 |
out.write(result); |
488 | 500 |
} |
501 |
|
|
502 |
/** |
|
503 |
* Create a unique docid for use in inserts and updates using the default |
|
504 |
* prefix from the document.accNumPrefix property. Does not include the |
|
505 |
* 'revision' part of the id if revision is '0', otherwise sets the |
|
506 |
* revision number to 'revision'. |
|
507 |
* |
|
508 |
* @param idPrefix the prefix to be used to construct the scope portion of the docid |
|
509 |
* @param revision the integer revision to use for this docid |
|
510 |
* @return a String docid based on the current date and time |
|
511 |
*/ |
|
512 |
public static String generateDocumentId(int revision) { |
|
513 |
return generateDocumentId(prefix, revision); |
|
514 |
} |
|
515 |
|
|
516 |
/** |
|
517 |
* Create a unique docid for use in inserts and updates using the prefix |
|
518 |
* that is provided. Does not include the 'revision' part of the id if |
|
519 |
* revision is '0', otherwise sets the revision number to 'revision'. |
|
520 |
* |
|
521 |
* @param idPrefix the prefix to be used to construct the scope portion of the docid |
|
522 |
* @param revision the integer revision to use for this docid |
|
523 |
* @return a String docid based on the current date and time |
|
524 |
*/ |
|
525 |
public static String generateDocumentId(String idPrefix, int revision) |
|
526 |
{ |
|
527 |
StringBuffer docid = new StringBuffer(idPrefix); |
|
528 |
docid.append("."); |
|
489 | 529 |
|
530 |
// Create a calendar to get the date formatted properly |
|
531 |
String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000); |
|
532 |
SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]); |
|
533 |
pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000); |
|
534 |
pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000); |
|
535 |
Calendar calendar = new GregorianCalendar(pdt); |
|
536 |
Date trialTime = new Date(); |
|
537 |
calendar.setTime(trialTime); |
|
538 |
docid.append(calendar.get(Calendar.YEAR)); |
|
539 |
docid.append(calendar.get(Calendar.DAY_OF_YEAR)); |
|
540 |
docid.append(calendar.get(Calendar.HOUR_OF_DAY)); |
|
541 |
docid.append(calendar.get(Calendar.MINUTE)); |
|
542 |
docid.append(calendar.get(Calendar.SECOND)); |
|
543 |
docid.append(calendar.get(Calendar.MILLISECOND)); |
|
544 |
|
|
545 |
if (revision > 0) { |
|
546 |
docid.append(".").append(revision); |
|
547 |
} |
|
548 |
return docid.toString(); |
|
549 |
} |
|
490 | 550 |
} |
src/edu/ucsb/nceas/metacat/IdentifierManager.java | ||
---|---|---|
32 | 32 |
|
33 | 33 |
import edu.ucsb.nceas.metacat.database.DBConnection; |
34 | 34 |
import edu.ucsb.nceas.metacat.database.DBConnectionPool; |
35 |
import edu.ucsb.nceas.metacat.util.DocumentUtil; |
|
35 | 36 |
|
36 | 37 |
/** |
37 | 38 |
* Manage the relationship between Metacat local identifiers (LocalIDs) that are |
... | ... | |
186 | 187 |
DBConnectionPool.returnDBConnection(dbConn, serialNumber); |
187 | 188 |
} |
188 | 189 |
} |
190 |
|
|
191 |
/** |
|
192 |
* Given a global identifier (guid), create a suitable local identifier that |
|
193 |
* follows Metacat's docid semantics and format (scope.id.rev), and create |
|
194 |
* a mapping between these two identifiers. This effectively reserves both |
|
195 |
* the global and the local identifier, as they will now be present in the |
|
196 |
* identifier mapping table. If the incoming guid has the syntax of a |
|
197 |
* Metacat docid (scope.id.rev), then simply use it. |
|
198 |
* |
|
199 |
* @param guid the global string identifier |
|
200 |
* @param rev the revision number to be used in the localId |
|
201 |
* @return String containing the localId to be used for Metacat operations |
|
202 |
*/ |
|
203 |
public String generateLocalId(String guid, int rev) |
|
204 |
{ |
|
205 |
String localId = ""; |
|
206 |
boolean conformsToDocidFormat = false; |
|
207 |
|
|
208 |
// Check if the guid passed in is already in docid (scope.id.rev) format |
|
209 |
try { |
|
210 |
AccessionNumber acc = new AccessionNumber(guid, "NONE"); |
|
211 |
if (new Integer(acc.getRev()).intValue() > 0) { |
|
212 |
conformsToDocidFormat = true; |
|
213 |
} |
|
214 |
} catch (NumberFormatException e) { |
|
215 |
// No action needed, simply detecting invalid AccessionNumbers |
|
216 |
} catch (AccessionNumberException e) { |
|
217 |
// No action needed, simply detecting invalid AccessionNumbers |
|
218 |
} catch (SQLException e) { |
|
219 |
// No action needed, simply detecting invalid AccessionNumbers |
|
220 |
} |
|
221 |
|
|
222 |
if (conformsToDocidFormat) { |
|
223 |
// if it conforms, use it for both guid and localId |
|
224 |
localId = guid; |
|
225 |
} else { |
|
226 |
// if not, then generate a new unique localId |
|
227 |
localId = DocumentUtil.generateDocumentId(rev); |
|
228 |
} |
|
229 |
|
|
230 |
// Register this new pair in the identifier mapping table |
|
231 |
createMapping(guid, localId); |
|
232 |
|
|
233 |
return localId; |
|
234 |
} |
|
189 | 235 |
} |
Also available in: Unified diff
Added support to ResourceHandler to allow the putObject method to use
arbitrary guid strings as input. These strings are examined, and if they
match the Metacat docid format (scope.id.rev), they are used directly. If
the id is a string in another format, a new localId is generated based on
the current time. Either way, a mapping is made into the identifier table
to relate the original guid to the new localId. Modified DocumentUtil to
generate the ids, and MCTest case to use this new utility method (to stay DRY).
Tests were updated to expect these global identifiers in the putObject
method.