Revision 5319
Added by Matt Jones almost 14 years ago
ResourceHandler.java | ||
---|---|---|
23 | 23 |
package edu.ucsb.nceas.metacat.restservice; |
24 | 24 |
|
25 | 25 |
import java.io.BufferedReader; |
26 |
import java.io.File; |
|
27 |
import java.io.FileNotFoundException; |
|
28 |
import java.io.FileOutputStream; |
|
26 | 29 |
import java.io.IOException; |
27 | 30 |
import java.io.InputStream; |
31 |
import java.io.OutputStream; |
|
28 | 32 |
import java.io.PrintWriter; |
29 | 33 |
import java.util.Enumeration; |
30 | 34 |
import java.util.Hashtable; |
31 | 35 |
import java.util.Timer; |
32 | 36 |
|
37 |
import javax.mail.BodyPart; |
|
38 |
import javax.mail.MessagingException; |
|
39 |
import javax.mail.internet.MimeMultipart; |
|
33 | 40 |
import javax.servlet.ServletContext; |
34 | 41 |
import javax.servlet.http.HttpServletRequest; |
35 | 42 |
import javax.servlet.http.HttpServletResponse; |
... | ... | |
37 | 44 |
import org.apache.commons.io.IOUtils; |
38 | 45 |
import org.apache.log4j.Logger; |
39 | 46 |
import org.dataone.service.exceptions.BaseException; |
47 |
import org.dataone.service.exceptions.IdentifierNotUnique; |
|
48 |
import org.dataone.service.exceptions.InsufficientResources; |
|
49 |
import org.dataone.service.exceptions.InvalidRequest; |
|
50 |
import org.dataone.service.exceptions.InvalidSystemMetadata; |
|
51 |
import org.dataone.service.exceptions.InvalidToken; |
|
52 |
import org.dataone.service.exceptions.NotAuthorized; |
|
53 |
import org.dataone.service.exceptions.NotImplemented; |
|
40 | 54 |
import org.dataone.service.exceptions.ServiceFailure; |
55 |
import org.dataone.service.exceptions.UnsupportedType; |
|
41 | 56 |
import org.dataone.service.types.AuthToken; |
42 | 57 |
import org.dataone.service.types.IdentifierType; |
58 |
import org.dataone.service.types.SystemMetadata; |
|
59 |
import org.exolab.castor.jdo.conf.DataSource; |
|
43 | 60 |
|
44 | 61 |
import edu.ucsb.nceas.metacat.DBUtil; |
45 | 62 |
import edu.ucsb.nceas.metacat.IdentifierManager; |
... | ... | |
280 | 297 |
status = true; |
281 | 298 |
} |
282 | 299 |
} else if (resource.equals(RESOURCE_OBJECTS)) { |
283 |
|
|
300 |
logMetacat.debug("D1 Rest: Starting resource processing..."); |
|
284 | 301 |
loadSessionData(); |
285 | 302 |
|
286 | 303 |
String objectId = request.getPathInfo(); |
287 | 304 |
if (objectId != null && objectId.length() > 1) |
288 | 305 |
objectId = request.getPathInfo().substring(1); //trim the slash |
306 |
logMetacat.debug("Processing objectId: " + objectId); |
|
307 |
logMetacat.debug("verb:" + httpVerb); |
|
289 | 308 |
|
290 |
System.out.println("verb:" + httpVerb);
|
|
309 |
logMetacat.debug("objectId:" + objectId);
|
|
291 | 310 |
|
292 |
System.out.println("objectId:" + objectId); |
|
293 |
|
|
294 | 311 |
if (httpVerb == GET) { |
295 | 312 |
getObject(objectId); |
296 | 313 |
status = true; |
297 | 314 |
} else if (httpVerb == POST) { |
298 |
query();
|
|
315 |
putObject(objectId, FUNCTION_NAME_INSERT);
|
|
299 | 316 |
status = true; |
300 | 317 |
} else if (httpVerb == PUT) { |
301 |
putObject(objectId); |
|
318 |
putObject(objectId, FUNCTION_NAME_UPDATE);
|
|
302 | 319 |
status = true; |
303 | 320 |
} else if (httpVerb == DELETE) { |
304 | 321 |
deleteObject(objectId); |
... | ... | |
450 | 467 |
private void getObject(String guid) { |
451 | 468 |
CrudService cs = new CrudService(servletContext, request, response); |
452 | 469 |
AuthToken token = null; |
470 |
OutputStream out = null; |
|
453 | 471 |
try { |
472 |
out = response.getOutputStream(); |
|
454 | 473 |
InputStream data = cs.get(token, new IdentifierType(guid)); |
455 | 474 |
IOUtils.copyLarge(data, response.getOutputStream()); |
456 | 475 |
} catch (BaseException e) { |
457 |
response.setContentType("text/xml"); |
|
458 |
response.setStatus(e.getCode()); |
|
459 |
// TODO: Use content negotiation to determine which return format to use |
|
460 |
try { |
|
461 |
IOUtils.write(e.serialize(BaseException.FMT_XML), |
|
462 |
response.getOutputStream()); |
|
463 |
} catch (IOException e1) { |
|
464 |
logMetacat.error("Error writing exception to stream. " |
|
465 |
+ e1.getMessage()); |
|
466 |
} |
|
476 |
serializeException(e, out); |
|
467 | 477 |
} catch (IOException e) { |
468 | 478 |
ServiceFailure sf = new ServiceFailure(1030, e.getMessage()); |
469 |
response.setContentType("text/xml"); |
|
470 |
response.setStatus(sf.getCode()); |
|
471 |
try { |
|
472 |
IOUtils.write(sf.serialize(BaseException.FMT_XML), |
|
473 |
response.getOutputStream()); |
|
474 |
} catch (IOException e1) { |
|
475 |
logMetacat.error("Error writing service exception to stream. " |
|
476 |
+ e1.getMessage()); |
|
477 |
} |
|
479 |
serializeException(sf, out); |
|
478 | 480 |
} |
479 | 481 |
} |
480 | 482 |
|
... | ... | |
544 | 546 |
out.print("<error>Query operation not yet supported by Metacat.</error>"); |
545 | 547 |
out.close(); |
546 | 548 |
} |
547 |
|
|
549 |
|
|
548 | 550 |
/** |
549 | 551 |
* Earthgrid API > Put Service >Put Function : calls MetacatHandler > handleInsertOrUpdateAction |
550 | 552 |
* |
551 |
* @param objectId ID of data object to be inserted or updated
|
|
553 |
* @param guid ID of data object to be inserted or updated
|
|
552 | 554 |
* @throws IOException |
553 | 555 |
*/ |
554 |
private void putObject(String objectId) throws IOException { |
|
555 |
|
|
556 |
private void putObject(String guid, String action) { |
|
557 |
logMetacat.debug("Entering putObject: " + guid + "/" + action); |
|
558 |
|
|
556 | 559 |
// TODO: This function lacks proper handling of authz and authn, so it |
557 | 560 |
// seems that anyone can insert or update; interacts with |
558 |
// loadSessinData(), which doesn't validate the session |
|
561 |
// loadSessionData(), which doesn't validate the session
|
|
559 | 562 |
|
560 |
String action = request.getParameter(FUNCTION_KEYWORD); |
|
563 |
// Get an output stream for handling errors; this should really be passed in as |
|
564 |
// a parameter |
|
565 |
OutputStream out = null; |
|
566 |
try { |
|
567 |
out = response.getOutputStream(); |
|
568 |
} catch (IOException e1) { |
|
569 |
logMetacat.error("Could not get the output stream for writing in putObject"); |
|
570 |
} |
|
571 |
try { |
|
572 |
if (action.equals(FUNCTION_NAME_UPDATE) |
|
573 |
|| action.equals(FUNCTION_NAME_INSERT)) { |
|
561 | 574 |
|
562 |
if (action.equals(FUNCTION_NAME_UPDATE) |
|
563 |
|| action.equals(FUNCTION_NAME_INSERT)) { |
|
564 |
|
|
565 |
// Check if the objectId exists |
|
566 |
IdentifierManager im = IdentifierManager.getInstance(); |
|
567 |
if (im.identifierExists(objectId)) { |
|
568 |
// TODO: return IdentifierNotUnique exception |
|
569 |
} |
|
570 |
|
|
571 |
// TODO: For updates, need to check if the old id exists, and if not throw an exception |
|
572 |
|
|
573 |
// WARNING: This should not be a Reader if we are inserting data |
|
574 |
// Nor should it be read into a String |
|
575 |
// so this seems like a latent bug to me (MBJ; 16Mar2010) |
|
576 |
BufferedReader reader = request.getReader(); |
|
577 |
StringBuffer buffer = new StringBuffer(); |
|
578 |
String line = null; |
|
579 |
while ((line = reader.readLine()) != null) { |
|
580 |
buffer.append(line); |
|
581 |
} |
|
575 |
// Check if the objectId exists |
|
576 |
IdentifierManager im = IdentifierManager.getInstance(); |
|
577 |
if (im.identifierExists(guid)) { |
|
578 |
throw new IdentifierNotUnique(1000, "Identifier is already in use: " + guid); |
|
579 |
} |
|
582 | 580 |
|
583 |
String localId = im.generateLocalId(objectId, 1); |
|
584 |
params.put("docid", new String[] { localId }); |
|
585 |
params.put("doctext", new String[] { buffer.toString().trim() }); |
|
586 |
params.put("action", new String[] { action }); |
|
581 |
// TODO: For updates, need to check if the old id exists, and if not throw an exception |
|
587 | 582 |
|
588 |
if (username != null && !username.equals("public")) { |
|
589 |
PrintWriter out = response.getWriter(); |
|
590 |
handler.handleInsertOrUpdateAction(request, response, out, |
|
591 |
params, username, groupNames); |
|
592 |
out.close(); |
|
583 |
// TODO: Change this to read the MIME forms that are created |
|
584 |
logMetacat.debug("Disassembling MIME multipart form"); |
|
585 |
InputStream object = null; |
|
586 |
InputStream sysmeta = null; |
|
587 |
MimeMultipart mmp = new MimeMultipart(new InputStreamDataSource("message", request.getInputStream())); |
|
588 |
logMetacat.debug("MMP created."); |
|
589 |
mmp.writeTo(System.out); |
|
590 |
for (int i = 0; i < mmp.getCount(); i++) { |
|
591 |
logMetacat.debug("Looping over MMP parts: " + i); |
|
592 |
BodyPart part = mmp.getBodyPart(i); |
|
593 |
String name = part.getFileName(); |
|
594 |
logMetacat.debug("Part name is: " + name); |
|
595 |
logMetacat.debug("Part has class name: " + part.getClass().getName()); |
|
596 |
if (name.equals("object")) { |
|
597 |
object = part.getInputStream(); |
|
598 |
logMetacat.debug("Found object part, size is: " + part.getSize()); |
|
599 |
} else if (name.equals("systemmetadata")) { |
|
600 |
sysmeta = part.getInputStream(); |
|
601 |
logMetacat.debug("Found sysmeta part, size is: " + part.getSize()); |
|
602 |
} else { |
|
603 |
throw new InvalidRequest(1000, "Request had malformed MIME part with name: " + name); |
|
604 |
} |
|
605 |
} |
|
606 |
|
|
607 |
//if (username != null && !username.equals("public")) { |
|
608 |
if (username != null) { |
|
609 |
|
|
610 |
logMetacat.debug("Commence creation..."); |
|
611 |
AuthToken token = null; |
|
612 |
SystemMetadata m = new SystemMetadata(sysmeta); |
|
613 |
logMetacat.debug(m.serialize(SystemMetadata.FMT_XML)); |
|
614 |
//IOUtils.copy(object, System.out); |
|
615 |
// byte[] b = new byte[2048]; |
|
616 |
// int len = object.read(b); |
|
617 |
// logMetacat.debug("Read " + len + " bytes from object: " + new String(b)); |
|
618 |
CrudService cs = new CrudService(servletContext, request, response); |
|
619 |
cs.create(token, new IdentifierType(guid), object, m); |
|
620 |
|
|
621 |
} else { |
|
622 |
logMetacat.debug("Unauthorized to create."); |
|
623 |
throw new NotAuthorized(1000, "Permission denied for user " + username); |
|
624 |
} |
|
593 | 625 |
} else { |
594 |
// TODO: throw exception to show lack of credentials |
|
595 |
printError("Permission denied for user " + username, response); |
|
596 |
|
|
626 |
throw new InvalidRequest(1000, "Operation must be create or update."); |
|
597 | 627 |
} |
598 |
} else { |
|
599 |
// TODO: throw the proper exception to indicate an invalid request |
|
600 |
printError("Specifiy the operation type.(update or insert)", |
|
601 |
response); |
|
628 |
} catch (NotAuthorized e) { |
|
629 |
serializeException(e, out); |
|
630 |
} catch (InvalidToken e) { |
|
631 |
serializeException(e, out); |
|
632 |
} catch (ServiceFailure e) { |
|
633 |
serializeException(e, out); |
|
634 |
} catch (IdentifierNotUnique e) { |
|
635 |
serializeException(e, out); |
|
636 |
} catch (UnsupportedType e) { |
|
637 |
serializeException(e, out); |
|
638 |
} catch (InsufficientResources e) { |
|
639 |
serializeException(e, out); |
|
640 |
} catch (InvalidSystemMetadata e) { |
|
641 |
serializeException(e, out); |
|
642 |
} catch (NotImplemented e) { |
|
643 |
serializeException(e, out); |
|
644 |
} catch (InvalidRequest e) { |
|
645 |
serializeException(e, out); |
|
646 |
} catch (MessagingException e) { |
|
647 |
ServiceFailure sf = new ServiceFailure(1000, e.getMessage()); |
|
648 |
serializeException(sf, out); |
|
649 |
} catch (IOException e) { |
|
650 |
ServiceFailure sf = new ServiceFailure(1000, e.getMessage()); |
|
651 |
serializeException(sf, out); |
|
602 | 652 |
} |
603 |
|
|
604 | 653 |
} |
605 | 654 |
|
606 | 655 |
/** |
... | ... | |
668 | 717 |
} |
669 | 718 |
} |
670 | 719 |
|
720 |
private void serializeException(BaseException e, OutputStream out) { |
|
721 |
// TODO: Use content negotiation to determine which return format to use |
|
722 |
response.setContentType("text/xml"); |
|
723 |
response.setStatus(e.getCode()); |
|
724 |
try { |
|
725 |
IOUtils.write(e.serialize(BaseException.FMT_XML), out); |
|
726 |
} catch (IOException e1) { |
|
727 |
logMetacat.error("Error writing exception to stream. " |
|
728 |
+ e1.getMessage()); |
|
729 |
} |
|
730 |
} |
|
731 |
|
|
671 | 732 |
} |
Also available in: Unified diff
Modifications to support the DataONE service API version 0.1.0. For DataONE, the get() and
create() services are partially complete. Several more functions and checks need to be added to
create() before it is viable. This DataONE support is not complete, and the current support breaks the MetacatRestClientTest for the time being (this client will eventually be removed).