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: tao $'
14
 *     '$Date: 2004-03-15 14:08:39 -0800 (Mon, 15 Mar 2004) $'
15
 * '$Revision: 2045 $'
16
 *
17
 * This program is free software; you can redistribute it and/or modify
18
 * it under the terms of the GNU General Public License as published by
19
 * the Free Software Foundation; either version 2 of the License, or
20
 * (at your option) any later version.
21
 *
22
 * This program is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
 * GNU General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU General Public License
28
 * along with this program; if not, write to the Free Software
29
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30
 */
31

    
32
package edu.ucsb.nceas.metacat;
33

    
34
import edu.ucsb.nceas.morpho.datapackage.*;
35
import java.io.*;
36
import java.util.StringTokenizer;
37
import java.util.Vector;
38
import java.util.zip.*;
39
import java.net.URL;
40
import java.net.MalformedURLException;
41
import java.sql.*;
42
import java.util.Stack;
43
import java.util.Hashtable;
44
import java.util.Enumeration;
45
import java.io.File;
46
import java.io.FileWriter;
47
import java.io.BufferedWriter;
48
import javax.servlet.ServletOutputStream;
49

    
50
/**
51
 * A Class that searches a relational DB for elements and
52
 * attributes that have free text matches a query string,
53
 * or structured query matches to a path specified node in the
54
 * XML hierarchy.  It returns a result set consisting of the
55
 * document ID for each document that satisfies the query
56
 */
