Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that searches a relational DB for elements and 
4
 *             attributes that have free text matches a query string,
5
 *             or structured query matches to a path specified node in the 
6
 *             XML hierarchy.  It returns a result set consisting of the 
7
 *             document ID for each document that satisfies the query
8
 *  Copyright: 2000 Regents of the University of California and the
9
 *             National Center for Ecological Analysis and Synthesis
10
 *    Authors: Matt Jones
11
 *    Release: @release@
12
 *
13
 *   '$Author: berkley $'
14
 *     '$Date: 2000-10-03 15:48:41 -0700 (Tue, 03 Oct 2000) $'
15
 * '$Revision: 489 $'
16
 */
17

    
18
package edu.ucsb.nceas.metacat;
19

    
20
import java.io.*;
21
import java.util.Vector;
22
import java.net.URL;
23
import java.net.MalformedURLException;
24
import java.sql.*;
25
import java.util.Stack;
26
import java.util.Hashtable;
27
import java.util.Enumeration;
28

    
29
/** 
30
 * A Class that searches a relational DB for elements and 
31
 * attributes that have free text matches a query string,
32
 * or structured query matches to a path specified node in the 
33
 * XML hierarchy.  It returns a result set consisting of the 
34
 * document ID for each document that satisfies the query
35
 */
