Project

General

Profile

« Previous | Next » 

Revision 5298

Added by Matt Jones about 14 years ago

Modified readFromMetacat() to pass most exceptions up the call stack, which
allows creation of new entry points for calling reads. Still need to
continue factoring out the HTTPServletResponse that is passed in in order to
make entrypoints that are not servlet based possible. Problem now is in
setting the content type properly on the servlet response before writing to
the output stream.

Added new dataone interface implementation for the CRUD service, but it is incomplete -- most interfaces thrown NotImplemented for now . The get() method should work but is not tested.

View differences:

MetacatHandler.java
29 29
import java.io.FileInputStream;
30 30
import java.io.FileReader;
31 31
import java.io.IOException;
32
import java.io.OutputStream;
32 33
import java.io.OutputStreamWriter;
33 34
import java.io.PrintWriter;
34 35
import java.io.StringReader;
......
71 72
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
72 73
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlInterface;
73 74
import edu.ucsb.nceas.metacat.cart.CartManager;
75
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
74 76
import edu.ucsb.nceas.metacat.database.DBConnection;
75 77
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
76 78
import edu.ucsb.nceas.metacat.dataquery.DataQuery;
......
720 722
            String[] docs = new String[0];
721 723
            String docid = "";
722 724
            String qformat = "";
723
            String abstrpath = null;
724 725
            
725 726
            // read the params
726 727
            if (params.containsKey("docid")) {
......
763 764
                        if (zip) {
764 765
                            addDocToZip(request, docid, providedFileName, zout, user, groups);
765 766
                        } else {
766
                            readFromMetacat(request, response, docid, qformat,
767
                                    abstrpath, user, groups, zip, zout,
768
                                    withInlineData, params);
767
                            readFromMetacat(request.getRemoteAddr(), response, response.getOutputStream(), docid, qformat,
768
                                    user, groups, withInlineData, params);
769 769
                        }
770 770
                        
771 771
                        // case docid="http://.../filename"
......
783 783
                    if (zip) {
784 784
                        addDocToZip(request, docid, providedFileName, zout, user, groups);
785 785
                    } else {
786
                        readFromMetacat(request, response, docid, qformat,
787
                                abstrpath, user, groups, zip, zout,
788
                                withInlineData, params);
786
                        readFromMetacat(request.getRemoteAddr(), response, response.getOutputStream(), docid, qformat,
787
                                user, groups, withInlineData, params);
789 788
                    }
790 789
                }
791 790
            }
......
896 895
    }
897 896
    
898 897
    /** read metadata or data from Metacat
898
     * @throws PropertyNotFoundException 
899
     * @throws ParseLSIDException 
900
     * @throws InsufficientKarmaException 
899 901
     */
900
    private void readFromMetacat(HttpServletRequest request,
901
            HttpServletResponse response, String docid, String qformat,
902
            String abstrpath, String user, String[] groups, boolean zip,
903
            ZipOutputStream zout, boolean withInlineData, Hashtable<String, String[]> params)
904
            throws ClassNotFoundException, IOException, SQLException,
