Project

General

Profile

« Previous | Next » 

Revision 7417

Implement MNQuery for "pathquery" engine. Optionally include guid in the pathquery results (https://redmine.dataone.org/issues/3083)

View differences:

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