Revision 5298
Added by Matt Jones over 14 years ago
src/edu/ucsb/nceas/metacat/PermissionController.java | ||
---|---|---|
231 | 231 |
*/ |
232 | 232 |
private boolean hasPermissionForInlineData(String user, String[] groups, |
233 | 233 |
String myPermission, String inlineDataId) |
234 |
throws Exception
|
|
234 |
throws McdbException
|
|
235 | 235 |
{ |
236 | 236 |
// this method can call the public method - hasPermission(...) |
237 | 237 |
// the only difference is about the ownership, you couldn't find the owner |
238 | 238 |
// from inlinedataId directly. You should get it from eml document itself |
239 | 239 |
String []userPackage = createUsersPackage(user, groups); |
240 |
if (containDocumentOwner(userPackage, docId)) |
|
241 |
{ |
|
242 |
return true; |
|
243 |
} |
|
244 |
else |
|
245 |
{ |
|
246 |
PermissionController controller = |
|
247 |
new PermissionController(inlineDataId, false); |
|
248 |
return controller.hasPermission(user, groups, myPermission); |
|
249 |
} |
|
240 |
try { |
|
241 |
if (containDocumentOwner(userPackage, docId)) |
|
242 |
{ |
|
243 |
return true; |
|
244 |
} |
|
245 |
else |
|
246 |
{ |
|
247 |
PermissionController controller = |
|
248 |
new PermissionController(inlineDataId, false); |
|
249 |
return controller.hasPermission(user, groups, myPermission); |
|
250 |
} |
|
251 |
} catch (SQLException e) { |
|
252 |
throw new McdbException(e.getMessage()); |
|
253 |
} |
|
250 | 254 |
} |
251 | 255 |
|
252 | 256 |
/** |
... | ... | |
964 | 968 |
public static Hashtable<String, String> getUnReadableInlineDataIdList(String docidWithoutRev, |
965 | 969 |
String user, String[] groups, |
966 | 970 |
boolean withRevision) |
967 |
throws Exception |
|
971 |
throws McdbException
|
|
968 | 972 |
{ |
969 | 973 |
Hashtable<String, String> inlineDataList = getUnAccessableInlineDataIdList(docidWithoutRev, |
970 | 974 |
user, groups, AccessControlInterface.READSTRING, |
... | ... | |
1007 | 1011 |
private static Hashtable<String, String> getUnAccessableInlineDataIdList(String docid, |
1008 | 1012 |
String user, String[] groups, String permission, |
1009 | 1013 |
boolean withRevision) |
1010 |
throws SQLException,McdbException, Exception
|
|
1014 |
throws McdbException
|
|
1011 | 1015 |
{ |
1012 |
Hashtable<String, String> unAccessibleIdList = new Hashtable(); |
|
1013 |
if (user == null) { |
|
1014 |
return unAccessibleIdList; |
|
1015 |
} |
|
1016 |
|
|
1017 |
Hashtable allIdList = getAllInlineDataIdList(docid); |
|
1018 |
Enumeration<String> en = allIdList.keys(); |
|
1016 |
Hashtable<String, String> unAccessibleIdList = new Hashtable(); |
|
1017 |
if (user == null) { |
|
1018 |
return unAccessibleIdList; |
|
1019 |
} |
|
1020 |
|
|
1021 |
Hashtable allIdList; |
|
1022 |
try { |
|
1023 |
allIdList = getAllInlineDataIdList(docid); |
|
1024 |
} catch (SQLException e) { |
|
1025 |
throw new McdbException(e.getMessage()); |
|
1026 |
} |
|
1027 |
Enumeration<String> en = allIdList.keys(); |
|
1019 | 1028 |
while (en.hasMoreElements()) |
1020 | 1029 |
{ |
1021 | 1030 |
String subTreeId = (String) en.nextElement(); |
src/edu/ucsb/nceas/metacat/DocumentImpl.java | ||
---|---|---|
1357 | 1357 |
|
1358 | 1358 |
String xmlFileContents = ""; |
1359 | 1359 |
|
1360 |
try { |
|
1361 |
xmlFileContents = FileUtil.readFileToString(documentPath); |
|
1360 |
try { |
|
1361 |
xmlFileContents = FileUtil.readFileToString(documentPath); |
|
1362 |
|
|
1362 | 1363 |
|
1363 | 1364 |
// get a list of inline data sections that are not readable |
1364 | 1365 |
// by this user |
... | ... | |
1395 | 1396 |
pw.write(xmlFileContents); |
1396 | 1397 |
pw.close(); |
1397 | 1398 |
|
1398 |
|
|
1399 |
} catch (Exception e) {
|
|
1400 |
throw new McdbException("Error reading document " + documentPath
|
|
1401 |
+ " from disk: " + e.getMessage());
|
|
1399 |
} catch (UtilException e) { |
|
1400 |
throw new McdbException(e.getMessage());
|
|
1401 |
} catch (IOException e) {
|
|
1402 |
throw new McdbException(e.getMessage());
|
|
1402 | 1403 |
} |
1403 |
|
|
1404 | 1404 |
} |
1405 | 1405 |
|
1406 | 1406 |
/** |
... | ... | |
1465 | 1465 |
* the unique key for this inline element |
1466 | 1466 |
*/ |
1467 | 1467 |
private String stripInline20XData(String xmlFileContents, String inLineId) |
1468 |
throws Exception { |
|
1468 |
throws McdbException {
|
|
1469 | 1469 |
String changedString = xmlFileContents; |
1470 | 1470 |
|
1471 | 1471 |
Pattern distStartPattern = Pattern.compile("<distribution", Pattern.CASE_INSENSITIVE); |
... | ... | |
1483 | 1483 |
// find the index of the corresponding end element |
1484 | 1484 |
int distStart = distStartMatcher.end(); |
1485 | 1485 |
if (!distEndMatcher.find(distStart)) { |
1486 |
throw new Exception("Could not find end tag for distribution"); |
|
1486 |
throw new McdbException("Could not find end tag for distribution");
|
|
1487 | 1487 |
} |
1488 | 1488 |
int distEnd = distEndMatcher.start(); |
1489 | 1489 |
|
... | ... | |
1516 | 1516 |
* @param inLineKey |
1517 | 1517 |
* the unique key for this inline element |
1518 | 1518 |
*/ |
1519 |
private String stripInline21XData(String xmlFileContents, String inLineId) throws Exception { |
|
1519 |
private String stripInline21XData(String xmlFileContents, String inLineId) throws McdbException {
|
|
1520 | 1520 |
int distributionIndex = Integer.valueOf(inLineId); |
1521 | 1521 |
String changedString = xmlFileContents; |
1522 | 1522 |
Pattern distStartPattern = Pattern.compile("<distribution", Pattern.CASE_INSENSITIVE); |
... | ... | |
1529 | 1529 |
// to set the start range we will search for the inline element. |
1530 | 1530 |
for (int i = 0; i < distributionIndex; i++) { |
1531 | 1531 |
if (!matcher.find()) { |
1532 |
throw new Exception("Could not find distribution number " + (i + 1)); |
|
1532 |
throw new McdbException("Could not find distribution number " + (i + 1));
|
|
1533 | 1533 |
} |
1534 | 1534 |
} |
1535 | 1535 |
int distStart = matcher.end(); |
... | ... | |
1538 | 1538 |
// the end range we will search for the inline element |
1539 | 1539 |
matcher.usePattern(distEndPattern); |
1540 | 1540 |
if (!matcher.find(distStart)) { |
1541 |
throw new Exception("Could not find end tag for distribution"); |
|
1541 |
throw new McdbException("Could not find end tag for distribution");
|
|
1542 | 1542 |
} |
1543 | 1543 |
int distEnd = matcher.start(); |
1544 | 1544 |
|
src/edu/ucsb/nceas/metacat/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; |
src/edu/ucsb/nceas/metacat/dataone/CrudService.java | ||
---|---|---|
1 |
/** |
|
2 |
* '$RCSfile$' |
|
3 |
* Copyright: 2000 Regents of the University of California and the |
|
4 |
* National Center for Ecological Analysis and Synthesis |
|
5 |
* |
|
6 |
* '$Author: Serhan AKIN $' |
|
7 |
* '$Date: 2009-06-13 15:28:13 +0300 $' |
|
8 |
* |
|
9 |
* This program is free software; you can redistribute it and/or modify |
|
10 |
* it under the terms of the GNU General Public License as published by |
|
11 |
* the Free Software Foundation; either version 2 of the License, or |
|
12 |
* (at your option) any later version. |
|
13 |
* |
|
14 |
* This program is distributed in the hope that it will be useful, |
|
15 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
16 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
17 |
* GNU General Public License for more details. |
|
18 |
* |
|
19 |
* You should have received a copy of the GNU General Public License |
|
20 |
* along with this program; if not, write to the Free Software |
|
21 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
22 |
*/ |
|
23 |
package edu.ucsb.nceas.metacat.dataone; |
|
24 |
|
|
25 |
import java.io.IOException; |
|
26 |
import java.io.InputStream; |
|
27 |
import java.io.OutputStream; |
|
28 |
import java.sql.SQLException; |
|
29 |
import java.util.Date; |
|
30 |
import java.util.Enumeration; |
|
31 |
import java.util.Hashtable; |
|
32 |
import java.util.Timer; |
|
33 |
|
|
34 |
import javax.servlet.ServletContext; |
|
35 |
import javax.servlet.http.HttpServletRequest; |
|
36 |
import javax.servlet.http.HttpServletResponse; |
|
37 |
|
|
38 |
import org.dataone.service.exceptions.IdentifierNotUnique; |
|
39 |
import org.dataone.service.exceptions.InsufficientResources; |
|
40 |
import org.dataone.service.exceptions.InvalidRequest; |
|
41 |
import org.dataone.service.exceptions.InvalidSystemMetadata; |
|
42 |
import org.dataone.service.exceptions.InvalidToken; |
|
43 |
import org.dataone.service.exceptions.NotAuthorized; |
|
44 |
import org.dataone.service.exceptions.NotFound; |
|
45 |
import org.dataone.service.exceptions.NotImplemented; |
|
46 |
import org.dataone.service.exceptions.ServiceFailure; |
|
47 |
import org.dataone.service.exceptions.UnsupportedType; |
|
48 |
import org.dataone.service.mn.MemberNodeCrud; |
|
49 |
import org.dataone.service.types.AuthToken; |
|
50 |
import org.dataone.service.types.Checksum; |
|
51 |
import org.dataone.service.types.DescribeResponse; |
|
52 |
import org.dataone.service.types.IdentifierType; |
|
53 |
import org.dataone.service.types.LogRecordSet; |
|
54 |
import org.dataone.service.types.SystemMetadata; |
|
55 |
|
|
56 |
import com.gc.iotools.stream.is.InputStreamFromOutputStream; |
|
57 |
|
|
58 |
import edu.ucsb.nceas.metacat.IdentifierManager; |
|
59 |
import edu.ucsb.nceas.metacat.McdbDocNotFoundException; |
|
60 |
import edu.ucsb.nceas.metacat.McdbException; |
|
61 |
import edu.ucsb.nceas.metacat.MetacatHandler; |
|
62 |
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException; |
|
63 |
import edu.ucsb.nceas.metacat.service.SessionService; |
|
64 |
import edu.ucsb.nceas.metacat.util.SessionData; |
|
65 |
import edu.ucsb.nceas.utilities.ParseLSIDException; |
|
66 |
import edu.ucsb.nceas.utilities.PropertyNotFoundException; |
|
67 |
|
|
68 |
/** |
|
69 |
* |
|
70 |
* Implements DataONE MemberNode CRUD API for Metacat. |
|
71 |
* |
|
72 |
* @author Matthew Jones |
|
73 |
*/ |
|
74 |
public class CrudService implements MemberNodeCrud { |
|
75 |
|
|
76 |
private ServletContext servletContext; |
|
77 |
private HttpServletRequest request; |
|
78 |
private HttpServletResponse response; |
|
79 |
|
|
80 |
// private Logger logMetacat; |
|
81 |
private MetacatHandler handler; |
|
82 |
// private String username; |
|
83 |
// private String password; |
|
84 |
// private String sessionId; |
|
85 |
// private String[] groupNames; |
|
86 |
private Hashtable<String, String[]> params; |
|
87 |
|
|
88 |
/** |
|
89 |
* Initializes new instance by setting servlet context,request and response. |
|
90 |
* TODO: remove dependency on Servlet infrastructure |
|
91 |
* TODO: Make this a real service, and make it a Singleton |
|
92 |
*/ |
|
93 |
public CrudService(ServletContext servletContext, |
|
94 |
HttpServletRequest request, HttpServletResponse response) { |
|
95 |
this.servletContext = servletContext; |
|
96 |
this.request = request; |
|
97 |
this.response = response; |
|
98 |
|
|
99 |
handler = new MetacatHandler(this.servletContext, new Timer()); |
|
100 |
initParams(); |
|
101 |
// loadSessionData(); |
|
102 |
} |
|
103 |
|
|
104 |
/** |
|
105 |
* copies request parameters to a Hashtable which is given as argument to |
|
106 |
* native MetacatHandler functions |
|
107 |
*/ |
|
108 |
private void initParams() { |
|
109 |
|
|
110 |
String name = null; |
|
111 |
String[] value = null; |
|
112 |
params = new Hashtable<String, String[]>(); |
|
113 |
Enumeration paramlist = request.getParameterNames(); |
|
114 |
while (paramlist.hasMoreElements()) { |
|
115 |
name = (String) paramlist.nextElement(); |
|
116 |
value = request.getParameterValues(name); |
|
117 |
params.put(name, value); |
|
118 |
} |
|
119 |
} |
|
120 |
|
|
121 |
/** |
|
122 |
* |
|
123 |
* Load user details of metacat session from the request |
|
124 |
* |
|
125 |
*/ |
|
126 |
// private void loadSessionData() { |
|
127 |
// SessionData sessionData = RequestUtil.getSessionData(request); |
|
128 |
// |
|
129 |
// // TODO: validate the session before allowing these values to be set |
|
130 |
// username = sessionData.getUserName(); |
|
131 |
// password = sessionData.getPassword(); |
|
132 |
// groupNames = sessionData.getGroupNames(); |
|
133 |
// sessionId = sessionData.getId(); |
|
134 |
// |
|
135 |
// if (username == null) { |
|
136 |
// username = "public"; |
|
137 |
// } |
|
138 |
// } |
|
139 |
|
|
140 |
/* |
|
141 |
* Look up the information on the session using the token provided in |
|
142 |
* the AuthToken. The Session should have all relevant user information. |
|
143 |
* If the session has expired or is invalid, the 'public' session will |
|
144 |
* be returned, giving the user anonymous access. |
|
145 |
*/ |
|
146 |
private static SessionData getSessionData(AuthToken token) { |
|
147 |
SessionData sessionData = null; |
|
148 |
String sessionId = token.getToken(); |
|
149 |
|
|
150 |
// if the session id is registered in SessionService, get the |
|
151 |
// SessionData for it. Otherwise, use the public session. |
|
152 |
if (SessionService.isSessionRegistered(sessionId)) { |
|
153 |
sessionData = SessionService.getRegisteredSession(sessionId); |
|
154 |
} else { |
|
155 |
sessionData = SessionService.getPublicSession(); |
|
156 |
} |
|
157 |
|
|
158 |
return sessionData; |
|
159 |
} |
|
160 |
|
|
161 |
public IdentifierType create(AuthToken token, IdentifierType guid, |
|
162 |
InputStream object, SystemMetadata sysmeta) throws InvalidToken, |
|
163 |
ServiceFailure, NotAuthorized, IdentifierNotUnique, UnsupportedType, |
|
164 |
InsufficientResources, InvalidSystemMetadata, NotImplemented { |
|
165 |
throw new NotImplemented(1000, "This method not yet implemented."); |
|
166 |
} |
|
167 |
|
|
168 |
public IdentifierType delete(AuthToken token, IdentifierType guid) |
|
169 |
throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, |
|
170 |
NotImplemented { |
|
171 |
throw new NotImplemented(1000, "This method not yet implemented."); |
|
172 |
} |
|
173 |
|
|
174 |
public DescribeResponse describe(AuthToken token, IdentifierType guid) |
|
175 |
throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, |
|
176 |
NotImplemented { |
|
177 |
throw new NotImplemented(1000, "This method not yet implemented."); |
|
178 |
} |
|
179 |
|
|
180 |
public InputStream get(AuthToken token, IdentifierType guid) |
|
181 |
throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, |
|
182 |
NotImplemented { |
|
183 |
|
|
184 |
// Retrieve the session information from the AuthToken |
|
185 |
// If the session is expired, then the user is 'public' |
|
186 |
final SessionData sessionData = getSessionData(token); |
|
187 |
|
|
188 |
// Look up the localId for this global identifier |
|
189 |
IdentifierManager im = IdentifierManager.getInstance(); |
|
190 |
try { |
|
191 |
final String localId = im.getLocalId(guid.getIdentifier()); |
|
192 |
|
|
193 |
final InputStreamFromOutputStream<String> objectStream = |
|
194 |
new InputStreamFromOutputStream<String>() { |
|
195 |
|
|
196 |
@Override |
|
197 |
public String produce(final OutputStream dataSink) throws Exception { |
|
198 |
|
|
199 |
try { |
|
200 |
handler.readFromMetacat(request.getRemoteAddr(), null, |
|
201 |
dataSink, localId, "xml", |
|
202 |
sessionData.getUserName(), |
|
203 |
sessionData.getGroupNames(), true, params); |
|
204 |
} catch (PropertyNotFoundException e) { |
|
205 |
throw new ServiceFailure(1030, e.getMessage()); |
|
206 |
} catch (ClassNotFoundException e) { |
|
207 |
throw new ServiceFailure(1030, e.getMessage()); |
|
208 |
} catch (IOException e) { |
|
209 |
throw new ServiceFailure(1030, e.getMessage()); |
|
210 |
} catch (SQLException e) { |
|
211 |
throw new ServiceFailure(1030, e.getMessage()); |
|
212 |
} catch (McdbException e) { |
|
213 |
throw new ServiceFailure(1030, e.getMessage()); |
|
214 |
} catch (ParseLSIDException e) { |
|
215 |
throw new NotFound(1020, e.getMessage()); |
|
216 |
} catch (InsufficientKarmaException e) { |
|
217 |
throw new NotAuthorized(1000, "Not authorized for get()."); |
|
218 |
} |
|
219 |
|
|
220 |
return "Completed"; |
|
221 |
} |
|
222 |
}; |
|
223 |
return objectStream; |
|
224 |
|
|
225 |
} catch (McdbDocNotFoundException e) { |
|
226 |
throw new NotFound(1020, e.getMessage()); |
|
227 |
} |
|
228 |
|
|
229 |
/* |
|
230 |
* Alternative approach that uses Piped streams, but requires thread handling |
|
231 |
* which makes exception handling difficult (because exceptions fall off the |
|
232 |
* calling thread, terminating the thread. |
|
233 |
* |
|
234 |
// Look up the localId for this global identifier |
|
235 |
IdentifierManager im = IdentifierManager.getInstance(); |
|
236 |
try { |
|
237 |
final String localId = im.getLocalId(guid.getIdentifier()); |
|
238 |
|
|
239 |
// Now use that localId to read the object and return it |
|
240 |
params.put("docid", new String[] { localId }); |
|
241 |
final PipedInputStream in = new PipedInputStream(); |
|
242 |
new Thread( |
|
243 |
new Runnable() { |
|
244 |
public void run() { |
|
245 |
try { |
|
246 |
PipedOutputStream out = new PipedOutputStream(in); |
|
247 |
handler.readFromMetacat(request.getRemoteAddr(), null, |
|
248 |
out, localId, "xml", |
|
249 |
username, groupNames, true, params); |
|
250 |
} catch (PropertyNotFoundException e) { |
|
251 |
throw new ServiceFailure(1030, e.getMessage()); |
|
252 |
} catch (ClassNotFoundException e) { |
|
253 |
throw new ServiceFailure(1030, e.getMessage()); |
|
254 |
} catch (IOException e) { |
|
255 |
throw new ServiceFailure(1030, e.getMessage()); |
|
256 |
} catch (SQLException e) { |
|
257 |
throw new ServiceFailure(1030, e.getMessage()); |
|
258 |
} catch (McdbException e) { |
|
259 |
throw new ServiceFailure(1030, e.getMessage()); |
|
260 |
} catch (ParseLSIDException e) { |
|
261 |
throw new NotFound(1020, e.getMessage()); |
|
262 |
} catch (InsufficientKarmaException e) { |
|
263 |
throw new NotAuthorized(1000, "Not authorized for get()."); |
|
264 |
} |
|
265 |
} |
|
266 |
} |
|
267 |
).start(); |
|
268 |
return in; |
|
269 |
} catch (McdbDocNotFoundException e) { |
|
270 |
throw new NotFound(1020, e.getMessage()); |
|
271 |
} |
|
272 |
*/ |
|
273 |
} |
|
274 |
|
|
275 |
public Checksum getChecksum(AuthToken token, IdentifierType guid) |
|
276 |
throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, |
|
277 |
InvalidRequest, NotImplemented { |
|
278 |
throw new NotImplemented(1000, "This method not yet implemented."); |
|
279 |
} |
|
280 |
|
|
281 |
public Checksum getChecksum(AuthToken token, IdentifierType guid, |
|
282 |
String checksumAlgorithm) throws InvalidToken, ServiceFailure, |
|
283 |
NotAuthorized, NotFound, InvalidRequest, NotImplemented { |
|
284 |
throw new NotImplemented(1000, "This method not yet implemented."); |
|
285 |
} |
|
286 |
|
|
287 |
public LogRecordSet getLogRecords(AuthToken token, Date fromDate, Date toDate) |
|
288 |
throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest, |
|
289 |
NotImplemented { |
|
290 |
throw new NotImplemented(1000, "This method not yet implemented."); |
|
291 |
} |
|
292 |
|
|
293 |
public SystemMetadata getSystemMetadata(AuthToken token, IdentifierType guid) |
|
294 |
throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, |
|
295 |
InvalidRequest, NotImplemented { |
|
296 |
throw new NotImplemented(1000, "This method not yet implemented."); |
|
297 |
} |
|
298 |
|
|
299 |
public IdentifierType update(AuthToken token, IdentifierType guid, |
|
300 |
InputStream object, IdentifierType obsoletedGuid, SystemMetadata sysmeta) |
|
301 |
throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, |
|
302 |
UnsupportedType, InsufficientResources, NotFound, InvalidSystemMetadata, |
|
303 |
NotImplemented { |
|
304 |
throw new NotImplemented(1000, "This method not yet implemented."); |
|
305 |
} |
|
306 |
|
|
307 |
} |
|
0 | 308 |
Also available in: Unified diff
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.