Project

General

Profile

« Previous | Next » 

Revision 5319

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).

View differences:

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