57
public class DBQuery {
58

    
59
  static final int ALL = 1;
60
  static final int WRITE = 2;
61
  static final int READ = 4;
62

    
63
  //private Connection  conn = null;
64
  private String  parserName = null;
65
  private MetaCatUtil util = new MetaCatUtil();
66
  /**
67
   * the main routine used to test the DBQuery utility.
68
   * <p>
69
   * Usage: java DBQuery <xmlfile>
70
   *
71
   * @param xmlfile the filename of the xml file containing the query
72
   */
73
  static public void main(String[] args) {
74

    
75
     if (args.length < 1)
76
     {
77
        System.err.println("Wrong number of arguments!!!");
78
        System.err.println("USAGE: java DBQuery [-t] [-index] <xmlfile>");
79
        return;
80
     } else {
81
        try {
82

    
83
          int i = 0;
84
          boolean showRuntime = false;
85
          boolean useXMLIndex = false;
86
          if ( args[i].equals( "-t" ) ) {
87
            showRuntime = true;
88
            i++;
89
          }
90
          if ( args[i].equals( "-index" ) ) {
91
            useXMLIndex = true;
92
            i++;
93
          }
94
          String xmlfile  = args[i];
95

    
96
          // Time the request if asked for
97
          double startTime = System.currentTimeMillis();
98

    
99
          // Open a connection to the database
100
          MetaCatUtil   util = new MetaCatUtil();
101
          //Connection dbconn = util.openDBConnection();
102

    
103
          double connTime = System.currentTimeMillis();
104

    
105
          // Execute the query
106
          DBQuery queryobj = new DBQuery(util.getOption("saxparser"));
107
          FileReader xml = new FileReader(new File(xmlfile));
108
          Hashtable nodelist = null;
109
          nodelist = queryobj.findDocuments(xml, null, null, useXMLIndex);
110

    
111
          // Print the reulting document listing
112
          StringBuffer result = new StringBuffer();
113
          String document = null;
114
          String docid = null;
115
          result.append("<?xml version=\"1.0\"?>\n");
116
          result.append("<resultset>\n");
117

    
118
          if (!showRuntime)
119
          {
120
            Enumeration doclist = nodelist.keys();
121
            while (doclist.hasMoreElements()) {
122
              docid = (String)doclist.nextElement();
123
              document = (String)nodelist.get(docid);
124
              result.append("  <document>\n    " + document +
125
                            "\n  </document>\n");
126
            }
127

    
128
            result.append("</resultset>\n");
129
          }
130
          // Time the request if asked for
131
          double stopTime = System.currentTimeMillis();
132
          double dbOpenTime = (connTime - startTime)/1000;
133
          double readTime = (stopTime - connTime)/1000;
134
          double executionTime = (stopTime - startTime)/1000;
135
          if (showRuntime) {
136
            System.out.print("  " + executionTime);
137
            System.out.print("  " + dbOpenTime);
138
            System.out.print("  " + readTime);
139
            System.out.print("  " + nodelist.size());
140
            System.out.println();
141
          }
142
          //System.out.println(result);
143
          //write into a file "result.txt"
144
          if (!showRuntime)
145
          {
146
            File f = new File("./result.txt");
147
            FileWriter fw = new FileWriter(f);
148
            BufferedWriter out = new BufferedWriter(fw);
149
            out.write(result.toString());
150
            out.flush();
151
            out.close();
152
            fw.close();
153
          }
154

    
155
        }
156
        catch (Exception e) {
157
          System.err.println("Error in DBQuery.main");
158
          System.err.println(e.getMessage());
159
          e.printStackTrace(System.err);
160
        }
161
     }
162
  }
163

    
164
  /**
165
   * construct an instance of the DBQuery class
166
   *
167
   * <p>Generally, one would call the findDocuments() routine after creating
168
   * an instance to specify the search query</p>
169
   *
170
   * @param conn the JDBC connection that we use for the query
171
   * @param parserName the fully qualified name of a Java class implementing
172
   *                   the org.xml.sax.XMLReader interface
173
   */
174
  public DBQuery(String parserName )
175
                  throws IOException,
176
                         SQLException,
177
                         ClassNotFoundException {
178
    //this.conn = conn;
179
    this.parserName = parserName;
180
  }
181

    
182
  /**
183
   * routine to search the elements and attributes looking to match query
184
   *
185
   * @param xmlquery the xml serialization of the query (@see pathquery.dtd)
186
   * @param user the username of the user
187
   * @param group the group of the user
188
   */
189
  public Hashtable findDocuments(Reader xmlquery, String user, String[] groups)
190
  {
191
    return findDocuments(xmlquery, user, groups, true);
192
  }
193

    
194
  /**
195
   * routine to search the elements and attributes looking to match query
196
   *
197
   * @param xmlquery the xml serialization of the query (@see pathquery.dtd)
198
   * @param user the username of the user
199
   * @param group the group of the user
200
   * @param useXMLIndex flag whether to search using the path index
201
   */
202
  public Hashtable findDocuments(Reader xmlquery, String user, String[] groups,
203
                                 boolean useXMLIndex)
204
  {
205
      Hashtable result = new Hashtable();
206
      try
207
      {
208
        // Get the XML query and covert it into a SQL statment
209
        QuerySpecification qspec = new QuerySpecification(xmlquery,
210
                                   parserName,
211
                                   util.getOption("accNumSeparator"));
212
        result = findDocuments(qspec, user, groups, useXMLIndex);
213
      }
214
      catch (IOException ioe)
215
      {
216
        MetaCatUtil.debugMessage("IO error in DBQuery.findDocuments:", 30);
217
        MetaCatUtil.debugMessage(ioe.getMessage(), 30);
218
      }
219
      return result;
220
  }
221

    
222
  /**
223
   * routine to search the elements and attributes looking to match query
224
   *
225
   * @param qspec java object of the query
226
   * @param user the username of the user
227
   * @param group the group of the user
228
   * @param useXMLIndex flag whether to search using the path index
229
   */
230
  public Hashtable findDocuments(QuerySpecification qspec, String user,
231
                                  String[] groups, boolean useXMLIndex)
232
  {
233
      Hashtable   docListResult = new Hashtable();
234
      PreparedStatement pstmt = null;
235
      String docid = null;
236
      String docname = null;
237
      String doctype = null;
238
      String createDate = null;
239
      String updateDate = null;
240
      String fieldname = null;
241
      String fielddata = null;
242
      String relation = null;
243
      //Connection dbconn = null;
244
      //Connection dbconn2 = null;
245
      int rev = 0;
246
      StringBuffer document = null;
247
      DBConnection dbconn = null;
248
      int serialNumber = -1;
249

    
250
      try {
251

    
252

    
253
        dbconn=DBConnectionPool.getDBConnection("DBQuery.findDocuments");
254
        serialNumber=dbconn.getCheckOutSerialNumber();
255

    
256
        String query = qspec.printSQL(useXMLIndex);
257
        String ownerQuery = getOwnerQuery(user);
258
        MetaCatUtil.debugMessage("query: "+query, 30);
259
        //MetaCatUtil.debugMessage("query: "+ownerQuery, 30);
260
        // if query is not the owner query, we need to check the permission
261
        // otherwise we don't need (owner has all permission by default)
262
        if (!query.equals(ownerQuery))
263
        {
264
          // set user name and group
265
          qspec.setUserName(user);
266
          qspec.setGroup(groups);
267
          // Get access query
268
          String accessQuery = qspec.getAccessQuery();
269
          query = query + accessQuery;
270
          MetaCatUtil.debugMessage(" final query: "+query, 30);
271
        }
272

    
273
        double startTime = System.currentTimeMillis()/1000;
274
        pstmt = dbconn.prepareStatement(query);
275

    
276
        // Execute the SQL query using the JDBC connection
277
        pstmt.execute();
278
        ResultSet rs = pstmt.getResultSet();
279
        double queryExecuteTime =System.currentTimeMillis()/1000;
280
        MetaCatUtil.debugMessage("Time for execute query: "+
281
                                            (queryExecuteTime -startTime), 30);
282
        boolean tableHasRows = rs.next();
283
        while (tableHasRows)
284
        {
285
          docid = rs.getString(1).trim();
286
          //long checkTimeStart = System.currentTimeMillis();
287
          //boolean permit =hasPermission(user, groups, docid);
288
          //long checkTimeEnd = System.currentTimeMillis();
289
          //MetaCatUtil.debugMessage("check permission time: "+
290
                                  //(checkTimeEnd - checkTimeStart), 30);
291
          //if ( !permit ) {
292
            // Advance to the next record in the cursor
293
            //tableHasRows = rs.next();
294
            //continue;
295
          //}
296

    
297
          docname = rs.getString(2);
298
          doctype = rs.getString(3);
299
          createDate = rs.getString(4);
300
          updateDate = rs.getString(5);
301
          rev = rs.getInt(6);
302

    
303
          // if there are returndocs to match, backtracking can be performed
304
          // otherwise, just return the document that was hit
305
          Vector returndocVec = qspec.getReturnDocList();
306
          if (returndocVec.size() != 0 && !returndocVec.contains(doctype)
307
              && !qspec.isPercentageSearch())
308
          {
309
            MetaCatUtil.debugMessage("Back tracing now...", 20);
310
            String sep = util.getOption("accNumSeparator");
311
            StringBuffer btBuf = new StringBuffer();
312
            btBuf.append("select docid from xml_relation where ");
313

    
314
            //build the doctype list for the backtracking sql statement
315
            btBuf.append("packagetype in (");
316
            for(int i=0; i<returndocVec.size(); i++)
317
            {
318
              btBuf.append("'").append((String)returndocVec.get(i)).append("'");
319
              if (i != (returndocVec.size() - 1))
320
              {
321
                btBuf.append(", ");
322
              }
323
            }
324
            btBuf.append(") ");
325

    
326
            btBuf.append("and (subject like '");
327
            btBuf.append(docid).append("'");
328
            btBuf.append("or object like '");
329
            btBuf.append(docid).append("')");
330

    
331
            PreparedStatement npstmt = dbconn.
332
                                       prepareStatement(btBuf.toString());
333
            //should incease usage count
334
            dbconn.increaseUsageCount(1);
335
            npstmt.execute();
336
            ResultSet btrs = npstmt.getResultSet();
337
            boolean hasBtRows = btrs.next();
338
            while (hasBtRows)
339
            { //there was a backtrackable document found
340
              DocumentImpl xmldoc = null;
341
              String packageDocid = btrs.getString(1);
342
              util.debugMessage("Getting document for docid: "+packageDocid,40);
343
              try
344
              {
345
                //  THIS CONSTRUCTOR BUILDS THE WHOLE XML doc not needed here
346
                // xmldoc = new DocumentImpl(dbconn, packageDocid);
347
                //  thus use the following to get the doc info only
348
                //  xmldoc = new DocumentImpl(dbconn);
349
                xmldoc = new DocumentImpl(packageDocid, false);
350
                if (xmldoc == null) {
351
                  util.debugMessage("Document was null for: "+packageDocid, 50);
352
                }
353
              }
354
              catch(Exception e)
355
              {
356
                System.out.println("Error getting document in " +
357
                                   "DBQuery.findDocuments: " + e.getMessage());
358
              }
359

    
360
              String docid_org = xmldoc.getDocID();
361
              if (docid_org == null) {
362
                util.debugMessage("Docid_org was null.", 40);
363
              }
364
              docid   = docid_org.trim();
365
              docname = xmldoc.getDocname();
366
              doctype = xmldoc.getDoctype();
367
              createDate = xmldoc.getCreateDate();
368
              updateDate = xmldoc.getUpdateDate();
369
              rev = xmldoc.getRev();
370

    
371
              document = new StringBuffer();
372

    
373
              String completeDocid = docid + util.getOption("accNumSeparator");
374
              completeDocid += rev;
375
              document.append("<docid>").append(completeDocid);
376
              document.append("</docid>");
377
              if (docname != null) {
378
                document.append("<docname>" + docname + "</docname>");
379
              }
380
              if (doctype != null) {
381
                document.append("<doctype>" + doctype + "</doctype>");
382
              }
383
              if (createDate != null) {
384
                document.append("<createdate>" + createDate + "</createdate>");
385
              }
386
              if (updateDate != null) {
387
                document.append("<updatedate>" + updateDate + "</updatedate>");
388
              }
389
              // Store the document id and the root node id
390
              docListResult.put(docid,(String)document.toString());
391

    
392
              // Get the next package document linked to our hit
393
              hasBtRows = btrs.next();
394
            }
395
            npstmt.close();
396
            btrs.close();
397
          }
398
          else if (returndocVec.size() != 0 && returndocVec.contains(doctype))
399
          {
400

    
401
            document = new StringBuffer();
402

    
403
            String completeDocid = docid + util.getOption("accNumSeparator");
404
            completeDocid += rev;
405
            document.append("<docid>").append(completeDocid).append("</docid>");
406
            if (docname != null) {
407
              document.append("<docname>" + docname + "</docname>");
408
            }
409
            if (doctype != null) {
410
              document.append("<doctype>" + doctype + "</doctype>");
411
            }
412
            if (createDate != null) {
413
              document.append("<createdate>" + createDate + "</createdate>");
414
            }
415
            if (updateDate != null) {
416
              document.append("<updatedate>" + updateDate + "</updatedate>");
417
            }
418
            // Store the document id and the root node id
419
            docListResult.put(docid,(String)document.toString());
420

    
421
          }
422

    
423
          // Advance to the next record in the cursor
424
          tableHasRows = rs.next();
425
        }
426
        rs.close();
427
        pstmt.close();
428
        double docListTime =System.currentTimeMillis()/1000;
429
        MetaCatUtil.debugMessage("prepare docid list time: "
430
                                          +(docListTime-queryExecuteTime), 30);
431

    
432
        if (qspec.containsExtendedSQL())
433
        {
434
          Vector extendedFields = new Vector(qspec.getReturnFieldList());
435
          Vector results = new Vector();
436
          Enumeration keylist = docListResult.keys();
437
          StringBuffer doclist = new StringBuffer();
438
          Vector parentidList = new Vector();
439
          Hashtable returnFieldValue = new Hashtable();
440
          while(keylist.hasMoreElements())
441
          {
442
            doclist.append("'");
443
            doclist.append((String)keylist.nextElement());
444
            doclist.append("',");
445
          }
446
          if (doclist.length() > 0)
447
          {
448
            Hashtable controlPairs = new Hashtable();
449
            double extendedQueryStart = System.currentTimeMillis()/1000;
450
            doclist.deleteCharAt(doclist.length()-1); //remove the last comma
451
            // check if user has permission to see the return field data
452
            String accessControlSQL = qspec.
453
                        printAccessControlSQLForReturnField(doclist.toString());
454
            pstmt = dbconn.prepareStatement(accessControlSQL);
455
            //increase dbconnection usage count
456
            dbconn.increaseUsageCount(1);
457
            pstmt.execute();
458
            rs = pstmt.getResultSet();
459
            tableHasRows = rs.next();
460
            while(tableHasRows)
461
            {
462
              long startNodeId = rs.getLong(1);
463
              long endNodeId = rs.getLong(2);
464
              controlPairs.put(new Long(startNodeId), new Long(endNodeId));
465
              tableHasRows = rs.next();
466
            }
467

    
468
            double extendedAccessQueryEnd = System.currentTimeMillis()/1000;
469
            MetaCatUtil.debugMessage("Time for execute access extended query: "
470
                              +(extendedAccessQueryEnd-extendedQueryStart), 30);
471

    
472
            String extendedQuery = qspec.printExtendedSQL(doclist.toString(),
473
                                                          controlPairs);
474
            MetaCatUtil.debugMessage("Extended query: "+ extendedQuery, 30);
475
            pstmt = dbconn.prepareStatement(extendedQuery);
476
            //increase dbconnection usage count
477
            dbconn.increaseUsageCount(1);
478
            pstmt.execute();
479
            rs = pstmt.getResultSet();
480
            double extendedQueryEnd = System.currentTimeMillis()/1000;
481
            MetaCatUtil.debugMessage("Time for execute extended query: "
482
                                    +(extendedQueryEnd-extendedQueryStart), 30);
483
            tableHasRows = rs.next();
484
            while(tableHasRows)
485
            {
486
              ReturnFieldValue returnValue = new ReturnFieldValue();
487
              docid = rs.getString(1).trim();
488
              fieldname = rs.getString(2);
489
              fielddata = rs.getString(3);
490
              fielddata = MetaCatUtil.normalize(fielddata);
491

    
492
              String parentId = rs.getString(4);
493

    
494
              StringBuffer value = new StringBuffer();
495
              if (!containsKey(parentidList,parentId))
496
              {
497
                // don't need to merger nodedata
498
                value.append("<param name=\"");
499
                value.append(fieldname);
500
                value.append("\">");
501
                value.append(fielddata);
502
                value.append("</param>");
503
                //set returnvalue
504
                returnValue.setDocid(docid);
505
                returnValue.setFieldValue(fielddata);
506
                returnValue.setXMLFieldValue(value.toString());
507
                // Store it in hastable
508
                putInArray(parentidList, parentId, returnValue);
509
              }
510
              else
511
              {
512
                // need to merge nodedata if they have same parent id ant
513
                // node type is text
514
                fielddata = (String)((ReturnFieldValue)
515
                       getArrayValue(parentidList,parentId)).getFieldValue() +  fielddata;
516
                value.append("<param name=\"");
517
                value.append(fieldname);
518
                value.append("\">");
519
                value.append(fielddata);
520
                value.append("</param>");
521
                returnValue.setDocid(docid);
522
                returnValue.setFieldValue(fielddata);
523
                returnValue.setXMLFieldValue(value.toString());
524
                // remove the old return value from paretnidList
525
                parentidList.remove(parentId);
526
                // store the new return value in parentidlit
527
                putInArray(parentidList,parentId, returnValue);
528
              }
529
               tableHasRows = rs.next();
530
            }//while
531
            rs.close();
532
            pstmt.close();
533

    
534
            // put the merger node data info into doclistReult
535
            Enumeration xmlFieldValue = (getElements(parentidList)).elements();
536
            while( xmlFieldValue.hasMoreElements() )
537
            {
538
              ReturnFieldValue object = (ReturnFieldValue)
539
                                         xmlFieldValue.nextElement();
540
              docid = object.getDocid();
541
              if (docListResult.containsKey(docid))
542
              {
543
                  String removedelement = (String)docListResult.remove(docid);
544
                  docListResult.put(docid, removedelement +
545
                                    object.getXMLFieldValue());
546
              }
547
              else
548
              {
549
                  docListResult.put(docid, object.getXMLFieldValue());
550
              }
551
            }//while
552
            double docListResultEnd = System.currentTimeMillis()/1000;
553
            MetaCatUtil.debugMessage("Time for prepare doclistresult after"+
554
                                      " execute extended query: "
555
                                    +(docListResultEnd-extendedQueryEnd), 30);
556

    
557

    
558
            // get attribures return
559
            docListResult = getAttributeValueForReturn
560
                                      (qspec,docListResult, doclist.toString());
561
          }//if doclist lenght is great than zero
562

    
563
        }//if has extended query
564

    
565

    
566
        //this loop adds the relation data to the resultdoc
567
        //this code might be able to be added to the backtracking code above
568
        double startRelation = System.currentTimeMillis()/1000;
569
        Enumeration docidkeys = docListResult.keys();
570
        while(docidkeys.hasMoreElements())
571
        {
572
          //String connstring = "metacat://"+util.getOption("server")+"?docid=";
573
          String connstring = "%docid=";
574
          String docidkey = (String)docidkeys.nextElement();
575
          pstmt = dbconn.prepareStatement(qspec.printRelationSQL(docidkey));
576
          pstmt.execute();
577
          rs = pstmt.getResultSet();
578
          tableHasRows = rs.next();
579
          while(tableHasRows)
580
          {
581
            String sub = rs.getString(1);
582
            String rel = rs.getString(2);
583
            String obj = rs.getString(3);
584
            String subDT = rs.getString(4);
585
            String objDT = rs.getString(5);
586

    
587
            document = new StringBuffer();
588
            document.append("<triple>");
589
            document.append("<subject>").append(MetaCatUtil.normalize(sub));
590
            document.append("</subject>");
591
            if ( subDT != null ) {
592
              document.append("<subjectdoctype>").append(subDT);
593
              document.append("</subjectdoctype>");
594
            }
595
            document.append("<relationship>").
596
                                          append(MetaCatUtil.normalize(rel));
597
            document.append("</relationship>");
598
            document.append("<object>").append(MetaCatUtil.normalize(obj));
599
            document.append("</object>");
600
            if ( objDT != null ) {
601
              document.append("<objectdoctype>").append(objDT);
602
              document.append("</objectdoctype>");
603
            }
604
            document.append("</triple>");
605

    
606
            String removedelement = (String)docListResult.remove(docidkey);
607
            docListResult.put(docidkey, removedelement +
608
                              document.toString());
609
            tableHasRows = rs.next();
610
          }
611
          rs.close();
612
          pstmt.close();
613
        }
614
        double endRelation = System.currentTimeMillis()/1000;
615
        MetaCatUtil.debugMessage("Time for adding relation to docListResult: "+
616
                                (endRelation-startRelation), 30);
617

    
618
      } catch (SQLException e) {
619
        System.err.println("SQL Error in DBQuery.findDocuments: " +
620
                           e.getMessage());
621
      } catch (Exception ee) {
622
        System.err.println("Exception in DBQuery.findDocuments: " +
623
                           ee.getMessage());
624
        ee.printStackTrace(System.err);
625
      }
626
      finally
627
      {
628
        try
629
        {
630
          pstmt.close();
631
        }//try
632
        catch (SQLException sqlE)
633
        {
634
          MetaCatUtil.debugMessage("Error in DBQuery.findDocuments: "
635
                                      +sqlE.getMessage(), 30);
636
        }//catch
637
        finally
638
        {
639
          DBConnectionPool.returnDBConnection(dbconn, serialNumber);
640
        }//finally
641
      }//finally
642
    //System.out.println("docListResult: ");
643
    //System.out.println(docListResult.toString());
644
    return docListResult;
645
  }
646

    
647
  /*
648
   * A method to search if Vector contains a particular key string
649
   */
650
  private boolean containsKey(Vector parentidList,String parentId){
651

    
652
    Vector tempVector = null;
653

    
654
    for(int count = 0; count < parentidList.size(); count++){
655
      tempVector = (Vector)parentidList.get(count);
656
      if(parentId.compareTo((String)tempVector.get(0)) == 0){
657
        return false;
658
      }
659
    }
660
    return false;
661
  }
662

    
663
  /*
664
   * A method to put key and value in Vector
665
   */
666
  private void putInArray(Vector parentidList, String key,
667
                          ReturnFieldValue value){
668

    
669
    Vector tempVector = null;
670

    
671
    for(int count = 0; count < parentidList.size(); count++){
672
      tempVector = (Vector)parentidList.get(count);
673

    
674
      if(key.compareTo((String)tempVector.get(0)) == 0){
675
        tempVector.remove(1);
676
        tempVector.add(1, value);
677
        return;
678
      }
679
    }
680

    
681
    tempVector = new Vector();
682
    tempVector.add(0, key);
683
    tempVector.add(1, value);
684
    parentidList.add(tempVector);
685
    return;
686
  }
687

    
688
  /*
689
   * A method to get value in Vector given a key
690
   */
691
  private ReturnFieldValue getArrayValue(Vector parentidList,
692
                                         String key){
693

    
694
    Vector tempVector = null;
695

    
696
    for(int count = 0; count < parentidList.size(); count++){
697
      tempVector = (Vector)parentidList.get(count);
698

    
699
      if(key.compareTo((String)tempVector.get(0)) == 0){
700
        return (ReturnFieldValue)tempVector.get(1);
701
      }
702
    }
703
    return null;
704
  }
705

    
706
  /*
707
   * A method to get enumeration of all values in Vector
708
   */
709
  private Vector getElements(Vector parentidList){
710
    Vector enum = new Vector();
711
    Vector tempVector = null;
712

    
713
    for(int count = 0; count < parentidList.size(); count++){
714
      tempVector = (Vector)parentidList.get(count);
715

    
716
      enum.add(tempVector.get(1));
717
    }
718
    return enum;
719
  }
720

    
721
  /*
722
   * A method to return search result after running a query which return
723
   * field have attribue
724
   */
725
  private Hashtable getAttributeValueForReturn(QuerySpecification squery,
726
                                               Hashtable docInformationList,
727
                                               String docList)
728
  {
729
    StringBuffer XML = null;
730
    String sql = null;
731
    DBConnection dbconn = null;
732
    PreparedStatement pstmt = null;
733
    ResultSet rs = null;
734
    int serialNumber = -1;
735
    boolean tableHasRows =false;
736

    
737
    //check the parameter
738
    if (squery == null || docList==null || docList.length() <0)
739
    {
740
      return docInformationList;
741
    }
742

    
743
    // if has attribute as return field
744
    if (squery.containAttributeReturnField())
745
    {
746
      sql = squery.printAttributeQuery(docList);
747
      try
748
      {
749
        dbconn=DBConnectionPool.getDBConnection("DBQuery.getAttributeValue");
750
        serialNumber=dbconn.getCheckOutSerialNumber();
751
        pstmt = dbconn.prepareStatement(sql);
752
        pstmt.execute();
753
        rs = pstmt.getResultSet();
754
        tableHasRows = rs.next();
755
        while(tableHasRows)
756
        {
757
          String docid = rs.getString(1).trim();
758
          String fieldname = rs.getString(2);
759
          String fielddata = rs.getString(3);
760
          String attirbuteName = rs.getString(4);
761
          XML = new StringBuffer();
762

    
763
          XML.append("<param name=\"");
764
          XML.append(fieldname);
765
          XML.append(QuerySpecification.ATTRIBUTESYMBOL);
766
          XML.append(attirbuteName);
767
          XML.append("\">");
768
          XML.append(fielddata);
769
          XML.append("</param>");
770
          tableHasRows = rs.next();
771

    
772
          if (docInformationList.containsKey(docid))
773
          {
774
            String removedelement = (String)docInformationList.remove(docid);
775
            docInformationList.put(docid, removedelement + XML.toString());
776
          }
777
          else
778
          {
779
            docInformationList.put(docid, XML.toString());
780
          }
781
        }//while
782
        rs.close();
783
        pstmt.close();
784
      }
785
      catch(Exception se)
786
      {
787
        MetaCatUtil.debugMessage("Error in DBQuery.getAttributeValue1: "
788
                                      +se.getMessage(), 30);
789
      }
790
      finally
791
      {
792
        try
793
        {
794
          pstmt.close();
795
        }//try
796
        catch (SQLException sqlE)
797
        {
798
          MetaCatUtil.debugMessage("Error in DBQuery.getAttributeValue2: "
799
                                      +sqlE.getMessage(), 30);
800
        }//catch
801
        finally
802
        {
803
          DBConnectionPool.returnDBConnection(dbconn, serialNumber);
804
        }//finally
805
      }//finally
806
    }//if
807
    return docInformationList;
808

    
809
  }
810

    
811

    
812
  /*
813
   * A method to create a query to get owner's docid list
814
   */
815
  private String getOwnerQuery(String owner)
816
  {
817
    if (owner != null)
818
    {
819
      owner = owner.toLowerCase();
820
    }
821
    StringBuffer self = new StringBuffer();
822
  
823
    self.append("SELECT docid,docname,doctype,");
824
    self.append("date_created, date_updated, rev ");
825
    self.append("FROM xml_documents WHERE docid IN (");
826
    self.append("(");
827
    self.append("SELECT DISTINCT docid FROM xml_nodes WHERE \n");
828
    self.append("nodedata LIKE '%%%' ");
829
    self.append(") \n");
830
    self.append(") ");
831
    self.append(" AND (");
832
    self.append(" lower(user_owner) = '" + owner + "'");
833
    self.append(") ");
834
    return self.toString();
835
  }
836
  /**
837
   * returns a string array of the contents of a particular node.
838
   * If the node appears more than once, the contents are returned
839
   * in the order in which they appearred in the document.
840
   * @param nodename the name or path of the particular node.
841
   * @param docid the docid of the document you want the node from.
842
   */
843
  public static Object[] getNodeContent(String nodename, String docid)
844
  {
845
    DBConnection dbconn = null;
846
    int serialNumber = -1;
847
    StringBuffer query = new StringBuffer();
848
    Vector result = new Vector();
849
    PreparedStatement pstmt = null;
850
    query.append("select nodedata from xml_nodes where parentnodeid in ");
851
    query.append("(select nodeid from xml_index where path like '");
852
    query.append(nodename);
853
    query.append("' and docid like '").append(docid).append("')");
854
    try
855
    {
856
      dbconn=DBConnectionPool.getDBConnection("DBQuery.getNodeContent");
857
        serialNumber=dbconn.getCheckOutSerialNumber();
858
      pstmt = dbconn.prepareStatement(query.toString());
859

    
860
      // Execute the SQL query using the JDBC connection
861
      pstmt.execute();
862
      ResultSet rs = pstmt.getResultSet();
863
      boolean tableHasRows = rs.next();
864
      while (tableHasRows)
865
      {
866
        result.add(rs.getString(1));
867
        //System.out.println(rs.getString(1));
868
        tableHasRows = rs.next();
869
      }
870
    }
871
    catch (SQLException e)
872
    {
873
      System.err.println("Error in DBQuery.getNodeContent: " + e.getMessage());
874
    } finally {
875
      try
876
      {
877
        pstmt.close();
878
      }
879
      catch(SQLException sqle)
880
      {}
881
      finally
882
      {
883
        DBConnectionPool.returnDBConnection(dbconn, serialNumber);
884
      }
885

    
886
    }
887
    return result.toArray();
888
  }
889

    
890
  /**
891
   * format a structured query as an XML document that conforms
892
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
893
   * structured query engine
894
   *
895
   * @param params The list of parameters that should be included in the query
896
   */
897
  public static String createSQuery(Hashtable params)
898
  {
899
    StringBuffer query = new StringBuffer();
900
    Enumeration elements;
901
    Enumeration keys;
902
    String filterDoctype = null;
903
    String casesensitive = null;
904
    String searchmode = null;
905
    Object nextkey;
906
    Object nextelement;
907
    //add the xml headers
908
    query.append("<?xml version=\"1.0\"?>\n");
909
    query.append("<pathquery version=\"1.0\">\n");
910

    
911
    if (params.containsKey("meta_file_id"))
912
    {
913
      query.append("<meta_file_id>");
914
      query.append( ((String[])params.get("meta_file_id"))[0]);
915
      query.append("</meta_file_id>");
916
    }
917

    
918
    if (params.containsKey("returndoctype"))
919
    {
920
      String[] returnDoctypes = ((String[])params.get("returndoctype"));
921
      for(int i=0; i<returnDoctypes.length; i++)
922
      {
923
        String doctype = (String)returnDoctypes[i];
924

    
925
        if (!doctype.equals("any") &&
926
            !doctype.equals("ANY") &&
927
            !doctype.equals("") )
928
        {
929
          query.append("<returndoctype>").append(doctype);
930
          query.append("</returndoctype>");
931
        }
932
      }
933
    }
934

    
935
    if (params.containsKey("filterdoctype"))
936
    {
937
      String[] filterDoctypes = ((String[])params.get("filterdoctype"));
938
      for(int i=0; i<filterDoctypes.length; i++)
939
      {
940
        query.append("<filterdoctype>").append(filterDoctypes[i]);
941
        query.append("</filterdoctype>");
942
      }
943
    }
944

    
945
    if (params.containsKey("returnfield"))
946
    {
947
      String[] returnfield = ((String[])params.get("returnfield"));
948
      for(int i=0; i<returnfield.length; i++)
949
      {
950
        query.append("<returnfield>").append(returnfield[i]);
951
        query.append("</returnfield>");
952
      }
953
    }
954

    
955
    if (params.containsKey("owner"))
956
    {
957
      String[] owner = ((String[])params.get("owner"));
958
      for(int i=0; i<owner.length; i++)
959
      {
960
        query.append("<owner>").append(owner[i]);
961
        query.append("</owner>");
962
      }
963
    }
964

    
965
    if (params.containsKey("site"))
966
    {
967
      String[] site = ((String[])params.get("site"));
968
      for(int i=0; i<site.length; i++)
969
      {
970
        query.append("<site>").append(site[i]);
971
        query.append("</site>");
972
      }
973
    }
974

    
975
    //allows the dynamic switching of boolean operators
976
    if (params.containsKey("operator"))
977
    {
978
      query.append("<querygroup operator=\"" +
979
                ((String[])params.get("operator"))[0] + "\">");
980
    }
981
    else
982
    { //the default operator is UNION
983
      query.append("<querygroup operator=\"UNION\">");
984
    }
985

    
986
    if (params.containsKey("casesensitive"))
987
    {
988
      casesensitive = ((String[])params.get("casesensitive"))[0];
989
    }
990
    else
991
    {
992
      casesensitive = "false";
993
    }
994

    
995
    if (params.containsKey("searchmode"))
996
    {
997
      searchmode = ((String[])params.get("searchmode"))[0];
998
    }
999
    else
1000
    {
1001
      searchmode = "contains";
1002
    }
1003

    
1004
    //anyfield is a special case because it does a
1005
    //free text search.  It does not have a <pathexpr>
1006
    //tag.  This allows for a free text search within the structured
1007
    //query.  This is useful if the INTERSECT operator is used.
1008
    if (params.containsKey("anyfield"))
1009
    {
1010
       String[] anyfield = ((String[])params.get("anyfield"));
1011
       //allow for more than one value for anyfield
1012
       for(int i=0; i<anyfield.length; i++)
1013
       {
1014
         if (!anyfield[i].equals(""))
1015
         {
1016
           query.append("<queryterm casesensitive=\"" + casesensitive +
1017
                        "\" " + "searchmode=\"" + searchmode + "\"><value>" +
1018
                        anyfield[i] +
1019
                        "</value></queryterm>");
1020
         }
1021
       }
1022
    }
1023

    
1024
    //this while loop finds the rest of the parameters
1025
    //and attempts to query for the field specified
1026
    //by the parameter.
1027
    elements = params.elements();
1028
    keys = params.keys();
1029
    while(keys.hasMoreElements() && elements.hasMoreElements())
1030
    {
1031
      nextkey = keys.nextElement();
1032
      nextelement = elements.nextElement();
1033

    
1034
      //make sure we aren't querying for any of these
1035
      //parameters since the are already in the query
1036
      //in one form or another.
1037
      Vector ignoredParams = new Vector();
1038
      ignoredParams.add("returndoctype");
1039
      ignoredParams.add("filterdoctype");
1040
      ignoredParams.add("action");
1041
      ignoredParams.add("qformat");
1042
      ignoredParams.add("anyfield");
1043
      ignoredParams.add("returnfield");
1044
      ignoredParams.add("owner");
1045
      ignoredParams.add("site");
1046
      ignoredParams.add("operator");
1047

    
1048
      // Also ignore parameters listed in the properties file
1049
      // so that they can be passed through to stylesheets
1050
      String paramsToIgnore = MetaCatUtil.getOption("query.ignored.params");
1051
      StringTokenizer st = new StringTokenizer(paramsToIgnore, ",");
1052
      while (st.hasMoreTokens()) {
1053
          ignoredParams.add(st.nextToken());
1054
      }
1055
      if (!ignoredParams.contains(nextkey.toString())) {
1056
        //allow for more than value per field name
1057
        for(int i=0; i<((String[])nextelement).length; i++) {
1058
          if (!((String[])nextelement)[i].equals("")) {
1059
            query.append("<queryterm casesensitive=\"" + casesensitive +"\" " +
1060
                         "searchmode=\"" + searchmode + "\">" +
1061
                         "<value>" +
1062
                         //add the query value
1063
                         ((String[])nextelement)[i] +
1064
                         "</value><pathexpr>" +
1065
                         //add the path to query by
1066
                         nextkey.toString() +
1067
                         "</pathexpr></queryterm>");
1068
          }
1069
        }
1070
      }
1071
    }
1072
    query.append("</querygroup></pathquery>");
1073
    //append on the end of the xml and return the result as a string
1074
    return query.toString();
1075
  }
1076

    
1077
  /**
1078
   * format a simple free-text value query as an XML document that conforms
1079
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
1080
   * structured query engine
1081
   *
1082
   * @param value the text string to search for in the xml catalog
1083
   * @param doctype the type of documents to include in the result set -- use
1084
   *        "any" or "ANY" for unfiltered result sets
1085
   */
1086
   public static String createQuery(String value, String doctype) {
1087
     StringBuffer xmlquery = new StringBuffer();
1088
     xmlquery.append("<?xml version=\"1.0\"?>\n");
1089
     xmlquery.append("<pathquery version=\"1.0\">");
1090

    
1091
     if (!doctype.equals("any") && !doctype.equals("ANY")) {
1092
       xmlquery.append("<returndoctype>");
1093
       xmlquery.append(doctype).append("</returndoctype>");
1094
     }
1095

    
1096
     xmlquery.append("<querygroup operator=\"UNION\">");
1097
     //chad added - 8/14
1098
     //the if statement allows a query to gracefully handle a null
1099
     //query.  Without this if a nullpointerException is thrown.
1100
     if (!value.equals(""))
1101
     {
1102
       xmlquery.append("<queryterm casesensitive=\"false\" ");
1103
       xmlquery.append("searchmode=\"contains\">");
1104
       xmlquery.append("<value>").append(value).append("</value>");
1105
       xmlquery.append("</queryterm>");
1106
     }
1107
     xmlquery.append("</querygroup>");
1108
     xmlquery.append("</pathquery>");
1109

    
1110

    
1111
     return (xmlquery.toString());
1112
   }
1113

    
1114
  /**
1115
   * format a simple free-text value query as an XML document that conforms
1116
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
1117
   * structured query engine
1118
   *
1119
   * @param value the text string to search for in the xml catalog
1120
   */
1121
   public static String createQuery(String value) {
1122
     return createQuery(value, "any");
1123
   }
1124

    
1125
  /**
1126
    * Check for "READ" permission on @docid for @user and/or @group
1127
    * from DB connection
1128
    */
1129
  private boolean hasPermission (String user,
1130
                                  String[] groups, String docid )
1131
                  throws SQLException, Exception
1132
  {
1133
    // Check for READ permission on @docid for @user and/or @groups
1134
   PermissionController controller = new PermissionController(docid);
1135
   return controller.hasPermission(user,groups,
1136
                                 AccessControlInterface.READSTRING);
1137
  }
1138

    
1139
  /**
1140
    * Get all docIds list for a data packadge
1141
    * @param dataPackageDocid, the string in docId field of xml_relation table
1142
    */
1143
  private Vector getCurrentDocidListForDataPackage(String dataPackageDocid)
1144
  {
1145
    DBConnection dbConn = null;
1146
    int serialNumber = -1;
1147
    Vector docIdList=new Vector();//return value
1148
    PreparedStatement pStmt = null;
1149
    ResultSet rs=null;
1150
    String docIdInSubjectField=null;
1151
    String docIdInObjectField=null;
1152

    
1153
    // Check the parameter
1154
    if (dataPackageDocid == null || dataPackageDocid.equals(""))
1155
    {
1156
      return docIdList;
1157
    }//if
1158

    
1159
    //the query stirng
1160
    String query="SELECT subject, object from xml_relation where docId = ?";
1161
    try
1162
    {
1163
      dbConn=DBConnectionPool.
1164
                  getDBConnection("DBQuery.getCurrentDocidListForDataPackage");
1165
      serialNumber=dbConn.getCheckOutSerialNumber();
1166
      pStmt=dbConn.prepareStatement(query);
1167
      //bind the value to query
1168
      pStmt.setString(1, dataPackageDocid);
1169

    
1170
      //excute the query
1171
      pStmt.execute();
1172
      //get the result set
1173
      rs=pStmt.getResultSet();
1174
      //process the result
1175
      while (rs.next())
1176
      {
1177
        //In order to get the whole docIds in a data packadge,
1178
        //we need to put the docIds of subject and object field in xml_relation
1179
        //into the return vector
1180
        docIdInSubjectField=rs.getString(1);//the result docId in subject field
1181
        docIdInObjectField=rs.getString(2);//the result docId in object field
1182

    
1183
        //don't put the duplicate docId into the vector
1184
        if (!docIdList.contains(docIdInSubjectField))
1185
        {
1186
          docIdList.add(docIdInSubjectField);
1187
        }
1188

    
1189
        //don't put the duplicate docId into the vector
1190
        if (!docIdList.contains(docIdInObjectField))
1191
        {
1192
          docIdList.add(docIdInObjectField);
1193
        }
1194
      }//while
1195
      //close the pStmt
1196
      pStmt.close();
1197
    }//try
1198
    catch (SQLException e)
1199
    {
1200
      MetaCatUtil.debugMessage("Error in getDocidListForDataPackage: "
1201
                            +e.getMessage(), 30);
1202
    }//catch
1203
    finally
1204
    {
1205
      try
1206
      {
1207
        pStmt.close();
1208
      }//try
1209
      catch (SQLException ee)
1210
      {
1211
        MetaCatUtil.debugMessage("Error in getDocidListForDataPackage: "
1212
                            +ee.getMessage(), 30);
1213
      }//catch
1214
      finally
1215
      {
1216
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1217
      }//fianlly
1218
    }//finally
1219
    return docIdList;
1220
  }//getCurrentDocidListForDataPackadge()
1221

    
1222
  /**
1223
   * Get all docIds list for a data packadge
1224
   * @param dataPackageDocid, the string in docId field of xml_relation table
1225
   */
1226
  private Vector getOldVersionDocidListForDataPackage(String dataPackageDocid)
1227
  {
1228

    
1229
    Vector docIdList=new Vector();//return value
1230
    Vector tripleList=null;
1231
    String xml=null;
1232

    
1233
     // Check the parameter
1234
    if (dataPackageDocid == null || dataPackageDocid.equals(""))
1235
    {
1236
      return docIdList;
1237
    }//if
1238

    
1239
    try
1240
    {
1241
      //initial a documentImpl object
1242
      DocumentImpl packageDocument =
1243
                  new DocumentImpl(dataPackageDocid);
1244
      //transfer to documentImpl object to string
1245
      xml=packageDocument.toString();
1246

    
1247
      //create a tripcollection object
1248
      TripleCollection tripleForPackage = new
1249
                                     TripleCollection(new StringReader(xml));
1250
      //get the vetor of triples
1251
      tripleList=tripleForPackage.getCollection();
1252

    
1253
      for (int i= 0; i<tripleList.size(); i++)
1254
      {
1255
        //put subject docid  into docIdlist without duplicate
1256
        if (!docIdList.contains(((Triple)tripleList.elementAt(i)).getSubject()))
1257
        {
1258
          //put subject docid  into docIdlist
1259
          docIdList.add(((Triple)tripleList.get(i)).getSubject());
1260
        }
1261
        //put object docid into docIdlist without duplicate
1262
        if (!docIdList.contains(((Triple)tripleList.elementAt(i)).getObject()))
1263
        {
1264
          docIdList.add(((Triple)(tripleList.get(i))).getObject());
1265
        }
1266
      }//for
1267
    }//try
1268
    catch (Exception e)
1269
    {
1270
      MetaCatUtil.debugMessage("Error in getOldVersionAllDocumentImpl: "
1271
                            +e.getMessage(), 30);
1272
    }//catch
1273

    
1274
    // return result
1275
    return docIdList;
1276
  }//getDocidListForPackageInXMLRevisions()
1277

    
1278
  /**
1279
   * Check if the docId is a data packadge id. If the id is a data packadage
1280
   *id, it should be store in the docId fields in xml_relation table.
1281
   *So we can use a query to get the entries which the docId equals the given
1282
   *value. If the result is null. The docId is not a packadge id. Otherwise,
1283
   * it is.
1284
   * @param docId, the id need to be checked
1285
   */
1286
  private boolean isDataPackageId(String docId)
1287
  {
1288
    boolean result=false;
1289
    PreparedStatement pStmt = null;
1290
    ResultSet rs=null;
1291
    String query="SELECT docId from xml_relation where docId = ?";
1292
    DBConnection dbConn = null;
1293
    int serialNumber = -1;
1294
    try
1295
    {
1296
      dbConn=DBConnectionPool.
1297
                  getDBConnection("DBQuery.isDataPackageId");
1298
      serialNumber=dbConn.getCheckOutSerialNumber();
1299
      pStmt=dbConn.prepareStatement(query);
1300
      //bind the value to query
1301
      pStmt.setString(1, docId);
1302
      //execute the query
1303
      pStmt.execute();
1304
      rs=pStmt.getResultSet();
1305
      //process the result
1306
      if (rs.next()) //There are some records for the id in docId fields
1307
      {
1308
        result=true;//It is a data packadge id
1309
      }
1310
      pStmt.close();
1311
    }//try
1312
    catch (SQLException e)
1313
    {
1314
      util.debugMessage("Error in isDataPackageId: "
1315
                            +e.getMessage(), 30);
1316
    }
1317
    finally
1318
    {
1319
      try
1320
      {
1321
        pStmt.close();
1322
      }//try
1323
      catch (SQLException ee)
1324
      {
1325
        MetaCatUtil.debugMessage("Error in isDataPackageId: "
1326
                                                        + ee.getMessage(), 30);
1327
      }//catch
1328
      finally
1329
      {
1330
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1331
      }//finally
1332
    }//finally
1333
    return result;
1334
  }//isDataPackageId()
1335

    
1336
  /**
1337
   * Check if the user has the permission to export data package
1338
   * @param conn, the connection
1339
   * @param docId, the id need to be checked
1340
   * @param user, the name of user
1341
   * @param groups, the user's group
1342
   */
1343
   private boolean hasPermissionToExportPackage(String docId,
1344
                                        String user, String[] groups)
1345
                   throws Exception
1346
   {
1347
     //DocumentImpl doc=new DocumentImpl(conn,docId);
1348
     return DocumentImpl.hasReadPermission(user, groups,docId);
1349
   }
1350

    
1351
  /**
1352
   *Get the current Rev for a docid in xml_documents table
1353
   * @param docId, the id need to get version numb
1354
   * If the return value is -5, means no value in rev field for this docid
1355
   */
1356
  private int getCurrentRevFromXMLDoumentsTable(String docId)
1357
                                                throws SQLException
1358
  {
1359
    int rev=-5;
1360
    PreparedStatement pStmt = null;
1361
    ResultSet rs=null;
1362
    String query="SELECT rev from xml_documents where docId = ?";
1363
    DBConnection dbConn=null;
1364
    int serialNumber = -1;
1365
    try
1366
    {
1367
      dbConn=DBConnectionPool.
1368
                  getDBConnection("DBQuery.getCurrentRevFromXMLDocumentsTable");
1369
      serialNumber=dbConn.getCheckOutSerialNumber();
1370
      pStmt=dbConn.prepareStatement(query);
1371
      //bind the value to query
1372
      pStmt.setString(1, docId);
1373
      //execute the query
1374
      pStmt.execute();
1375
      rs=pStmt.getResultSet();
1376
      //process the result
1377
      if (rs.next()) //There are some records for rev
1378
      {
1379
        rev=rs.getInt(1);;//It is the version for given docid
1380
      }
1381
      else
1382
      {
1383
        rev=-5;
1384
      }
1385

    
1386
    }//try
1387
    catch (SQLException e)
1388
    {
1389
      MetaCatUtil.debugMessage("Error in getCurrentRevFromXMLDoumentsTable: "
1390
                            +e.getMessage(), 30);
1391
      throw e;
1392
    }//catch
1393
    finally
1394
    {
1395
      try
1396
      {
1397
        pStmt.close();
1398
      }//try
1399
      catch (SQLException ee)
1400
      {
1401
        MetaCatUtil.debugMessage("Error in getCurrentRevFromXMLDoumentsTable: "
1402
                                  +ee.getMessage(), 30);
1403
      }//catch
1404
      finally
1405
      {
1406
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1407
      }//finally
1408
    }//finally
1409
    return rev;
1410
  }//getCurrentRevFromXMLDoumentsTable
1411

    
1412
 /**
1413
   *put a doc into a zip output stream
1414
   *@param docImpl, docmentImpl object which will be sent to zip output stream
1415
   *@param zipOut, zip output stream which the docImpl will be put
1416
   *@param packageZipEntry, the zip entry name for whole package
1417
   */
1418
  private void addDocToZipOutputStream(DocumentImpl docImpl,
1419
                                ZipOutputStream zipOut, String packageZipEntry)
1420
               throws ClassNotFoundException, IOException, SQLException,
1421
                      McdbException, Exception
1422
  {
1423
    byte[] byteString = null;
1424
    ZipEntry zEntry = null;
1425

    
1426
    byteString = docImpl.toString().getBytes();
1427
    //use docId as the zip entry's name
1428
    zEntry = new ZipEntry(packageZipEntry+"/metadata/"+docImpl.getDocID());
1429
    zEntry.setSize(byteString.length);
1430
    zipOut.putNextEntry(zEntry);
1431
    zipOut.write(byteString, 0, byteString.length);
1432
    zipOut.closeEntry();
1433

    
1434
  }//addDocToZipOutputStream()
1435

    
1436

    
1437
  /**
1438
   * Transfer a docid vetor to a documentImpl vector. The documentImpl vetor
1439
   * only inlcudes current version. If a DocumentImple object
1440
   * couldn't find for a docid, then the String of this docid was added to vetor
1441
   * rather than DocumentImple object.
1442
   * @param docIdList, a vetor hold a docid list for a data package. In docid,
1443
   * there is not version number in it.
1444
   */
1445

    
1446
  private Vector getCurrentAllDocumentImpl( Vector docIdList)
1447
                              throws McdbException,Exception
1448
  {
1449
    //Connection dbConn=null;
1450
    Vector documentImplList=new Vector();
1451
    int rev=0;
1452

    
1453
    // Check the parameter
1454
    if (docIdList.isEmpty())
1455
    {
1456
      return documentImplList;
1457
    }//if
1458

    
1459
    //for every docid in vector
1460
    for (int i=0;i<docIdList.size();i++)
1461
    {
1462
      try
1463
      {
1464
        //get newest version for this docId
1465
        rev=getCurrentRevFromXMLDoumentsTable((String)docIdList.elementAt(i));
1466

    
1467
        // There is no record for this docId in xml_documents table
1468
        if (rev ==-5)
1469
        {
1470
          // Rather than put DocumentImple object, put a String Object(docid)
1471
          // into the documentImplList
1472
          documentImplList.add((String)docIdList.elementAt(i));
1473
          // Skip other code
1474
          continue;
1475
        }
1476

    
1477
        String docidPlusVersion=((String)docIdList.elementAt(i))
1478
                        +util.getOption("accNumSeparator")+rev;
1479

    
1480

    
1481
        //create new documentImpl object
1482
        DocumentImpl documentImplObject =
1483
                                    new DocumentImpl(docidPlusVersion);
1484
       //add them to vector
1485
        documentImplList.add(documentImplObject);
1486
      }//try
1487
      catch (Exception e)
1488
      {
1489
        MetaCatUtil.debugMessage("Error in getCurrentAllDocumentImpl: "
1490
                            +e.getMessage(), 30);
1491
        // continue the for loop
1492
        continue;
1493
      }
1494
    }//for
1495
    return documentImplList;
1496
  }
1497

    
1498
  /**
1499
   * Transfer a docid vetor to a documentImpl vector. If a DocumentImple object
1500
   * couldn't find for a docid, then the String of this docid was added to vetor
1501
   * rather than DocumentImple object.
1502
   * @param docIdList, a vetor hold a docid list for a data package. In docid,
1503
   *t here is version number in it.
1504
   */
1505
  private Vector getOldVersionAllDocumentImpl( Vector docIdList)
1506
  {
1507
    //Connection dbConn=null;
1508
    Vector documentImplList=new Vector();
1509
    String siteCode=null;
1510
    String uniqueId=null;
1511
    int rev=0;
1512

    
1513
    // Check the parameter
1514
    if (docIdList.isEmpty())
1515
    {
1516
      return documentImplList;
1517
    }//if
1518

    
1519
    //for every docid in vector
1520
    for (int i=0;i<docIdList.size();i++)
1521
    {
1522

    
1523
        String docidPlusVersion=(String)(docIdList.elementAt(i));
1524

    
1525
        try
1526
        {
1527
          //create new documentImpl object
1528
          DocumentImpl documentImplObject =
1529
                                    new DocumentImpl(docidPlusVersion);
1530
          //add them to vector
1531
          documentImplList.add(documentImplObject);
1532
        }//try
1533
        catch (McdbDocNotFoundException notFoundE)
1534
        {
1535
          MetaCatUtil.debugMessage("Error in DBQuery.getOldVersionAllDocument"+
1536
                                  "Imple" + notFoundE.getMessage(), 30);
1537
          // Rather than add a DocumentImple object into vetor, a String object
1538
          // - the doicd was added to the vector
1539
          documentImplList.add(docidPlusVersion);
1540
          // Continue the for loop
1541
          continue;
1542
        }//catch
1543
        catch (Exception e)
1544
        {
1545
          MetaCatUtil.debugMessage("Error in DBQuery.getOldVersionAllDocument"+
1546
                                  "Imple" + e.getMessage(), 30);
1547
          // Continue the for loop
1548
          continue;
1549
        }//catch
1550

    
1551

    
1552
    }//for
1553
    return documentImplList;
1554
  }//getOldVersionAllDocumentImple
1555

    
1556
  /**
1557
   *put a data file into a zip output stream
1558
   *@param docImpl, docmentImpl object which will be sent to zip output stream
1559
   *@param zipOut, the zip output stream which the docImpl will be put
1560
   *@param packageZipEntry, the zip entry name for whole package
1561
   */
1562
  private void addDataFileToZipOutputStream(DocumentImpl docImpl,
1563
                                ZipOutputStream zipOut, String packageZipEntry)
1564
               throws ClassNotFoundException, IOException, SQLException,
1565
                      McdbException, Exception
1566
  {
1567
    byte[] byteString = null;
1568
    ZipEntry zEntry = null;
1569
    // this is data file; add file to zip
1570
    String filePath = util.getOption("datafilepath");
1571
    if (!filePath.endsWith("/"))
1572
    {
1573
      filePath += "/";
1574
    }
1575
    String fileName = filePath + docImpl.getDocID();
1576
    zEntry = new ZipEntry(packageZipEntry+"/data/"+docImpl.getDocID());
1577
    zipOut.putNextEntry(zEntry);
1578
    FileInputStream fin = null;
1579
    try
1580
    {
1581
      fin = new FileInputStream(fileName);
1582
      byte[] buf = new byte[4 * 1024]; // 4K buffer
1583
      int b = fin.read(buf);
1584
      while (b != -1)
1585
      {
1586
        zipOut.write(buf, 0, b);
1587
        b = fin.read(buf);
1588
      }//while
1589
      zipOut.closeEntry();
1590
    }//try
1591
    catch (IOException ioe)
1592
    {
1593
      util.debugMessage("There is an exception: "+ioe.getMessage(), 30);
1594
    }//catch
1595
  }//addDataFileToZipOutputStream()
1596

    
1597
  /**
1598
   *create a html summary for data package and put it into zip output stream
1599
   *@param docImplList, the documentImpl ojbects in data package
1600
   *@param zipOut, the zip output stream which the html should be put
1601
   *@param packageZipEntry, the zip entry name for whole package
1602
   */
1603
   private void addHtmlSummaryToZipOutputStream(Vector docImplList,
1604
                                ZipOutputStream zipOut, String packageZipEntry)
1605
                                           throws Exception
1606
  {
1607
    StringBuffer htmlDoc = new StringBuffer();
1608
    ZipEntry zEntry = null;
1609
    byte[] byteString=null;
1610
    InputStream source;
1611
    DBTransform xmlToHtml;
1612

    
1613
    //create a DBTransform ojbect
1614
    xmlToHtml = new DBTransform();
1615
    //head of html
1616
    htmlDoc.append("<html><head></head><body>");
1617
    for (int i=0; i<docImplList.size(); i++)
1618
    {
1619
      // If this String object, this means it is missed data file
1620
      if ((((docImplList.elementAt(i)).getClass()).toString())
1621
                                             .equals("class java.lang.String"))
1622
      {
1623

    
1624
        htmlDoc.append("<a href=\"");
1625
        String dataFileid =(String)docImplList.elementAt(i);
1626
        htmlDoc.append("./data/").append(dataFileid).append("\">");
1627
        htmlDoc.append("Data File: ");
1628
        htmlDoc.append(dataFileid).append("</a><br>");
1629
        htmlDoc.append("<br><hr><br>");
1630

    
1631
      }//if
1632
      else if ((((DocumentImpl)docImplList.elementAt(i)).getDoctype()).
1633
                                                         compareTo("BIN")!=0)
1634
      { //this is an xml file so we can transform it.
1635
        //transform each file individually then concatenate all of the
1636
        //transformations together.
1637

    
1638
        //for metadata xml title
1639
        htmlDoc.append("<h2>");
1640
        htmlDoc.append(((DocumentImpl)docImplList.elementAt(i)).getDocID());
1641
        //htmlDoc.append(".");
1642
        //htmlDoc.append(((DocumentImpl)docImplList.elementAt(i)).getRev());
1643
        htmlDoc.append("</h2>");
1644
        //do the actual transform
1645
        StringWriter docString = new StringWriter();
1646
        xmlToHtml.transformXMLDocument(
1647
                        ((DocumentImpl)docImplList.elementAt(i)).toString(),
1648
           "-//NCEAS//eml-generic//EN", "-//W3C//HTML//EN", "html", docString);
1649
        htmlDoc.append(docString.toString());
1650
        htmlDoc.append("<br><br><hr><br><br>");
1651
      }//if
1652
      else
1653
      { //this is a data file so we should link to it in the html
1654
        htmlDoc.append("<a href=\"");
1655
        String dataFileid =((DocumentImpl)docImplList.elementAt(i)).getDocID();
1656
        htmlDoc.append("./data/").append(dataFileid).append("\">");
1657
        htmlDoc.append("Data File: ");
1658
        htmlDoc.append(dataFileid).append("</a><br>");
1659
        htmlDoc.append("<br><hr><br>");
1660
      }//else
1661
    }//for
1662
    htmlDoc.append("</body></html>");
1663
    byteString = htmlDoc.toString().getBytes();
1664
    zEntry = new ZipEntry(packageZipEntry+"/metadata.html");
1665
    zEntry.setSize(byteString.length);
1666
    zipOut.putNextEntry(zEntry);
1667
    zipOut.write(byteString, 0, byteString.length);
1668
    zipOut.closeEntry();
1669
    //dbConn.close();
1670

    
1671
  }//addHtmlSummaryToZipOutputStream
1672

    
1673

    
1674

    
1675
  /**
1676
   * put a data packadge into a zip output stream
1677
   * @param docId, which the user want to put into zip output stream
1678
   * @param out, a servletoutput stream which the zip output stream will be put
1679
   * @param user, the username of the user
1680
   * @param groups, the group of the user
1681
   */
1682
  public ZipOutputStream getZippedPackage(String docIdString,
1683
        ServletOutputStream out, String user, String[] groups, String passWord)
1684
                    throws ClassNotFoundException, IOException, SQLException,
1685
                      McdbException, NumberFormatException, Exception
1686
  {
1687
    ZipOutputStream zOut = null;
1688
    String elementDocid=null;
1689
    DocumentImpl docImpls=null;
1690
    //Connection dbConn = null;
1691
    Vector docIdList=new Vector();
1692
    Vector documentImplList=new Vector();
1693
    Vector htmlDocumentImplList=new Vector();
1694
    String packageId=null;
1695
    String rootName="package";//the package zip entry name
1696

    
1697
    String docId=null;
1698
    int version=-5;
1699
    // Docid without revision
1700
    docId=MetaCatUtil.getDocIdFromString(docIdString);
1701
    // revision number
1702
    version=MetaCatUtil.getVersionFromString(docIdString);
1703

    
1704
    //check if the reqused docId is a data package id
1705
    if (!isDataPackageId(docId))
1706
    {
1707

    
1708
      /*Exception e = new Exception("The request the doc id " +docIdString+
1709
                                    " is not a data package id");
1710
      throw e;*/
1711

    
1712

    
1713
      //CB 1/6/03: if the requested docid is not a datapackage, we just zip
1714
      //up the single document and return the zip file.
1715

    
1716
      if(!hasPermissionToExportPackage(docId, user, groups))
1717
      {
1718

    
1719
        Exception e = new Exception("User " + user + " does not have permission"
1720
                         +" to export the data package " + docIdString);
1721
        throw e;
1722
      }
1723

    
1724
      docImpls=new DocumentImpl(docId);
1725
      //checking if the user has the permission to read the documents
1726
      if (docImpls.hasReadPermission(user,groups,docImpls.getDocID()))
1727
      {
1728
        zOut = new ZipOutputStream(out);
1729
        //if the docImpls is metadata
1730
        if ((docImpls.getDoctype()).compareTo("BIN")!=0)
1731
        {
1732
          //add metadata into zip output stream
1733
          addDocToZipOutputStream(docImpls, zOut, rootName);
1734
        }//if
1735
        else
1736
        {
1737
          //it is data file
1738
          addDataFileToZipOutputStream(docImpls, zOut, rootName);
1739
          htmlDocumentImplList.add(docImpls);
1740
        }//else
1741
      }//if
1742

    
1743
      zOut.finish(); //terminate the zip file
1744
      return zOut;
1745
    }
1746
    // Check the permission of user
1747
    else if(!hasPermissionToExportPackage(docId, user, groups))
1748
    {
1749

    
1750
      Exception e = new Exception("User " + user + " does not have permission"
1751
                       +" to export the data package " + docIdString);
1752
      throw e;
1753
    }
1754
    else //it is a packadge id
1755
    {
1756
      //store the package id
1757
      packageId=docId;
1758
      //get current version in database
1759
      int currentVersion = getCurrentRevFromXMLDoumentsTable(packageId);
1760
      //If it is for current version (-1 means user didn't specify revision)
1761
      if ((version ==-1)||version==currentVersion)
1762
      {
1763
        //get current version number
1764
        version=currentVersion;
1765
        //get package zip entry name
1766
        //it should be docId.revsion.package
1767
        rootName=packageId+util.getOption("accNumSeparator")+version+
1768
                                  util.getOption("accNumSeparator")+"package";
1769
        //get the whole id list for data packadge
1770
        docIdList=getCurrentDocidListForDataPackage(packageId);
1771
        //get the whole documentImple object
1772
        documentImplList=getCurrentAllDocumentImpl(docIdList);
1773

    
1774
      }//if
1775
      else if (version > currentVersion || version < -1)
1776
      {
1777
        throw new Exception ("The user specified docid: "+docId+"."+version
1778
                                              +" doesn't exist");
1779
      }//else if
1780
      else  //for an old version
1781
      {
1782

    
1783
        rootName=docIdString+util.getOption("accNumSeparator")+"package";
1784
        //get the whole id list for data packadge
1785
        docIdList=getOldVersionDocidListForDataPackage(docIdString);
1786

    
1787
        //get the whole documentImple object
1788
        documentImplList=getOldVersionAllDocumentImpl(docIdList);
1789
      }//else
1790

    
1791
      // Make sure documentImplist is not empty
1792
      if (documentImplList.isEmpty())
1793
      {
1794
        throw new Exception ("Couldn't find component for data package: "
1795
                                              + packageId);
1796
      }//if
1797

    
1798

    
1799
       zOut = new ZipOutputStream(out);
1800
      //put every element into zip output stream
1801
      for (int i=0; i < documentImplList.size(); i++ )
1802
      {
1803
        // if the object in the vetor is String, this means we couldn't find
1804
        // the document locally, we need find it remote
1805
       if ((((documentImplList.elementAt(i)).getClass()).toString())
1806
                                             .equals("class java.lang.String"))
1807
        {
1808
          // Get String object from vetor
1809
          String documentId = (String) documentImplList.elementAt(i);
1810
          MetaCatUtil.debugMessage("docid: "+documentId, 30);
1811
          // Get doicd without revision
1812
          String docidWithoutRevision =
1813
                                     MetaCatUtil.getDocIdFromString(documentId);
1814
          MetaCatUtil.debugMessage("docidWithoutRevsion: "
1815
                                                     +docidWithoutRevision, 30);
1816
          // Get revision
1817
          String revision = MetaCatUtil.getRevisionStringFromString(documentId);
1818
          MetaCatUtil.debugMessage("revsion from docIdentifier: "+revision, 30);
1819
          // Zip entry string
1820
          String zipEntryPath = rootName+"/data/";
1821
          // Create a RemoteDocument object
1822
          RemoteDocument remoteDoc =
1823
                          new RemoteDocument(docidWithoutRevision,revision,user,
1824
                                                     passWord, zipEntryPath);
1825
          // Here we only read data file from remote metacat
1826
          String docType = remoteDoc.getDocType();
1827
          if (docType!=null)
1828
          {
1829
            if (docType.equals("BIN"))
1830
            {
1831
              // Put remote document to zip output
1832
              remoteDoc.readDocumentFromRemoteServerByZip(zOut);
1833
              // Add String object to htmlDocumentImplList
1834
              String elementInHtmlList = remoteDoc.getDocIdWithoutRevsion()+
1835
               MetaCatUtil.getOption("accNumSeparator")+remoteDoc.getRevision();
1836
              htmlDocumentImplList.add(elementInHtmlList);
1837
            }//if
1838
          }//if
1839

    
1840
        }//if
1841
        else
1842
        {
1843
          //create a docmentImpls object (represent xml doc) base on the docId
1844
          docImpls=(DocumentImpl)documentImplList.elementAt(i);
1845
          //checking if the user has the permission to read the documents
1846
          if (docImpls.hasReadPermission(user,groups,docImpls.getDocID()))
1847
          {
1848
            //if the docImpls is metadata
1849
            if ((docImpls.getDoctype()).compareTo("BIN")!=0)
1850
            {
1851
              //add metadata into zip output stream
1852
              addDocToZipOutputStream(docImpls, zOut, rootName);
1853
              //add the documentImpl into the vetor which will be used in html
1854
              htmlDocumentImplList.add(docImpls);
1855

    
1856
            }//if
1857
            else
1858
            {
1859
              //it is data file
1860
              addDataFileToZipOutputStream(docImpls, zOut, rootName);
1861
              htmlDocumentImplList.add(docImpls);
1862
            }//else
1863
          }//if
1864
        }//else
1865
      }//for
1866

    
1867
      //add html summary file
1868
      addHtmlSummaryToZipOutputStream(htmlDocumentImplList, zOut, rootName);
1869
      zOut.finish(); //terminate the zip file
1870
      //dbConn.close();
1871
      return zOut;
1872
    }//else
1873
  }//getZippedPackage()
1874

    
1875
   private class ReturnFieldValue
1876
  {
1877
    private String docid          = null; //return field value for this docid
1878
    private String fieldValue     = null;
1879
    private String xmlFieldValue  = null; //return field value in xml format
1880

    
1881

    
1882
    public void setDocid(String myDocid)
1883
    {
1884
      docid = myDocid;
1885
    }
1886

    
1887
    public String getDocid()
1888
    {
1889
      return docid;
1890
    }
1891

    
1892
    public void setFieldValue(String myValue)
1893
    {
1894
      fieldValue = myValue;
1895
    }
1896

    
1897
    public String getFieldValue()
1898
    {
1899
      return fieldValue;
1900
    }
1901

    
1902
    public void setXMLFieldValue(String xml)
1903
    {
1904
      xmlFieldValue = xml;
1905
    }
1906

    
1907
    public String getXMLFieldValue()
1908
    {
1909
      return xmlFieldValue;
1910
    }
1911

    
1912

    
1913
  }
1914

    
1915
}
(22-22/58)