905
            McdbException, Exception {
902
    public void readFromMetacat(String ipAddress,
903
            HttpServletResponse response, OutputStream out, String docid, String qformat,
904
            String user, String[] groups, boolean withInlineData, 
905
            Hashtable<String, String[]> params) throws ClassNotFoundException, 
906
            IOException, SQLException, McdbException, PropertyNotFoundException, 
907
            ParseLSIDException, InsufficientKarmaException {
906 908
        
907
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
909
        Logger logMetacat = Logger.getLogger(MetacatHandler.class);
908 910
        try {
909 911
            
910 912
            if (docid.startsWith("urn:")) {
......
923 925
            
924 926
            //check the permission for read
925 927
            if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
926
                Exception e = new Exception("User " + user
928
                InsufficientKarmaException e = new InsufficientKarmaException("User " + user
927 929
                        + " does not have permission"
928 930
                        + " to read the document with the docid " + docid);
929
                
930 931
                throw e;
931 932
            }
932 933
            
933 934
            if (doc.getRootNodeID() == 0) {
934
                // this is data file
935
                // this is data file, so find the path on disk for the file
935 936
                String filepath = PropertyService.getProperty("application.datafilepath");
936 937
                if (!filepath.endsWith("/")) {
937 938
                    filepath += "/";
......
940 941
                FileInputStream fin = null;
941 942
                fin = new FileInputStream(filename);
942 943
                
943
                //MIME type
944
                String contentType = servletContext.getMimeType(filename);
945
                if (contentType == null) {
946
                    ContentTypeProvider provider = new ContentTypeProvider(
947
                            docid);
948
                    contentType = provider.getContentType();
949
                    logMetacat.info("MetaCatServlet.readFromMetacat - Final contenttype is: "
950
                            + contentType);
951
                }
952
                
953
                response.setContentType(contentType);
954
                // if we decide to use "application/octet-stream" for all data
955
                // returns
956
                // response.setContentType("application/octet-stream");
944
                if (response != null) {
945
                    // MIME type
946
                    String contentType = servletContext.getMimeType(filename);
947
                    if (contentType == null) {
948
                        ContentTypeProvider provider = new ContentTypeProvider(
949
                                docid);
950
                        contentType = provider.getContentType();
951
                        logMetacat.info("MetaCatServlet.readFromMetacat - Final contenttype is: "
952
                                + contentType);
953
                    }
954
                    response.setContentType(contentType);
957 955

  
958
                // check for the existence of a metadatadocid parameter,
959
                // if this is sent, then send a filename which contains both
960
                // the metadata docid and the data docid, so the link with
961
                // metadata is explicitly encoded in the filename.
962
                String metadatadocid = null;
963
                Vector<String> nameparts = new Vector<String>();
964

  
965
                if(params.containsKey("metadatadocid")) {
966
                    metadatadocid = params.get("metadatadocid")[0];
956
                    // Set the output filename on the response
957
                    String outputname = generateOutputName(docid, params, doc);                    
958
                    response.setHeader("Content-Disposition",
959
                            "attachment; filename=\"" + outputname + "\"");
967 960
                }
968
                if (metadatadocid != null && !metadatadocid.equals("")) {
969
                    nameparts.add(metadatadocid);
970
                }
971
                // we'll always have the docid, include it in the name
972
                String doctype = doc.getDoctype();
973
                                // TODO: fix this to lookup the associated FGDC metadata document,
974
                                // and grab the doctype tag for it.  These should be set to something 
975
                                // consistent, not 'metadata' as it stands...
976
                //if (!doctype.equals("metadata")) {
977
                //    nameparts.add(docid);
978
                //} 
979
                                nameparts.add(docid);
980
                // Set the name of the data file to the entity name plus docid,
981
                // or if that is unavailable, use the docid alone
982
                String docname = doc.getDocname();
983
                if (docname != null && !docname.equals("")) {
984
                    nameparts.add(docname); 
985
                }
986
                // combine the name elements with a dash, using a 'join' equivalent
987
                String outputname = null;
988
                String delimiter = "-";
989
                Iterator<String> iter = nameparts.iterator();
990
                StringBuffer buffer = new StringBuffer(iter.next());
991
                while (iter.hasNext()) buffer.append(delimiter).append(iter.next());
992
                outputname = buffer.toString();    
993 961
                
994
                response.setHeader("Content-Disposition",
995
                        "attachment; filename=\"" + outputname + "\"");
996
                
962
                // Write the data to the output stream
997 963
                try {
998
                    ServletOutputStream out = response.getOutputStream();
999 964
                    byte[] buf = new byte[4 * 1024]; // 4K buffer
1000 965
                    int b = fin.read(buf);
1001 966
                    while (b != -1) {
......
1008 973
                
1009 974
            } else {
1010 975
                // this is metadata doc
1011
                ServletOutputStream streamOut = response.getOutputStream();
1012 976
                if (qformat.equals("xml") || qformat.equals("")) {
1013 977
                    // if equals "", that means no qformat is specified. hence
1014 978
                    // by default the document should be returned in xml format
1015 979
                    // set content type first
1016
                    response.setContentType("text/xml"); //MIME type
1017
                    response.setHeader("Content-Disposition",
1018
                            "attachment; filename=" + docid + ".xml");
1019 980
                    
981
                    if (response != null) {
982
                        response.setContentType("text/xml"); //MIME type
983
                        response.setHeader("Content-Disposition",
984
                                "attachment; filename=" + docid + ".xml");
985
                    }
986
                    
1020 987
                    // Try to get the metadata file from disk. If it isn't
1021 988
                    // found, create it from the db and write it to disk then.
1022 989
                    try {
1023
                        PrintWriter out = new PrintWriter(streamOut);
1024
                        doc.toXml(out, user, groups, withInlineData);               
1025
                    } catch (Exception e) {
990
                        PrintWriter pw = new PrintWriter(out);
991
                        doc.toXml(pw, user, groups, withInlineData);               
992
                    } catch (McdbException e) {
1026 993
                        // any exceptions in reading the xml from disc, and we go back to the
1027 994
                        // old way of creating the xml directly.
1028 995
                        logMetacat.error("MetaCatServlet.readFromMetacat - could not read from document file " + docid 
1029 996
                                + ": " + e.getMessage());
1030
                        PrintWriter out = new PrintWriter(streamOut);
1031
                        doc.toXmlFromDb(out, user, groups, withInlineData);
997
                        PrintWriter pw = new PrintWriter(out);
998
                        doc.toXmlFromDb(pw, user, groups, withInlineData);
1032 999
                    }
1033 1000
                } else {
1034 1001
                    // TODO MCD, this should read from disk as well?
......
1041 1008
                            params.put("publicRead", new String[] {"false"});
1042 1009
                    }
1043 1010
                    
1044
                    response.setContentType("text/html"); //MIME type
1045
                    PrintWriter out = new PrintWriter(streamOut);
1011
                    if (response != null) {
1012
                        response.setContentType("text/html"); //MIME type
1013
                    }
1046 1014
                    
1015
                    PrintWriter pw = new PrintWriter(out);
1016
                    
1047 1017
                    // Look up the document type
1048 1018
                    String doctype = doc.getDoctype();
1049 1019
                    // Transform the document to the new doctype
1050 1020
                    DBTransform dbt = new DBTransform();
1051 1021
                    dbt.transformXMLDocument(doc.toString(user, groups,
1052 1022
                            withInlineData), doctype, "-//W3C//HTML//EN",
1053
                            qformat, out, params, null);
1023
                            qformat, pw, params, null);
1054 1024
                }
1055 1025
                
1056 1026
            }
1057
            EventLog.getInstance().log(request.getRemoteAddr(), user,
1058
                    docid, "read");
1059
        } catch (Exception except) {
1027
            EventLog.getInstance().log(ipAddress, user, docid, "read");
1028
        } catch (PropertyNotFoundException except) {
1060 1029
            throw except;
1061 1030
        }
1062 1031
    }
1032

  
1033
    /**
1034
     * Create a filename to be used for naming a downloaded document
1035
     * @param docid the identifier of the document to be named
1036
     * @param params the parameters of the request
1037
     * @param doc the DocumentImpl of the document to be named
1038
     * @return String containing a name for the download
1039
     */
1040
    private String generateOutputName(String docid,
1041
            Hashtable<String, String[]> params, DocumentImpl doc) {
1042
        String outputname = null;
1043
        // check for the existence of a metadatadocid parameter,
1044
        // if this is sent, then send a filename which contains both
1045
        // the metadata docid and the data docid, so the link with
1046
        // metadata is explicitly encoded in the filename.
1047
        String metadatadocid = null;
1048
        Vector<String> nameparts = new Vector<String>();
1049

  
1050
        if(params.containsKey("metadatadocid")) {
1051
            metadatadocid = params.get("metadatadocid")[0];
1052
        }
1053
        if (metadatadocid != null && !metadatadocid.equals("")) {
1054
            nameparts.add(metadatadocid);
1055
        }
1056
        // we'll always have the docid, include it in the name
1057
        String doctype = doc.getDoctype();
1058
        // TODO: fix this to lookup the associated FGDC metadata document,
1059
        // and grab the doctype tag for it.  These should be set to something 
1060
        // consistent, not 'metadata' as it stands...
1061
        //if (!doctype.equals("metadata")) {
1062
        //    nameparts.add(docid);
1063
        //} 
1064
        nameparts.add(docid);
1065
        // Set the name of the data file to the entity name plus docid,
1066
        // or if that is unavailable, use the docid alone
1067
        String docname = doc.getDocname();
1068
        if (docname != null && !docname.equals("")) {
1069
            nameparts.add(docname); 
1070
        }
1071
        // combine the name elements with a dash, using a 'join' equivalent
1072
        String delimiter = "-";
1073
        Iterator<String> iter = nameparts.iterator();
1074
        StringBuffer buffer = new StringBuffer(iter.next());
1075
        while (iter.hasNext()) buffer.append(delimiter).append(iter.next());
1076
        outputname = buffer.toString();
1077
        return outputname;
1078
    }
1063 1079
    
1064 1080
    /**
1065 1081
     * read data from URLConnection
......
2796 2812
     * If the given docid only have one seperter, we need
2797 2813
     * append rev for it. The rev come from xml_documents
2798 2814
     */
2799
    private static String appendRev(String docid) throws Exception {
2815
    private static String appendRev(String docid) throws PropertyNotFoundException, SQLException, McdbDocNotFoundException {
2800 2816
//        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2801 2817
        String newAccNum = null;
2802 2818
        String separator = PropertyService.getProperty("document.accNumSeparator");
......
2807 2823
            //only one seperater
2808 2824
            int rev = DBUtil.getLatestRevisionInDocumentTable(docid);
2809 2825
            if (rev == -1) {
2810
                throw new Exception("the requested docid '"
2826
                throw new McdbDocNotFoundException("the requested docid '"
2811 2827
                        + docid+ "' does not exist");
2812 2828
            } else {
2813 2829
                newAccNum = docid+ separator+ rev;

Also available in: Unified diff