36
public class DBQuery {
37

    
38
  static final int ALL = 1;
39
  static final int WRITE = 2;
40
  static final int READ = 4;
41

    
42
  private Connection	conn = null;
43
  private String	parserName = null;
44
  private MetaCatUtil util = new MetaCatUtil();
45
  /**
46
   * the main routine used to test the DBQuery utility.
47
   * <p>
48
   * Usage: java DBQuery <xmlfile>
49
   *
50
   * @param xmlfile the filename of the xml file containing the query
51
   */
52
  static public void main(String[] args) {
53
     
54
     if (args.length < 1)
55
     {
56
        System.err.println("Wrong number of arguments!!!");
57
        System.err.println("USAGE: java DBQuery <xmlfile>");
58
        return;
59
     } else {
60
        try {
61
                    
62
          String xmlfile  = args[0];
63

    
64
          // Open a connection to the database
65
          MetaCatUtil   util = new MetaCatUtil();
66
          Connection dbconn = util.openDBConnection();
67

    
68
          // Execute the query
69
          DBQuery queryobj = new DBQuery(dbconn, util.getOption("saxparser"));
70
          FileReader xml = new FileReader(new File(xmlfile));
71
          Hashtable nodelist = null;
72
          nodelist = queryobj.findDocuments(xml, null, null);
73

    
74
          // Print the reulting document listing
75
          StringBuffer result = new StringBuffer();
76
          String document = null;
77
          String docid = null;
78
          result.append("<?xml version=\"1.0\"?>\n");
79
          result.append("<resultset>\n"); 
80
  // following line removed by Dan Higgins to avoid insertion of query XML inside returned XML doc
81
  //        result.append("  <query>" + xmlfile + "</query>\n");
82
          Enumeration doclist = nodelist.keys(); 
83
          while (doclist.hasMoreElements()) {
84
            docid = (String)doclist.nextElement();
85
            document = (String)nodelist.get(docid);
86
            result.append("  <document>\n    " + document + 
87
                          "\n  </document>\n");
88
          }
89
          result.append("</resultset>\n");
90

    
91
          System.out.println(result);
92

    
93
        } catch (Exception e) {
94
          System.err.println("EXCEPTION HANDLING REQUIRED");
95
          System.err.println(e.getMessage());
96
          e.printStackTrace(System.err);
97
        }
98
     }
99
  }
100
  
101
  /**
102
   * construct an instance of the DBQuery class 
103
   *
104
   * <p>Generally, one would call the findDocuments() routine after creating 
105
   * an instance to specify the search query</p>
106
   *
107
   * @param conn the JDBC connection that we use for the query
108
   * @param parserName the fully qualified name of a Java class implementing
109
   *                   the org.xml.sax.XMLReader interface
110
   */
111
  public DBQuery( Connection conn, String parserName ) 
112
                  throws IOException, 
113
                         SQLException, 
114
                         ClassNotFoundException {
115
    this.conn = conn;
116
    this.parserName = parserName;
117
  }
118
  
119
  public Hashtable findDocuments(Reader xmlquery, String user, String group)
120
  {
121
    return findDocuments(xmlquery, user, group, null);
122
  }
123
  
124
  /** 
125
   * routine to search the elements and attributes looking to match query
126
   *
127
   * @param xmlquery the xml serialization of the query (@see pathquery.dtd)
128
   * @param user the username of the user
129
   * @param group the group of the user
130
   * @param returndoc an array of document types to backtrack against.
131
   */
132
  public Hashtable findDocuments(Reader xmlquery, String user, String group,
133
                                 String[] returndoc)
134
  {
135
      Hashtable	 docListResult = new Hashtable();
136
      PreparedStatement pstmt;
137
      String docid = null;
138
      String docname = null;
139
      String doctype = null;
140
      String doctitle = null;
141
      String createDate = null;
142
      String updateDate = null;
143
      String fieldname = null;
144
      String fielddata = null;
145
      String relation = null;
146
      StringBuffer document = null; 
147
      Vector returndocVec = new Vector();
148
      
149
      if(returndoc != null)
150
      {//add the returndoc elements to a vector for easier manipulation
151
        for(int i=0; i<returndoc.length; i++)
152
        {
153
          returndocVec.add(new String((String)returndoc[i]));
154
        }
155
      }
156
      
157
      try {
158
        // Get the XML query and covert it into a SQL statment
159
        QuerySpecification qspec = new QuerySpecification(xmlquery, 
160
                                   parserName);
161
        //System.out.println(qspec.printSQL());
162
        pstmt = conn.prepareStatement( qspec.printSQL() );
163

    
164
        // Execute the SQL query using the JDBC connection
165
        pstmt.execute();
166
        ResultSet rs = pstmt.getResultSet();
167
        boolean tableHasRows = rs.next();
168
        while (tableHasRows) {
169
          docid = rs.getString(1);
170
          if ( !hasReadPermission(conn, docid, user, group) ) {continue;}
171
          docname = rs.getString(2);
172
          doctype = rs.getString(3);
173
          doctitle = rs.getString(4);
174
          createDate = rs.getString(5);
175
          updateDate = rs.getString(6);
176
          
177
          if(returndocVec.size() != 0 && !returndocVec.contains(doctype))
178
          { //there are returndocs to match (backtracking can now be performed). 
179
            //System.out.println("olddoctype: " + doctype);
180
            StringBuffer btBuf = new StringBuffer();
181
            btBuf.append("select object from xml_relation where ");
182
            btBuf.append("objdoctype in (");
183
            //build the doctype list for the backtracking sql statement
184
            for(int i=0; i<returndocVec.size(); i++)
185
            {
186
              btBuf.append("'").append((String)returndocVec.get(i)).append("'");
187
              if(i != (returndocVec.size() - 1))
188
              {
189
                btBuf.append(", ");
190
              } 
191
            }
192
            btBuf.append(") ");
193
            btBuf.append("and subject like '");
194
            btBuf.append("metacat://").append(util.getOption("server"));
195
            btBuf.append("?docid=").append(docid).append("'");
196
            pstmt = conn.prepareStatement(btBuf.toString());
197
            pstmt.execute();
198
            ResultSet btrs = pstmt.getResultSet();
199
            boolean hasBtRows = btrs.next();
200
            if(hasBtRows)
201
            { //there was a backtrackable document found
202
              DocumentImpl xmldoc = null;
203
              //System.out.println("document found is: " + btrs.getString(1));
204
              metacatURL objURL = new metacatURL(btrs.getString(1));
205
              try
206
              {
207
                xmldoc = new DocumentImpl(conn, objURL.getParam(0)[1]);
208
              }
209
              catch(Exception e)
210
              {
211
                System.out.println("Error getting document: " + e.getMessage());
212
              }
213
              
214
              docid   = xmldoc.getDocID();
215
              docname = xmldoc.getDocname();
216
              doctype = xmldoc.getDoctype();
217
              doctitle = xmldoc.getDocTitle();
218
              createDate = xmldoc.getCreateDate();
219
              updateDate = xmldoc.getUpdateDate();
220
              //System.out.println("docname: " + docname + " doctype: " + doctype + 
221
              //                   " doctitle: " + doctitle + " createdate: " +
222
              //                   createDate + " updatedate: " + updateDate);
223
            }
224
            btrs.close();
225
          }
226
          
227
          document = new StringBuffer();
228
          //System.out.println("packagdoctype: " + util.getOption("packagedoctype"));
229
          if(!doctype.equals(util.getOption("packagedoctype")))
230
          {
231
            document.append("<docid>").append(docid).append("</docid>");
232
            if (docname != null) {
233
              document.append("<docname>" + docname + "</docname>");
234
            }
235
            if (doctype != null) {
236
              document.append("<doctype>" + doctype + "</doctype>");
237
            }
238
            if (doctitle != null) {
239
              document.append("<doctitle>" + doctitle + "</doctitle>");
240
            }
241
            if(createDate != null) {
242
              document.append("<createdate>" + createDate + "</createdate>");
243
            }
244
            if(updateDate != null) {
245
              document.append("<updatedate>" + updateDate + "</updatedate>");
246
            }
247
            // Store the document id and the root node id
248
            docListResult.put(docid,(String)document.toString());
249
          }
250

    
251
          // Advance to the next record in the cursor
252
          tableHasRows = rs.next();
253
        }
254
        
255
        if(qspec.containsExtendedSQL())
256
        {
257
          Vector extendedFields = new Vector(qspec.getReturnFieldList());
258
          Vector results = new Vector();
259
          Enumeration keylist = docListResult.keys();
260
          StringBuffer doclist = new StringBuffer();
261
          while(keylist.hasMoreElements())
262
          {
263
            doclist.append("'");
264
            doclist.append((String)keylist.nextElement());
265
            doclist.append("',");
266
          }
267
          doclist.deleteCharAt(doclist.length()-1); //remove the last comma
268
          pstmt = conn.prepareStatement(qspec.printExtendedSQL(
269
                                        doclist.toString()));
270
          pstmt.execute();
271
          rs = pstmt.getResultSet();
272
          tableHasRows = rs.next();
273
          while(tableHasRows) 
274
          {
275
            docid = rs.getString(1);
276
            if ( !hasReadPermission(conn, docid, user, group) ) {continue;}
277
            fieldname = rs.getString(2);
278
            fielddata = rs.getString(3);
279
            
280
            document = new StringBuffer();
281

    
282
            document.append("<param name=\"");
283
            document.append(fieldname);
284
            document.append("\">");
285
            document.append(fielddata);
286
            document.append("</param>");
287

    
288
            tableHasRows = rs.next();
289
            if(docListResult.containsKey(docid))
290
            {
291
              String removedelement = (String)docListResult.remove(docid);
292
              docListResult.put(docid, removedelement + document.toString());
293
            }
294
            else
295
            {
296
              docListResult.put(docid, document.toString()); 
297
            }
298
          }
299
        }
300

    
301
        //this loop adds the relation data to the resultdoc
302
        //this code might be able to be added to the backtracking code above
303
        Enumeration docidkeys = docListResult.keys();
304
        while(docidkeys.hasMoreElements())
305
        {
306
          String connstring = "metacat://"+util.getOption("server")+"?docid=";
307
          String docidkey = (String)docidkeys.nextElement();
308
          pstmt = conn.prepareStatement(
309
                  qspec.printRelationSQL(connstring + docidkey));
310
          pstmt.execute();
311
          rs = pstmt.getResultSet();
312
          tableHasRows = rs.next();
313
          while(tableHasRows)
314
          {
315
            String sub = rs.getString(1);
316
            String rel = rs.getString(2);
317
            String obj = rs.getString(3);
318
            String subDT = rs.getString(4);
319
            String objDT = rs.getString(5);
320
            
321
            metacatURL murl = new metacatURL(sub);
322
            if(murl.getURLType().equals("metacat"))
323
            {//we only want to process metacat urls here.
324
              String[] tempparam = murl.getParam(0);
325
              if(tempparam[0].equals("docid") && tempparam[1].equals(docidkey))
326
              {
327
                document = new StringBuffer();
328
                document.append("<relation>");
329
                document.append("<relationtype>").append(rel);
330
                document.append("</relationtype>");
331
                document.append("<relationdoc>").append(obj);
332
                document.append("</relationdoc>");
333
                document.append("<relationdoctype>").append(objDT);
334
                document.append("</relationdoctype>");
335
                document.append("</relation>");
336
                
337
                String removedelement = (String)docListResult.remove(docidkey);
338
                docListResult.put(docidkey, removedelement + document.toString());
339
                
340
              }
341
            }
342
            tableHasRows = rs.next();
343
          }
344
        }
345
        pstmt.close();
346
      } catch (SQLException e) {
347
        System.err.println("Error getting id: " + e.getMessage());
348
      } catch (IOException ioe) {
349
        System.err.println("Error printing qspec:");
350
        System.err.println(ioe.getMessage());
351
      }
352
    //System.out.println("docListResult: ");
353
    //System.out.println(docListResult.toString());
354
    return docListResult;
355
  }
356
  
357
  /**
358
   * returns a string array of the contents of a particular node. 
359
   * If the node appears more than once, the contents are returned 
360
   * in the order in which they appearred in the document.
361
   * @param nodename the name or path of the particular node.
362
   * @param docid the docid of the document you want the node from.
363
   * @param conn a database connection-this allows this method to be static
364
   */
365
  public static Object[] getNodeContent(String nodename, String docid, 
366
                                        Connection conn)
367
  {
368
    StringBuffer query = new StringBuffer();
369
    Vector result = new Vector();
370
    PreparedStatement pstmt;
371
    query.append("select nodedata from xml_nodes where parentnodeid in ");
372
    query.append("(select nodeid from xml_index where path like '");
373
    query.append(nodename);
374
    query.append("' and docid like '").append(docid).append("')");
375
    try
376
    {
377
      pstmt = conn.prepareStatement(query.toString());
378

    
379
      // Execute the SQL query using the JDBC connection
380
      pstmt.execute();
381
      ResultSet rs = pstmt.getResultSet();
382
      boolean tableHasRows = rs.next();
383
      while (tableHasRows) 
384
      {
385
        result.add(rs.getString(1));
386
        System.out.println(rs.getString(1));
387
        tableHasRows = rs.next();
388
      }
389
    } 
390
    catch (SQLException e) 
391
    {
392
      System.err.println("Error getting id: " + e.getMessage());
393
    } 
394
    
395
    return result.toArray();
396
  }
397
  
398
  /**
399
   * format a structured query as an XML document that conforms
400
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
401
   * structured query engine
402
   *
403
   * @param params The list of parameters that  should be included in the query
404
   */
405
  public static String createSQuery(Hashtable params)
406
  { 
407
    StringBuffer query = new StringBuffer();
408
    Enumeration elements;
409
    Enumeration keys;
410
    String doctype = null;
411
    String casesensitive = null;
412
    String searchmode = null;
413
    Object nextkey;
414
    Object nextelement;
415
    //add the xml headers
416
    query.append("<?xml version=\"1.0\"?>\n");
417
    query.append("<pathquery version=\"1.0\"><meta_file_id>");
418
    
419
    if(params.containsKey("meta_file_id"))
420
    {
421
      query.append( ((String[])params.get("meta_file_id"))[0]);
422
    	query.append("</meta_file_id>");
423
    }
424
    else
425
    {
426
      query.append("unspecified</meta_file_id>");
427
    }
428
    
429
    query.append("<querytitle>");
430
    if(params.containsKey("querytitle"))
431
    {
432
      query.append(((String[])params.get("querytitle"))[0]);
433
    	query.append("</querytitle>");
434
    }
435
    else
436
    {
437
    	query.append("unspecified</querytitle>");
438
    }
439
    
440
    if(params.containsKey("doctype"))
441
    {
442
      doctype = ((String[])params.get("doctype"))[0]; 
443
    }
444
    else
445
    {
446
      doctype = "ANY";  
447
    }
448
    
449
    if(params.containsKey("returnfield"))
450
    {
451
      String[] returnfield = ((String[])params.get("returnfield"));
452
      for(int i=0; i<returnfield.length; i++)
453
      {
454
        query.append("<returnfield>").append(returnfield[i]);
455
        query.append("</returnfield>");
456
      }
457
    }
458
    
459
    //if you don't limit the query by doctype, then it just creates
460
    //an empty returndoctype tag.
461
    if (!doctype.equals("any") && 
462
        !doctype.equals("ANY") &&
463
        !doctype.equals("") ) 
464
    {
465
       query.append("<returndoctype>");
466
       query.append(doctype).append("</returndoctype>");
467
    }
468
    else
469
    { 
470
      query.append("<returndoctype></returndoctype>");
471
    }
472
    
473
    //allows the dynamic switching of boolean operators
474
    if(params.containsKey("operator"))
475
    {
476
      query.append("<querygroup operator=\"" + 
477
    		        ((String[])params.get("operator"))[0] + "\">");
478
    }
479
    else
480
    { //the default operator is UNION
481
      query.append("<querygroup operator=\"UNION\">"); 
482
    }
483
    		
484
    if(params.containsKey("casesensitive"))
485
    {
486
      casesensitive = ((String[])params.get("casesensitive"))[0]; 
487
    }
488
    else
489
    {
490
      casesensitive = "false"; 
491
    }
492
    
493
    if(params.containsKey("searchmode"))
494
    {
495
      searchmode = ((String[])params.get("searchmode"))[0]; 
496
    }
497
    else
498
    {
499
      searchmode = "contains"; 
500
    }
501
    		
502
    //anyfield is a special case because it does a 
503
    //free text search.  It does not have a <pathexpr>
504
    //tag.  This allows for a free text search within the structured
505
    //query.  This is useful if the INTERSECT operator is used.
506
    if(params.containsKey("anyfield"))
507
    {
508
       String[] anyfield = ((String[])params.get("anyfield"));
509
       //allow for more than one value for anyfield
510
       for(int i=0; i<anyfield.length; i++)
511
       {
512
         if(!anyfield[i].equals(""))
513
         {
514
           query.append("<queryterm casesensitive=\"" + casesensitive + 
515
                        "\" " + "searchmode=\"" + searchmode + "\"><value>" +
516
    			              anyfield[i] +
517
    			              "</value></queryterm>"); 
518
         }
519
       }
520
    }
521
    		
522
    //this while loop finds the rest of the parameters
523
    //and attempts to query for the field specified
524
    //by the parameter.
525
    elements = params.elements();
526
    keys = params.keys();
527
    while(keys.hasMoreElements() && elements.hasMoreElements())
528
    {
529
      nextkey = keys.nextElement();
530
    	nextelement = elements.nextElement();
531

    
532
    	//make sure we aren't querying for any of these
533
    	//parameters since the are already in the query
534
      //in one form or another.
535
    	if(!nextkey.toString().equals("doctype") && 
536
    		 !nextkey.toString().equals("action")  &&
537
    		 !nextkey.toString().equals("qformat") && 
538
    		 !nextkey.toString().equals("anyfield") &&
539
         !nextkey.toString().equals("returnfield") &&
540
    		 !nextkey.toString().equals("operator") )
541
    	{
542
        //allow for more than value per field name
543
        for(int i=0; i<((String[])nextelement).length; i++)
544
        {
545
          if(!((String[])nextelement)[i].equals(""))
546
          {
547
            query.append("<queryterm casesensitive=\"" + casesensitive +"\" " + 
548
    				             "searchmode=\"" + searchmode + "\">" +
549
    		                 "<value>" +
550
                         //add the query value
551
    		                 ((String[])nextelement)[i] +
552
    		                 "</value><pathexpr>" +
553
    		                 //add the path to query by 
554
                         nextkey.toString() + 
555
                         "</pathexpr></queryterm>");
556
          }
557
        }
558
    	}
559
    }
560
    query.append("</querygroup></pathquery>");
561
    //append on the end of the xml and return the result as a string
562
    return query.toString();
563
  }
564
  
565
  /**
566
   * format a simple free-text value query as an XML document that conforms
567
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
568
   * structured query engine
569
   *
570
   * @param value the text string to search for in the xml catalog
571
   * @param doctype the type of documents to include in the result set -- use
572
   *        "any" or "ANY" for unfiltered result sets
573
   */
574
   public static String createQuery(String value, String doctype) {
575
     StringBuffer xmlquery = new StringBuffer();
576
     xmlquery.append("<?xml version=\"1.0\"?>\n");
577
     xmlquery.append("<pathquery version=\"1.0\">");
578
     xmlquery.append("<meta_file_id>Unspecified</meta_file_id>");
579
     xmlquery.append("<querytitle>Unspecified</querytitle>");
580

    
581
     if (!doctype.equals("any") && !doctype.equals("ANY")) {
582
       xmlquery.append("<returndoctype>");
583
       xmlquery.append(doctype).append("</returndoctype>");
584
     }
585

    
586
     xmlquery.append("<querygroup operator=\"UNION\">");
587
     //chad added - 8/14
588
     //the if statement allows a query to gracefully handle a null 
589
     //query.  Without this if a nullpointerException is thrown.
590
     if(!value.equals(""))
591
     {
592
       xmlquery.append("<queryterm casesensitive=\"false\" ");
593
       xmlquery.append("searchmode=\"contains\">");
594
       xmlquery.append("<value>").append(value).append("</value>");
595
       xmlquery.append("</queryterm>");
596
     }
597
     xmlquery.append("</querygroup>");
598
     xmlquery.append("</pathquery>");
599

    
600
     
601
     return (xmlquery.toString());
602
   }
603

    
604
  /**
605
   * format a simple free-text value query as an XML document that conforms
606
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
607
   * structured query engine
608
   *
609
   * @param value the text string to search for in the xml catalog
610
   */
611
   public static String createQuery(String value) {
612
     return createQuery(value, "any");
613
   }
614
   
615
  /** Check for "read" permissions from DB connection */
616
  private boolean hasReadPermission(Connection conn, String docid, 
617
                                     String user, String group) 
618
                                     throws SQLException {
619
    // b' of the command line invocation
620
    if ( (user == null) && (group == null) ) {
621
      return true;
622
    }
623
    
624
    PreparedStatement pstmt;
625
    // checking if user is owner of docid or if docid has public access
626
    try {
627
      pstmt = conn.prepareStatement(
628
                   "SELECT 'x' FROM xml_documents " +
629
                   "WHERE docid LIKE ? AND user_owner LIKE ? " + 
630
                   "UNION " +
631
                   "SELECT 'x' FROM xml_documents " +
632
                   "WHERE docid LIKE ? AND public_access = 1");
633
      // Bind the values to the query
634
      pstmt.setString(1, docid);
635
      pstmt.setString(2, user);
636
      pstmt.setString(3, docid);
637

    
638
      pstmt.execute();
639
      ResultSet rs = pstmt.getResultSet();
640
      boolean hasRow = rs.next();
641
      pstmt.close();
642
      if (hasRow) {
643
        return true;
644
      }
645
      
646
    } catch (SQLException e) {
647
      throw new 
648
        SQLException("Error checking document's owner or public access: "
649
                      + e.getMessage());
650
    }
651

    
652
    // checking if docid has public access at this time
653
    try {
654
      pstmt = conn.prepareStatement(
655
                   "SELECT 'x' FROM xml_access " +
656
                   "WHERE docid LIKE ? " +
657
                   "AND principal_name = 'public' " +
658
                   "AND principal_type = 'user' " +
659
                   "AND sysdate BETWEEN nvl(begin_time,sysdate) " +
660
                                   "AND nvl(end_time,sysdate)");
661
      // Bind the values to the query
662
      pstmt.setString(1, docid);
663

    
664
      pstmt.execute();
665
      ResultSet rs = pstmt.getResultSet();
666
      boolean hasRow = rs.next();
667
      pstmt.close();
668
      if (hasRow) {
669
        return true;
670
      }
671
      
672
    } catch (SQLException e) {
673
      throw new 
674
        SQLException("Error checking doc's public access: " + e.getMessage());
675
    }
676

    
677
    // checking access type from xml_access table
678
    int accesstype = 0;
679
    try {
680
      pstmt = conn.prepareStatement(
681
                   "SELECT access_type FROM xml_access " +
682
                   "WHERE docid LIKE ? " + 
683
                   "AND principal_name LIKE ? " +
684
                   "AND principal_type = 'user' " +
685
                   "AND sysdate BETWEEN nvl(begin_time,sysdate) " +
686
                                   "AND nvl(end_time,sysdate) " +
687
                   "UNION " +
688
                   "SELECT access_type FROM xml_access " +
689
                   "WHERE docid LIKE ? " + 
690
                   "AND principal_name LIKE ? " +
691
                   "AND principal_type = 'group' " +
692
                   "AND sysdate BETWEEN nvl(begin_time,sysdate) " +
693
                                   "AND nvl(end_time,sysdate)");
694
      // Bind the values to the query
695
      pstmt.setString(1, docid);
696
      pstmt.setString(2, user);
697
      pstmt.setString(3, docid);
698
      pstmt.setString(2, group);
699

    
700
      pstmt.execute();
701
      ResultSet rs = pstmt.getResultSet();
702
      boolean hasRows = rs.next();
703
      while ( hasRows ) {
704
        accesstype = rs.getInt(1);
705
        if ( (accesstype & READ) == READ ) {
706
          pstmt.close();
707
          return true;
708
        }
709
        hasRows = rs.next();
710
      }
711

    
712
      pstmt.close();
713
      return false;
714
      
715
    } catch (SQLException e) {
716
      throw new 
717
      SQLException("Error getting document's permissions: " + e.getMessage());
718
    }
719
  }
720
   
721
}
722

    
723
/**
724
 * '$Log$
725
 * 'Revision 1.23  2000/09/27 21:37:05  berkley
726
 * 'removed system.out.printlns
727
 * '
728
 * 'Revision 1.22  2000/09/27 20:11:17  berkley
729
 * 'added support for urls of the form "metacat://server.xyz.com?docid=XXX:yy"
730
 * '
731
 * 'Revision 1.21  2000/09/26 22:06:51  berkley
732
 * 'Added backtrack functionality.  Backtracking works by passing a returndoc parameter.  There can be more than one.  If a document that is hit by a query is not of type returndoc then it searches the database for a related file of type returndoc.  If one is found it is displayed, if no relation is found, the original is displayed.
733
 * '
734
 * 'Support was also added for an index of relations.  the table xml_relation handles the all of the relation indexing.
735
 * '
736
 * 'Revision 1.20  2000/09/15 19:52:11  berkley
737
 * 'Added functionality for package specifications.  metacatservlet now contains a new action called getrelateddocument that handles retrieving related documents using the metacatURL specification (metacatURL.java).  DBQuery contains new code in runQuery that embeds relation tags in the returned hashtable describing the documents related to each docid.  querySpecification contains a new method which prints the sql that does the relation query.
738
 * '
739
 * 'Revision 1.19  2000/09/12 17:37:07  bojilova
740
 * 'added check from "read" permission on "query" and "squery" actions
741
 * 'for connected user or for "public" connection
742
 * '
743
 * 'Revision 1.18  2000/09/05 20:50:56  berkley
744
 * 'Added a method called getNodeContent which retrieves the content of a node in a document.  If there are more than one nodes with the same name returned, it returns an array with all of the data.
745
 * '
746
 * 'Revision 1.17  2000/08/31 21:20:39  berkley
747
 * 'changed xslf for new returnfield scheme.  the returnfields are now returned as <param name="<returnfield>"> tags.
748
 * 'hThe sql for the returnfield query was redone to fix a previous problem with slow queries
749
 * '
750
 * 'Revision 1.16  2000/08/23 22:55:25  berkley
751
 * 'changed the field names to be case-sensitive in the returnfields
752
 * '
753
 * 'Revision 1.15  2000/08/23 17:22:07  berkley
754
 * 'added support for the returnfield parameter
755
 * '-added the dynamic parameters to the returned hash table of documents
756
 * '
757
 * 'Revision 1.14  2000/08/17 16:02:34  berkley
758
 * 'Made changes to createSQuery to allow for multiple parameters of the same name.  Also changed the param list to include only "Hashtable params" without a "String doctype" since the doctype is already contained in the params.
759
 * '
760
 * 'Revision 1.13  2000/08/14 21:26:12  berkley
761
 * 'Added createSQuery() to handle structured queries of an arbitrary number of parameters.  Also modified createQuery() to handle a null query in a graceful manner.
762
 * '
763
 * 'Revision 1.12  2000/08/14 20:53:33  jones
764
 * 'Added "release" keyword to all metacat source files so that the release
765
 * 'number will be evident in software distributions.
766
 * '
767
 * 'Revision 1.11  2000/08/11 18:26:07  berkley
768
 * 'added createSQuery
769
 * '
770
 * 'Revision 1.10  2000/07/26 20:40:41  higgins
771
 * 'no message
772
 * '
773
 * 'Revision 1.9  2000/06/26 10:35:04  jones
774
 * 'Merged in substantial changes to DBWriter and associated classes and to
775
 * 'the MetaCatServlet in order to accomodate the new UPDATE and DELETE
776
 * 'functions.  The command line tools and the parameters for the
777
 * 'servlet have changed substantially.
778
 * '
779
 * 'Revision 1.8.2.2  2000/06/25 23:38:16  jones
780
 * 'Added RCSfile keyword
781
 * '
782
 * 'Revision 1.8.2.1  2000/06/25 23:34:17  jones
783
 * 'Changed documentation formatting, added log entries at bottom of source files
784
 * ''
785
 */
(11-11/32)