Revision 7417
Added by ben leinfelder about 12 years ago
src/edu/ucsb/nceas/metacat/QuerySpecification.java | ||
---|---|---|
749 | 749 |
StringBuffer self = new StringBuffer(); |
750 | 750 |
StringBuffer queryString = new StringBuffer(); |
751 | 751 |
|
752 |
queryString.append("SELECT xml_documents.docid, docname, doctype, date_created, date_updated, xml_documents.rev "); |
|
752 |
queryString.append("SELECT xml_documents.docid, identifier.guid, docname, doctype, date_created, date_updated, xml_documents.rev ");
|
|
753 | 753 |
queryString.append("FROM xml_documents, identifier "); |
754 | 754 |
queryString.append("WHERE xml_documents.docid = identifier.docid AND xml_documents.rev = identifier.rev AND"); |
755 | 755 |
|
src/edu/ucsb/nceas/metacat/restservice/MNResourceHandler.java | ||
---|---|---|
75 | 75 |
import org.dataone.service.types.v1.Permission; |
76 | 76 |
import org.dataone.service.types.v1.Subject; |
77 | 77 |
import org.dataone.service.types.v1.SystemMetadata; |
78 |
import org.dataone.service.types.v1_1.QueryEngineDescription; |
|
79 |
import org.dataone.service.types.v1_1.QueryEngineList; |
|
78 | 80 |
import org.dataone.service.util.Constants; |
79 | 81 |
import org.dataone.service.util.DateTimeMarshaller; |
80 | 82 |
import org.dataone.service.util.ExceptionHandler; |
... | ... | |
126 | 128 |
* @author leinfelder |
127 | 129 |
* |
128 | 130 |
*/ |
129 |
public class MNResourceHandler extends D1ResourceHandler{ |
|
131 |
public class MNResourceHandler extends D1ResourceHandler {
|
|
130 | 132 |
|
131 | 133 |
// MN-specific API Resources |
132 | 134 |
protected static final String RESOURCE_MONITOR = "monitor"; |
... | ... | |
323 | 325 |
getReplica(extra); |
324 | 326 |
status = true; |
325 | 327 |
} |
328 |
} else if (resource.startsWith(RESOURCE_QUERY)) { |
|
329 |
logMetacat.debug("Using resource " + RESOURCE_QUERY); |
|
330 |
// after the command |
|
331 |
extra = parseTrailing(resource, RESOURCE_QUERY); |
|
332 |
logMetacat.debug("query extra: " + extra); |
|
333 |
|
|
334 |
String engine = null; |
|
335 |
String query = null; |
|
336 |
|
|
337 |
if (extra != null) { |
|
338 |
// get the engine |
|
339 |
int engineIndex = extra.length(); |
|
340 |
if (extra.indexOf("/") > -1) { |
|
341 |
engineIndex = extra.indexOf("/"); |
|
342 |
} |
|
343 |
engine = extra.substring(0, engineIndex); |
|
344 |
logMetacat.debug("query engine: " + engine); |
|
345 |
|
|
346 |
// get the query if it is there |
|
347 |
query = extra.substring(engineIndex, extra.length()); |
|
348 |
if (query != null && query.length() == 0) { |
|
349 |
query = null; |
|
350 |
} else { |
|
351 |
if (query.startsWith("/")) { |
|
352 |
query = query.substring(1); |
|
353 |
} |
|
354 |
} |
|
355 |
logMetacat.debug("query: " + query); |
|
356 |
|
|
357 |
} |
|
358 |
logMetacat.debug("verb:" + httpVerb); |
|
359 |
if (httpVerb == GET) { |
|
360 |
doQuery(engine, query); |
|
361 |
status = true; |
|
362 |
} |
|
326 | 363 |
} |
327 | 364 |
|
328 | 365 |
if (!status) { |
... | ... | |
355 | 392 |
} |
356 | 393 |
|
357 | 394 |
|
395 |
private void doQuery(String engine, String query) { |
|
396 |
|
|
397 |
OutputStream out = null; |
|
398 |
|
|
399 |
try { |
|
400 |
// NOTE: we set the session explicitly for the MNode instance since these methods do not provide a parameter |
|
401 |
if (engine == null) { |
|
402 |
// just looking for list of engines |
|
403 |
MNodeService mnode = MNodeService.getInstance(request); |
|
404 |
mnode.setSession(session); |
|
405 |
QueryEngineList qel = mnode.listQueryEngines(); |
|
406 |
response.setContentType("text/xml"); |
|
407 |
response.setStatus(200); |
|
408 |
out = response.getOutputStream(); |
|
409 |
TypeMarshaller.marshalTypeToOutputStream(qel, out); |
|
410 |
return; |
|
411 |
} else { |
|
412 |
if (query != null) { |
|
413 |
MNodeService mnode = MNodeService.getInstance(request); |
|
414 |
mnode.setSession(session); |
|
415 |
InputStream stream = mnode.query(engine, query); |
|
416 |
|
|
417 |
//response.setContentType("application/octet-stream"); |
|
418 |
response.setContentType("text/xml"); |
|
419 |
response.setStatus(200); |
|
420 |
out = response.getOutputStream(); |
|
421 |
// write the results to the output stream |
|
422 |
IOUtils.copyLarge(stream, out); |
|
423 |
return; |
|
424 |
} else { |
|
425 |
MNodeService mnode = MNodeService.getInstance(request); |
|
426 |
mnode.setSession(session); |
|
427 |
QueryEngineDescription qed = mnode.getQueryEngineDescription(engine); |
|
428 |
response.setContentType("text/xml"); |
|
429 |
response.setStatus(200); |
|
430 |
out = response.getOutputStream(); |
|
431 |
TypeMarshaller.marshalTypeToOutputStream(qed, out); |
|
432 |
return; |
|
433 |
} |
|
434 |
} |
|
435 |
|
|
436 |
|
|
437 |
} catch (BaseException be) { |
|
438 |
// report Exceptions as clearly as possible |
|
439 |
try { |
|
440 |
out = response.getOutputStream(); |
|
441 |
} catch (IOException e) { |
|
442 |
logMetacat.error("Could not get output stream from response", e); |
|
443 |
} |
|
444 |
serializeException(be, out); |
|
445 |
} catch (Exception e) { |
|
446 |
// report Exceptions as clearly and generically as possible |
|
447 |
logMetacat.error(e.getClass() + ": " + e.getMessage(), e); |
|
448 |
try { |
|
449 |
out = response.getOutputStream(); |
|
450 |
} catch (IOException ioe) { |
|
451 |
logMetacat.error("Could not get output stream from response", ioe); |
|
452 |
} |
|
453 |
ServiceFailure se = new ServiceFailure("0000", e.getMessage()); |
|
454 |
serializeException(se, out); |
|
455 |
} |
|
456 |
} |
|
457 |
|
|
458 |
|
|
358 | 459 |
/** |
359 | 460 |
* Handles notification of system metadata changes for the given identifier |
360 | 461 |
* |
... | ... | |
885 | 986 |
|
886 | 987 |
} |
887 | 988 |
|
989 |
|
|
990 |
|
|
888 | 991 |
/** |
889 | 992 |
* Implements REST version of DataONE CRUD API --> get |
890 | 993 |
* @param pid ID of data object to be read |
src/edu/ucsb/nceas/metacat/restservice/D1ResourceHandler.java | ||
---|---|---|
91 | 91 |
protected static final String RESOURCE_META = "meta"; |
92 | 92 |
protected static final String RESOURCE_LOG = "log"; |
93 | 93 |
|
94 |
protected static final String RESOURCE_QUERY = "query"; |
|
95 |
|
|
94 | 96 |
protected static final String RESOURCE_IS_AUTHORIZED = "isAuthorized"; |
95 | 97 |
protected static final String RESOURCE_ACCESS_RULES = "accessRules"; |
96 | 98 |
|
src/edu/ucsb/nceas/metacat/DBQuery.java | ||
---|---|---|
391 | 391 |
response.setContentType("text/xml"); |
392 | 392 |
} |
393 | 393 |
createResultDocument(xmlquery, qspec, out, user, groups, useXMLIndex, |
394 |
pagesize, pagestart, sessionid, qformat); |
|
394 |
pagesize, pagestart, sessionid, qformat, false);
|
|
395 | 395 |
}//if |
396 | 396 |
else |
397 | 397 |
{ |
... | ... | |
400 | 400 |
Writer nonout = null; |
401 | 401 |
StringBuffer xml = createResultDocument(xmlquery, qspec, nonout, user, |
402 | 402 |
groups, useXMLIndex, pagesize, |
403 |
pagestart, sessionid, qformat); |
|
403 |
pagestart, sessionid, qformat, false);
|
|
404 | 404 |
|
405 | 405 |
//transfer the xml to html |
406 | 406 |
try |
... | ... | |
440 | 440 |
|
441 | 441 |
} |
442 | 442 |
|
443 |
|
|
444 |
|
|
445 | 443 |
/** |
446 | 444 |
* Transforms a hashtable of documents to an xml or html result and sent |
447 | 445 |
* the content to outputstream. Keep going untill hastable is empty. stop it. |
... | ... | |
462 | 460 |
String user, String[] groups, |
463 | 461 |
boolean useXMLIndex) |
464 | 462 |
{ |
465 |
return createResultDocument(xmlquery,qspec,out, user,groups, useXMLIndex, 0, 0,"", qformat); |
|
463 |
return createResultDocument(xmlquery,qspec,out, user,groups, useXMLIndex, 0, 0,"", qformat, false);
|
|
466 | 464 |
} |
465 |
|
|
466 |
/** |
|
467 |
* |
|
468 |
* @param xmlquery |
|
469 |
* @param user |
|
470 |
* @param groups |
|
471 |
* @param useXMLIndex |
|
472 |
* @return |
|
473 |
* @throws IOException |
|
474 |
* @throws PropertyNotFoundException |
|
475 |
*/ |
|
476 |
public String performPathquery(String xmlquery, String user, |
|
477 |
String[] groups) throws PropertyNotFoundException, IOException { |
|
478 |
|
|
479 |
// get the XML query and convert it to query specification |
|
480 |
xmlquery = transformQuery(xmlquery); |
|
481 |
QuerySpecification qspec = new QuerySpecification(xmlquery, parserName, PropertyService.getProperty("document.accNumSeparator")); |
|
482 |
|
|
483 |
// force it to output the results to the string buffer, not outputstream |
|
484 |
Writer nonout = null; |
|
485 |
boolean useXMLIndex = (new Boolean(PropertyService.getProperty("database.usexmlindex"))).booleanValue(); |
|
486 |
StringBuffer xml = createResultDocument(xmlquery, qspec, nonout, user, groups, useXMLIndex, 0, 0, "", qformat, true); |
|
467 | 487 |
|
488 |
return xml.toString(); |
|
489 |
|
|
490 |
} |
|
491 |
|
|
468 | 492 |
/* |
469 | 493 |
* Transforms a hashtable of documents to an xml or html result and sent |
470 | 494 |
* the content to outputstream. Keep going untill hastable is empty. stop it. |
... | ... | |
477 | 501 |
String user, String[] groups, |
478 | 502 |
boolean useXMLIndex, int pagesize, |
479 | 503 |
int pagestart, String sessionid, |
480 |
String qformat) |
|
504 |
String qformat, boolean includeGuid)
|
|
481 | 505 |
{ |
482 | 506 |
DBConnection dbconn = null; |
483 | 507 |
int serialNumber = -1; |
... | ... | |
523 | 547 |
logMetacat.debug("DBQuery.createResultDocument - Not in map query"); |
524 | 548 |
resultContent = findResultDoclist(qspec, out, user, groups, |
525 | 549 |
dbconn, useXMLIndex, pagesize, pagestart, |
526 |
sessionid, givenDocids, qformat); |
|
550 |
sessionid, givenDocids, qformat, includeGuid);
|
|
527 | 551 |
} |
528 | 552 |
else |
529 | 553 |
{ |
... | ... | |
535 | 559 |
givenDocids = (Vector)docidOverride.elementAt(i); |
536 | 560 |
StringBuffer subset = findResultDoclist(qspec, out, user, groups, |
537 | 561 |
dbconn, useXMLIndex, pagesize, pagestart, |
538 |
sessionid, givenDocids, qformat); |
|
562 |
sessionid, givenDocids, qformat, includeGuid);
|
|
539 | 563 |
resultContent.append(subset); |
540 | 564 |
} |
541 | 565 |
} |
... | ... | |
584 | 608 |
String user, String[]groups, |
585 | 609 |
DBConnection dbconn, boolean useXMLIndex, |
586 | 610 |
int pagesize, int pagestart, String sessionid, |
587 |
Vector givenDocids, String qformat) |
|
611 |
Vector givenDocids, String qformat, boolean includeGuid)
|
|
588 | 612 |
throws Exception |
589 | 613 |
{ |
590 | 614 |
// keep track of the values we add as prepared statement question marks (?) |
... | ... | |
597 | 621 |
ResultDocumentSet docListResult = new ResultDocumentSet(); |
598 | 622 |
PreparedStatement pstmt = null; |
599 | 623 |
String docid = null; |
624 |
String guid = null; |
|
600 | 625 |
String docname = null; |
601 | 626 |
String doctype = null; |
602 | 627 |
String createDate = null; |
... | ... | |
652 | 677 |
|
653 | 678 |
// include the docids, either exclusively, or in conjuction with the query |
654 | 679 |
if (operator == null) { |
655 |
query = "SELECT xml_documents.docid, docname, doctype, date_created, date_updated, xml_documents.rev " + |
|
680 |
query = "SELECT xml_documents.docid, identifier.guid, docname, doctype, date_created, date_updated, xml_documents.rev " +
|
|
656 | 681 |
"FROM xml_documents, identifier " + |
657 | 682 |
"WHERE xml_documents.docid = identifier.docid AND xml_documents.rev = identifier.rev AND "; |
658 | 683 |
query = query + docidCondition.toString(); |
... | ... | |
749 | 774 |
{ |
750 | 775 |
logMetacat.debug("DBQuery.findResultDoclist - getting result: " + currentIndex); |
751 | 776 |
docid = rs.getString(1).trim(); |
752 |
logMetacat.debug("DBQuery.findResultDoclist - processing: " + docid); |
|
753 |
docname = rs.getString(2); |
|
754 |
doctype = rs.getString(3); |
|
755 |
logMetacat.debug("DBQuery.findResultDoclist - processing: " + doctype); |
|
756 |
createDate = rs.getString(4); |
|
757 |
updateDate = rs.getString(5); |
|
758 |
rev = rs.getInt(6); |
|
777 |
logMetacat.debug("DBQuery.findResultDoclist - docid: " + docid); |
|
778 |
guid = rs.getString(2).trim(); |
|
779 |
logMetacat.debug("DBQuery.findResultDoclist - guid: " + guid); |
|
780 |
docname = rs.getString(3); |
|
781 |
doctype = rs.getString(4); |
|
782 |
logMetacat.debug("DBQuery.findResultDoclist - doctype: " + doctype); |
|
783 |
createDate = rs.getString(5); |
|
784 |
updateDate = rs.getString(6); |
|
785 |
rev = rs.getInt(7); |
|
759 | 786 |
|
760 | 787 |
Vector returndocVec = qspec.getReturnDocList(); |
761 | 788 |
if (returndocVec.size() == 0 || returndocVec.contains(doctype)) |
... | ... | |
767 | 794 |
+ PropertyService.getProperty("document.accNumSeparator"); |
768 | 795 |
completeDocid += rev; |
769 | 796 |
document.append("<docid>").append(completeDocid).append("</docid>"); |
797 |
if (includeGuid) { |
|
798 |
document.append("<guid>").append(guid).append("</guid>"); |
|
799 |
} |
|
770 | 800 |
if (docname != null) |
771 | 801 |
{ |
772 | 802 |
document.append("<docname>" + docname + "</docname>"); |
src/edu/ucsb/nceas/metacat/dataone/MNodeService.java | ||
---|---|---|
23 | 23 |
|
24 | 24 |
package edu.ucsb.nceas.metacat.dataone; |
25 | 25 |
|
26 |
import java.io.ByteArrayInputStream; |
|
26 | 27 |
import java.io.IOException; |
27 | 28 |
import java.io.InputStream; |
28 | 29 |
import java.math.BigInteger; |
29 | 30 |
import java.security.NoSuchAlgorithmException; |
30 |
import java.sql.SQLException;
|
|
31 |
import java.util.ArrayList;
|
|
31 | 32 |
import java.util.Calendar; |
32 | 33 |
import java.util.Date; |
33 | 34 |
import java.util.List; |
35 |
import java.util.Set; |
|
34 | 36 |
import java.util.Timer; |
35 | 37 |
|
36 | 38 |
import javax.servlet.http.HttpServletRequest; |
... | ... | |
59 | 61 |
import org.dataone.service.mn.tier2.v1.MNAuthorization; |
60 | 62 |
import org.dataone.service.mn.tier3.v1.MNStorage; |
61 | 63 |
import org.dataone.service.mn.tier4.v1.MNReplication; |
64 |
import org.dataone.service.mn.v1.MNQuery; |
|
62 | 65 |
import org.dataone.service.types.v1.Checksum; |
63 | 66 |
import org.dataone.service.types.v1.DescribeResponse; |
64 | 67 |
import org.dataone.service.types.v1.Event; |
65 |
import org.dataone.service.types.v1.Group; |
|
66 | 68 |
import org.dataone.service.types.v1.Identifier; |
67 | 69 |
import org.dataone.service.types.v1.Log; |
68 | 70 |
import org.dataone.service.types.v1.LogEntry; |
... | ... | |
85 | 87 |
import org.dataone.service.types.v1.Subject; |
86 | 88 |
import org.dataone.service.types.v1.Synchronization; |
87 | 89 |
import org.dataone.service.types.v1.SystemMetadata; |
90 |
import org.dataone.service.types.v1.util.AuthUtils; |
|
88 | 91 |
import org.dataone.service.types.v1.util.ChecksumUtil; |
92 |
import org.dataone.service.types.v1_1.QueryEngineDescription; |
|
93 |
import org.dataone.service.types.v1_1.QueryEngineList; |
|
89 | 94 |
import org.dataone.service.util.Constants; |
90 | 95 |
|
91 |
import edu.ucsb.nceas.metacat.DocumentImpl;
|
|
96 |
import edu.ucsb.nceas.metacat.DBQuery;
|
|
92 | 97 |
import edu.ucsb.nceas.metacat.EventLog; |
93 | 98 |
import edu.ucsb.nceas.metacat.IdentifierManager; |
94 | 99 |
import edu.ucsb.nceas.metacat.McdbDocNotFoundException; |
100 |
import edu.ucsb.nceas.metacat.MetaCatServlet; |
|
95 | 101 |
import edu.ucsb.nceas.metacat.MetacatHandler; |
96 |
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException; |
|
97 | 102 |
import edu.ucsb.nceas.metacat.dataone.hazelcast.HazelcastService; |
98 | 103 |
import edu.ucsb.nceas.metacat.properties.PropertyService; |
99 | 104 |
import edu.ucsb.nceas.metacat.util.SystemUtil; |
... | ... | |
127 | 132 |
* |
128 | 133 |
*/ |
129 | 134 |
public class MNodeService extends D1NodeService |
130 |
implements MNAuthorization, MNCore, MNRead, MNReplication, MNStorage { |
|
135 |
implements MNAuthorization, MNCore, MNRead, MNReplication, MNStorage, MNQuery {
|
|
131 | 136 |
|
132 | 137 |
/* the logger instance */ |
133 | 138 |
private Logger logMetacat = null; |
... | ... | |
1317 | 1322 |
|
1318 | 1323 |
return update(null, pid, object, newPid, sysmeta); |
1319 | 1324 |
} |
1325 |
|
|
1326 |
@Override |
|
1327 |
public QueryEngineDescription getQueryEngineDescription(String engine) |
|
1328 |
throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented, |
|
1329 |
NotFound { |
|
1330 |
// TODO: implement |
|
1331 |
throw new NotImplemented("", "Metacat has not implemented this method"); |
|
1332 |
} |
|
1333 |
|
|
1334 |
@Override |
|
1335 |
public QueryEngineList listQueryEngines() throws InvalidToken, |
|
1336 |
ServiceFailure, NotAuthorized, NotImplemented { |
|
1337 |
QueryEngineList qel = new QueryEngineList(); |
|
1338 |
// support pathquery initially |
|
1339 |
qel.addQueryEngine("pathquery"); |
|
1340 |
// TODO: implement solr-based query |
|
1341 |
//qel.addQueryEngine("solr"); |
|
1342 |
return qel; |
|
1343 |
} |
|
1344 |
|
|
1345 |
@Override |
|
1346 |
public InputStream query(String engine, String query) throws InvalidToken, |
|
1347 |
ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented, |
|
1348 |
NotFound { |
|
1349 |
if (engine.equals("pathquery")) { |
|
1350 |
try { |
|
1351 |
DBQuery queryobj = new DBQuery(); |
|
1352 |
String user = Constants.SUBJECT_PUBLIC; |
|
1353 |
String[] groups= null; |
|
1354 |
if (session != null) { |
|
1355 |
user = session.getSubject().getValue(); |
|
1356 |
Set<Subject> subjects = AuthUtils.authorizedClientSubjects(session); |
|
1357 |
if (subjects != null) { |
|
1358 |
List<String> groupList = new ArrayList<String>(); |
|
1359 |
for (Subject subject: subjects) { |
|
1360 |
groupList.add(subject.getValue()); |
|
1361 |
} |
|
1362 |
groups = groupList.toArray(new String[0]); |
|
1363 |
} |
|
1364 |
} |
|
1365 |
String results = queryobj.performPathquery(query, user, groups); |
|
1366 |
return new ByteArrayInputStream(results.getBytes(MetaCatServlet.DEFAULT_ENCODING)); |
|
1367 |
|
|
1368 |
} catch (Exception e) { |
|
1369 |
|
|
1370 |
} |
|
1371 |
|
|
1372 |
} |
|
1373 |
return null; |
|
1374 |
} |
|
1320 | 1375 |
|
1321 | 1376 |
} |
src/edu/ucsb/nceas/metacat/dataone/D1NodeService.java | ||
---|---|---|
107 | 107 |
|
108 | 108 |
/* parameters set in the incoming request */ |
109 | 109 |
private Hashtable<String, String[]> params; |
110 |
|
|
111 |
/** |
|
112 |
* out-of-band session object to be used when not passed in as a method parameter |
|
113 |
*/ |
|
114 |
protected Session session; |
|
110 | 115 |
|
111 | 116 |
/** |
112 | 117 |
* Constructor - used to set the metacatUrl from a subclass extending D1NodeService |
... | ... | |
116 | 121 |
public D1NodeService(HttpServletRequest request) { |
117 | 122 |
this.request = request; |
118 | 123 |
} |
119 |
|
|
124 |
|
|
120 | 125 |
/** |
126 |
* retrieve the out-of-band session |
|
127 |
* @return |
|
128 |
*/ |
|
129 |
public Session getSession() { |
|
130 |
return session; |
|
131 |
} |
|
132 |
|
|
133 |
/** |
|
134 |
* Set the out-of-band session |
|
135 |
* @param session |
|
136 |
*/ |
|
137 |
public void setSession(Session session) { |
|
138 |
this.session = session; |
|
139 |
} |
|
140 |
|
|
141 |
/** |
|
121 | 142 |
* This method provides a lighter weight mechanism than |
122 | 143 |
* getSystemMetadata() for a client to determine basic |
123 | 144 |
* properties of the referenced object. |
Also available in: Unified diff
Implement MNQuery for "pathquery" engine. Optionally include guid in the pathquery results (https://redmine.dataone.org/issues/3083)