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: jones $'
14
 *     '$Date: 2004-03-30 10:02:41 -0800 (Tue, 30 Mar 2004) $'
15
 * '$Revision: 2074 $'
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 java.io.BufferedWriter;
35
import java.io.File;
36
import java.io.FileInputStream;
37
import java.io.FileReader;
38
import java.io.FileWriter;
39
import java.io.IOException;
40
import java.io.InputStream;
41
import java.io.Reader;
42
import java.io.StringReader;
43
import java.io.StringWriter;
44
import java.sql.PreparedStatement;
45
import java.sql.ResultSet;
46
import java.sql.SQLException;
47
import java.util.Enumeration;
48
import java.util.Hashtable;
49
import java.util.StringTokenizer;
50
import java.util.Vector;
51
import java.util.zip.ZipEntry;
52
import java.util.zip.ZipOutputStream;
53

    
54
import javax.servlet.ServletOutputStream;
55

    
56
import edu.ucsb.nceas.morpho.datapackage.Triple;
57
import edu.ucsb.nceas.morpho.datapackage.TripleCollection;
58

    
59
/**
60
 * A Class that searches a relational DB for elements and
61
 * attributes that have free text matches a query string,
62
 * or structured query matches to a path specified node in the
63
 * XML hierarchy.  It returns a result set consisting of the
64
 * document ID for each document that satisfies the query
65
 */
66
public class DBQuery {
67

    
68
  static final int ALL = 1;
69
  static final int WRITE = 2;
70
  static final int READ = 4;
71

    
72
  //private Connection  conn = null;
73
  private String  parserName = null;
74
  private MetaCatUtil util = new MetaCatUtil();
75
  
76
  /**
77
   * the main routine used to test the DBQuery utility.
78
   * <p>
79
   * Usage: java DBQuery <xmlfile>
80
   *
81
   * @param xmlfile the filename of the xml file containing the query
82
   */
83
  static public void main(String[] args) {
84

    
85
     if (args.length < 1)
86
     {
87
        System.err.println("Wrong number of arguments!!!");
88
        System.err.println("USAGE: java DBQuery [-t] [-index] <xmlfile>");
89
        return;
90
     } else {
91
        try {
92

    
93
          int i = 0;
94
          boolean showRuntime = false;
95
          boolean useXMLIndex = false;
96
          if ( args[i].equals( "-t" ) ) {
97
            showRuntime = true;
98
            i++;
99
          }
100
          if ( args[i].equals( "-index" ) ) {
101
            useXMLIndex = true;
102
            i++;
103
          }
104
          String xmlfile  = args[i];
105

    
106
          // Time the request if asked for
107
          double startTime = System.currentTimeMillis();
108

    
109
          // Open a connection to the database
110
          MetaCatUtil   util = new MetaCatUtil();
111
          //Connection dbconn = util.openDBConnection();
112

    
113
          double connTime = System.currentTimeMillis();
114

    
115
          // Execute the query
116
          DBQuery queryobj = new DBQuery(MetaCatUtil.getOption("saxparser"));
117
          FileReader xml = new FileReader(new File(xmlfile));
118
          Hashtable nodelist = null;
119
          nodelist = queryobj.findDocuments(xml, null, null, useXMLIndex);
120

    
121
          // Print the reulting document listing
122
          StringBuffer result = new StringBuffer();
123
          String document = null;
124
          String docid = null;
125
          result.append("<?xml version=\"1.0\"?>\n");
126
          result.append("<resultset>\n");
127

    
128
          if (!showRuntime)
129
          {
130
            Enumeration doclist = nodelist.keys();
131
            while (doclist.hasMoreElements()) {
132
              docid = (String)doclist.nextElement();
133
              document = (String)nodelist.get(docid);
134
              result.append("  <document>\n    " + document +
135
                            "\n  </document>\n");
136
            }
137

    
138
            result.append("</resultset>\n");
139
          }
140
          // Time the request if asked for
141
          double stopTime = System.currentTimeMillis();
142
          double dbOpenTime = (connTime - startTime)/1000;
143
          double readTime = (stopTime - connTime)/1000;
144
          double executionTime = (stopTime - startTime)/1000;
145
          if (showRuntime) {
146
            System.out.print("  " + executionTime);
147
            System.out.print("  " + dbOpenTime);
148
            System.out.print("  " + readTime);
149
            System.out.print("  " + nodelist.size());
150
            System.out.println();
151
          }
152
          //System.out.println(result);
153
          //write into a file "result.txt"
154
          if (!showRuntime)
155
          {
156
            File f = new File("./result.txt");
157
            FileWriter fw = new FileWriter(f);
158
            BufferedWriter out = new BufferedWriter(fw);
159
            out.write(result.toString());
160
            out.flush();
161
            out.close();
162
            fw.close();
163
          }
164

    
165
        }
166
        catch (Exception e) {
167
          System.err.println("Error in DBQuery.main");
168
          System.err.println(e.getMessage());
169
          e.printStackTrace(System.err);
170
        }
171
     }
172
  }
173

    
174
  /**
175
   * construct an instance of the DBQuery class
176
   *
177
   * <p>Generally, one would call the findDocuments() routine after creating
178
   * an instance to specify the search query</p>
179
   *
180
   * @param conn the JDBC connection that we use for the query
181
   * @param parserName the fully qualified name of a Java class implementing
182
   *                   the org.xml.sax.XMLReader interface
183
   */
184
  public DBQuery(String parserName )
185
                  throws IOException,
186
                         SQLException,
187
                         ClassNotFoundException {
188
    //this.conn = conn;
189
    this.parserName = parserName;
190
  }
191

    
192
  /**
193
   * routine to search the elements and attributes looking to match query
194
   *
195
   * @param xmlquery the xml serialization of the query (@see pathquery.dtd)
196
   * @param user the username of the user
197
   * @param group the group of the user
198
   */
199
  public Hashtable findDocuments(Reader xmlquery, String user, String[] groups)
200
  {
201
    boolean useXMLIndex = (new Boolean(
202
            MetaCatUtil.getOption("usexmlindex"))).booleanValue();
203
    return findDocuments(xmlquery, user, groups, useXMLIndex);
204
  }
205

    
206
  /**
207
   * routine to search the elements and attributes looking to match query
208
   *
209
   * @param xmlquery the xml serialization of the query (@see pathquery.dtd)
210
   * @param user the username of the user
211
   * @param group the group of the user
212
   * @param useXMLIndex flag whether to search using the path index
213
   */
214
  public Hashtable findDocuments(Reader xmlquery, String user, String[] groups,
215
                                 boolean useXMLIndex)
216
  {
217
      Hashtable result = new Hashtable();
218
      try
219
      {
220
        // Get the XML query and covert it into a SQL statment
221
        QuerySpecification qspec = new QuerySpecification(xmlquery,
222
                                   parserName,
223
                                   MetaCatUtil.getOption("accNumSeparator"));
224
        result = findDocuments(qspec, user, groups, useXMLIndex);
225
      }
226
      catch (IOException ioe)
227
      {
228
        MetaCatUtil.debugMessage("IO error in DBQuery.findDocuments:", 30);
229
        MetaCatUtil.debugMessage(ioe.getMessage(), 30);
230
      }
231
      return result;
232
  }
233

    
234
  /**
235
   * routine to search the elements and attributes looking to match query
236
   *
237
   * @param qspec java object of the query
238
   * @param user the username of the user
239
   * @param group the group of the user
240
   * @param useXMLIndex flag whether to search using the path index
241
   */
242
  public Hashtable findDocuments(QuerySpecification qspec, String user,
243
                                  String[] groups, boolean useXMLIndex)
244
  {
245
      Hashtable   docListResult = new Hashtable();
246
      PreparedStatement pstmt = null;
247
      String docid = null;
248
      String docname = null;
249
      String doctype = null;
250
      String createDate = null;
251
      String updateDate = null;
252
      String fieldname = null;
253
      String fielddata = null;
254
      String relation = null;
255
      //Connection dbconn = null;
256
      //Connection dbconn2 = null;
257
      int rev = 0;
258
      StringBuffer document = null;
259
      DBConnection dbconn = null;
260
      int serialNumber = -1;
261

    
262
      try {
263

    
264

    
265
        dbconn=DBConnectionPool.getDBConnection("DBQuery.findDocuments");
266
        serialNumber=dbconn.getCheckOutSerialNumber();
267

    
268
        String query = qspec.printSQL(useXMLIndex);
269
        String ownerQuery = getOwnerQuery(user);
270
        MetaCatUtil.debugMessage("query: "+query, 30);
271
        //MetaCatUtil.debugMessage("query: "+ownerQuery, 30);
272
        // if query is not the owner query, we need to check the permission
273
        // otherwise we don't need (owner has all permission by default)
274
        if (!query.equals(ownerQuery))
275
        {
276
          // set user name and group
277
          qspec.setUserName(user);
278
          qspec.setGroup(groups);
279
          // Get access query
280
          String accessQuery = qspec.getAccessQuery();
281
          query = query + accessQuery;
282
          MetaCatUtil.debugMessage(" final query: "+query, 30);
283
        }
284

    
285
        double startTime = System.currentTimeMillis()/1000;
286
        pstmt = dbconn.prepareStatement(query);
287

    
288
        // Execute the SQL query using the JDBC connection
289
        pstmt.execute();
290
        ResultSet rs = pstmt.getResultSet();
291
        double queryExecuteTime =System.currentTimeMillis()/1000;
292
        MetaCatUtil.debugMessage("Time for execute query: "+
293
                                            (queryExecuteTime -startTime), 30);
294
        boolean tableHasRows = rs.next();
295
        while (tableHasRows)
296
        {
297
          docid = rs.getString(1).trim();
298
          //long checkTimeStart = System.currentTimeMillis();
299
          //boolean permit =hasPermission(user, groups, docid);
300
          //long checkTimeEnd = System.currentTimeMillis();
301
          //MetaCatUtil.debugMessage("check permission time: "+
302
                                  //(checkTimeEnd - checkTimeStart), 30);
303
          //if ( !permit ) {
304
            // Advance to the next record in the cursor
305
            //tableHasRows = rs.next();
306
            //continue;
307
          //}
308

    
309
          docname = rs.getString(2);
310
          doctype = rs.getString(3);
311
          createDate = rs.getString(4);
312
          updateDate = rs.getString(5);
313
          rev = rs.getInt(6);
314

    
315
          // if there are returndocs to match, backtracking can be performed
316
          // otherwise, just return the document that was hit
317
          Vector returndocVec = qspec.getReturnDocList();
318
          if (returndocVec.size() != 0 && !returndocVec.contains(doctype)
319
              && !qspec.isPercentageSearch())
320
          {
321
            MetaCatUtil.debugMessage("Back tracing now...", 20);
322
            String sep = MetaCatUtil.getOption("accNumSeparator");
323
            StringBuffer btBuf = new StringBuffer();
324
            btBuf.append("select docid from xml_relation where ");
325

    
326
            //build the doctype list for the backtracking sql statement
327
            btBuf.append("packagetype in (");
328
            for(int i=0; i<returndocVec.size(); i++)
329
            {
330
              btBuf.append("'").append((String)returndocVec.get(i)).append("'");
331
              if (i != (returndocVec.size() - 1))
332
              {
333
                btBuf.append(", ");
334
              }
335
            }
336
            btBuf.append(") ");
337

    
338
            btBuf.append("and (subject like '");
339
            btBuf.append(docid).append("'");
340
            btBuf.append("or object like '");
341
            btBuf.append(docid).append("')");
342

    
343
            PreparedStatement npstmt = dbconn.
344
                                       prepareStatement(btBuf.toString());
345
            //should incease usage count
346
            dbconn.increaseUsageCount(1);
347
            npstmt.execute();
348
            ResultSet btrs = npstmt.getResultSet();
349
            boolean hasBtRows = btrs.next();
350
            while (hasBtRows)
351
            { //there was a backtrackable document found
352
              DocumentImpl xmldoc = null;
353
              String packageDocid = btrs.getString(1);
354
              MetaCatUtil.debugMessage("Getting document for docid: "+packageDocid,40);
355
              try
356
              {
357
                //  THIS CONSTRUCTOR BUILDS THE WHOLE XML doc not needed here
358
                // xmldoc = new DocumentImpl(dbconn, packageDocid);
359
                //  thus use the following to get the doc info only
360
                //  xmldoc = new DocumentImpl(dbconn);
361
                xmldoc = new DocumentImpl(packageDocid, false);
362
                if (xmldoc == null) {
363
                    MetaCatUtil.debugMessage("Document was null for: "+packageDocid, 50);
364
                }
365
              }
366
              catch(Exception e)
367
              {
368
                System.out.println("Error getting document in " +
369
                                   "DBQuery.findDocuments: " + e.getMessage());
370
              }
371

    
372
              String docid_org = xmldoc.getDocID();
373
              if (docid_org == null) {
374
                  MetaCatUtil.debugMessage("Docid_org was null.", 40);
375
              }
376
              docid   = docid_org.trim();
377
              docname = xmldoc.getDocname();
378
              doctype = xmldoc.getDoctype();
379
              createDate = xmldoc.getCreateDate();
380
              updateDate = xmldoc.getUpdateDate();
381
              rev = xmldoc.getRev();
382

    
383
              document = new StringBuffer();
384

    
385
              String completeDocid = docid + MetaCatUtil.getOption("accNumSeparator");
386
              completeDocid += rev;
387
              document.append("<docid>").append(completeDocid);
388
              document.append("</docid>");
389
              if (docname != null) {
390
                document.append("<docname>" + docname + "</docname>");
391
              }
392
              if (doctype != null) {
393
                document.append("<doctype>" + doctype + "</doctype>");
394
              }
395
              if (createDate != null) {
396
                document.append("<createdate>" + createDate + "</createdate>");
397
              }
398
              if (updateDate != null) {
399
                document.append("<updatedate>" + updateDate + "</updatedate>");
400
              }
401
              // Store the document id and the root node id
402
              docListResult.put(docid,(String)document.toString());
403

    
404
              // Get the next package document linked to our hit
405
              hasBtRows = btrs.next();
406
            }
407
            npstmt.close();
408
            btrs.close();
409
          }
410
          else if (returndocVec.size() != 0 && returndocVec.contains(doctype))
411
          {
412

    
413
            document = new StringBuffer();
414

    
415
            String completeDocid = docid + MetaCatUtil.getOption("accNumSeparator");
416
            completeDocid += rev;
417
            document.append("<docid>").append(completeDocid).append("</docid>");
418
            if (docname != null) {
419
              document.append("<docname>" + docname + "</docname>");
420
            }
421
            if (doctype != null) {
422
              document.append("<doctype>" + doctype + "</doctype>");
423
            }
424
            if (createDate != null) {
425
              document.append("<createdate>" + createDate + "</createdate>");
426
            }
427
            if (updateDate != null) {
428
              document.append("<updatedate>" + updateDate + "</updatedate>");
429
            }
430
            // Store the document id and the root node id
431
            docListResult.put(docid,(String)document.toString());
432

    
433
          }
434

    
435
          // Advance to the next record in the cursor
436
          tableHasRows = rs.next();
437
        }
438
        rs.close();
439
        pstmt.close();
440
        double docListTime =System.currentTimeMillis()/1000;
441
        MetaCatUtil.debugMessage("prepare docid list time: "
442
                                          +(docListTime-queryExecuteTime), 30);
443

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

    
480
            double extendedAccessQueryEnd = System.currentTimeMillis()/1000;
481
            MetaCatUtil.debugMessage("Time for execute access extended query: "
482
                              +(extendedAccessQueryEnd-extendedQueryStart), 30);
483

    
484
            String extendedQuery = qspec.printExtendedSQL(doclist.toString(), 
485
                    controlPairs, useXMLIndex);
486
            MetaCatUtil.debugMessage("Extended query: "+ extendedQuery, 30);
487
            pstmt = dbconn.prepareStatement(extendedQuery);
488
            //increase dbconnection usage count
489
            dbconn.increaseUsageCount(1);
490
            pstmt.execute();
491
            rs = pstmt.getResultSet();
492
            double extendedQueryEnd = System.currentTimeMillis()/1000;
493
            MetaCatUtil.debugMessage("Time for execute extended query: "
494
                                    +(extendedQueryEnd-extendedQueryStart), 30);
495
            tableHasRows = rs.next();
496
            while(tableHasRows)
497
            {
498
              ReturnFieldValue returnValue = new ReturnFieldValue();
499
              docid = rs.getString(1).trim();
500
              fieldname = rs.getString(2);
501
              fielddata = rs.getString(3);
502
              fielddata = MetaCatUtil.normalize(fielddata);
503

    
504
              String parentId = rs.getString(4);
505

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

    
546
            // put the merger node data info into doclistReult
547
            Enumeration xmlFieldValue = (getElements(parentidList)).elements();
548
            while( xmlFieldValue.hasMoreElements() )
549
            {
550
              ReturnFieldValue object = (ReturnFieldValue)
551
                                         xmlFieldValue.nextElement();
552
              docid = object.getDocid();
553
              if (docListResult.containsKey(docid))
554
              {
555
                  String removedelement = (String)docListResult.remove(docid);
556
                  docListResult.put(docid, removedelement +
557
                                    object.getXMLFieldValue());
558
              }
559
              else
560
              {
561
                  docListResult.put(docid, object.getXMLFieldValue());
562
              }
563
            }//while
564
            double docListResultEnd = System.currentTimeMillis()/1000;
565
            MetaCatUtil.debugMessage("Time for prepare doclistresult after"+
566
                                      " execute extended query: "
567
                                    +(docListResultEnd-extendedQueryEnd), 30);
568

    
569

    
570
            // get attribures return
571
            docListResult = getAttributeValueForReturn(qspec, docListResult, 
572
                    doclist.toString(), useXMLIndex);
573
          }//if doclist lenght is great than zero
574

    
575
        }//if has extended query
576

    
577

    
578
        //this loop adds the relation data to the resultdoc
579
        //this code might be able to be added to the backtracking code above
580
        double startRelation = System.currentTimeMillis()/1000;
581
        Enumeration docidkeys = docListResult.keys();
582
        while(docidkeys.hasMoreElements())
583
        {
584
          //String connstring = "metacat://"+util.getOption("server")+"?docid=";
585
          String connstring = "%docid=";
586
          String docidkey = (String)docidkeys.nextElement();
587
          pstmt = dbconn.prepareStatement(QuerySpecification.printRelationSQL(docidkey));
588
          pstmt.execute();
589
          rs = pstmt.getResultSet();
590
          tableHasRows = rs.next();
591
          while(tableHasRows)
592
          {
593
            String sub = rs.getString(1);
594
            String rel = rs.getString(2);
595
            String obj = rs.getString(3);
596
            String subDT = rs.getString(4);
597
            String objDT = rs.getString(5);
598

    
599
            document = new StringBuffer();
600
            document.append("<triple>");
601
            document.append("<subject>").append(MetaCatUtil.normalize(sub));
602
            document.append("</subject>");
603
            if ( subDT != null ) {
604
              document.append("<subjectdoctype>").append(subDT);
605
              document.append("</subjectdoctype>");
606
            }
607
            document.append("<relationship>").
608
                                          append(MetaCatUtil.normalize(rel));
609
            document.append("</relationship>");
610
            document.append("<object>").append(MetaCatUtil.normalize(obj));
611
            document.append("</object>");
612
            if ( objDT != null ) {
613
              document.append("<objectdoctype>").append(objDT);
614
              document.append("</objectdoctype>");
615
            }
616
            document.append("</triple>");
617

    
618
            String removedelement = (String)docListResult.remove(docidkey);
619
            docListResult.put(docidkey, removedelement +
620
                              document.toString());
621
            tableHasRows = rs.next();
622
          }
623
          rs.close();
624
          pstmt.close();
625
        }
626
        double endRelation = System.currentTimeMillis()/1000;
627
        MetaCatUtil.debugMessage("Time for adding relation to docListResult: "+
628
                                (endRelation-startRelation), 30);
629

    
630
      } catch (SQLException e) {
631
        System.err.println("SQL Error in DBQuery.findDocuments: " +
632
                           e.getMessage());
633
      } catch (Exception ee) {
634
        System.err.println("Exception in DBQuery.findDocuments: " +
635
                           ee.getMessage());
636
        ee.printStackTrace(System.err);
637
      }
638
      finally
639
      {
640
        try
641
        {
642
          pstmt.close();
643
        }//try
644
        catch (SQLException sqlE)
645
        {
646
          MetaCatUtil.debugMessage("Error in DBQuery.findDocuments: "
647
                                      +sqlE.getMessage(), 30);
648
        }//catch
649
        finally
650
        {
651
          DBConnectionPool.returnDBConnection(dbconn, serialNumber);
652
        }//finally
653
      }//finally
654
    //System.out.println("docListResult: ");
655
    //System.out.println(docListResult.toString());
656
    return docListResult;
657
  }
658

    
659
  /*
660
   * A method to search if Vector contains a particular key string
661
   */
662
  private boolean containsKey(Vector parentidList,String parentId){
663

    
664
    Vector tempVector = null;
665

    
666
    for(int count = 0; count < parentidList.size(); count++){
667
      tempVector = (Vector)parentidList.get(count);
668
      if(parentId.compareTo((String)tempVector.get(0)) == 0){
669
        return false;
670
      }
671
    }
672
    return false;
673
  }
674

    
675
  /*
676
   * A method to put key and value in Vector
677
   */
678
  private void putInArray(Vector parentidList, String key,
679
                          ReturnFieldValue value){
680

    
681
    Vector tempVector = null;
682

    
683
    for(int count = 0; count < parentidList.size(); count++){
684
      tempVector = (Vector)parentidList.get(count);
685

    
686
      if(key.compareTo((String)tempVector.get(0)) == 0){
687
        tempVector.remove(1);
688
        tempVector.add(1, value);
689
        return;
690
      }
691
    }
692

    
693
    tempVector = new Vector();
694
    tempVector.add(0, key);
695
    tempVector.add(1, value);
696
    parentidList.add(tempVector);
697
    return;
698
  }
699

    
700
  /*
701
   * A method to get value in Vector given a key
702
   */
703
  private ReturnFieldValue getArrayValue(Vector parentidList,
704
                                         String key){
705

    
706
    Vector tempVector = null;
707

    
708
    for(int count = 0; count < parentidList.size(); count++){
709
      tempVector = (Vector)parentidList.get(count);
710

    
711
      if(key.compareTo((String)tempVector.get(0)) == 0){
712
        return (ReturnFieldValue)tempVector.get(1);
713
      }
714
    }
715
    return null;
716
  }
717

    
718
  /*
719
   * A method to get enumeration of all values in Vector
720
   */
721
  private Vector getElements(Vector parentidList){
722
    Vector enum = new Vector();
723
    Vector tempVector = null;
724

    
725
    for(int count = 0; count < parentidList.size(); count++){
726
      tempVector = (Vector)parentidList.get(count);
727

    
728
      enum.add(tempVector.get(1));
729
    }
730
    return enum;
731
  }
732

    
733
  /*
734
   * A method to return search result after running a query which return
735
   * field have attribue
736
   */
737
  private Hashtable getAttributeValueForReturn(QuerySpecification squery, 
738
          Hashtable docInformationList, String docList, boolean useXMLIndex)
739
  {
740
    StringBuffer XML = null;
741
    String sql = null;
742
    DBConnection dbconn = null;
743
    PreparedStatement pstmt = null;
744
    ResultSet rs = null;
745
    int serialNumber = -1;
746
    boolean tableHasRows =false;
747

    
748
    //check the parameter
749
    if (squery == null || docList==null || docList.length() <0)
750
    {
751
      return docInformationList;
752
    }
753

    
754
    // if has attribute as return field
755
    if (squery.containAttributeReturnField())
756
    {
757
      sql = squery.printAttributeQuery(docList, useXMLIndex);
758
      try
759
      {
760
        dbconn=DBConnectionPool.getDBConnection("DBQuery.getAttributeValue");
761
        serialNumber=dbconn.getCheckOutSerialNumber();
762
        pstmt = dbconn.prepareStatement(sql);
763
        pstmt.execute();
764
        rs = pstmt.getResultSet();
765
        tableHasRows = rs.next();
766
        while(tableHasRows)
767
        {
768
          String docid = rs.getString(1).trim();
769
          String fieldname = rs.getString(2);
770
          String fielddata = rs.getString(3);
771
          String attirbuteName = rs.getString(4);
772
          XML = new StringBuffer();
773

    
774
          XML.append("<param name=\"");
775
          XML.append(fieldname);
776
          XML.append(QuerySpecification.ATTRIBUTESYMBOL);
777
          XML.append(attirbuteName);
778
          XML.append("\">");
779
          XML.append(fielddata);
780
          XML.append("</param>");
781
          tableHasRows = rs.next();
782

    
783
          if (docInformationList.containsKey(docid))
784
          {
785
            String removedelement = (String)docInformationList.remove(docid);
786
            docInformationList.put(docid, removedelement + XML.toString());
787
          }
788
          else
789
          {
790
            docInformationList.put(docid, XML.toString());
791
          }
792
        }//while
793
        rs.close();
794
        pstmt.close();
795
      }
796
      catch(Exception se)
797
      {
798
        MetaCatUtil.debugMessage("Error in DBQuery.getAttributeValue1: "
799
                                      +se.getMessage(), 30);
800
      }
801
      finally
802
      {
803
        try
804
        {
805
          pstmt.close();
806
        }//try
807
        catch (SQLException sqlE)
808
        {
809
          MetaCatUtil.debugMessage("Error in DBQuery.getAttributeValue2: "
810
                                      +sqlE.getMessage(), 30);
811
        }//catch
812
        finally
813
        {
814
          DBConnectionPool.returnDBConnection(dbconn, serialNumber);
815
        }//finally
816
      }//finally
817
    }//if
818
    return docInformationList;
819

    
820
  }
821

    
822

    
823
  /*
824
   * A method to create a query to get owner's docid list
825
   */
826
  private String getOwnerQuery(String owner)
827
  {
828
    if (owner != null)
829
    {
830
      owner = owner.toLowerCase();
831
    }
832
    StringBuffer self = new StringBuffer();
833
  
834
    self.append("SELECT docid,docname,doctype,");
835
    self.append("date_created, date_updated, rev ");
836
    self.append("FROM xml_documents WHERE docid IN (");
837
    self.append("(");
838
    self.append("SELECT DISTINCT docid FROM xml_nodes WHERE \n");
839
    self.append("nodedata LIKE '%%%' ");
840
    self.append(") \n");
841
    self.append(") ");
842
    self.append(" AND (");
843
    self.append(" lower(user_owner) = '" + owner + "'");
844
    self.append(") ");
845
    return self.toString();
846
  }
847

    
848
  /**
849
   * format a structured query as an XML document that conforms
850
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
851
   * structured query engine
852
   *
853
   * @param params The list of parameters that should be included in the query
854
   */
855
  public static String createSQuery(Hashtable params)
856
  {
857
    StringBuffer query = new StringBuffer();
858
    Enumeration elements;
859
    Enumeration keys;
860
    String filterDoctype = null;
861
    String casesensitive = null;
862
    String searchmode = null;
863
    Object nextkey;
864
    Object nextelement;
865
    //add the xml headers
866
    query.append("<?xml version=\"1.0\"?>\n");
867
    query.append("<pathquery version=\"1.0\">\n");
868

    
869
    if (params.containsKey("meta_file_id"))
870
    {
871
      query.append("<meta_file_id>");
872
      query.append( ((String[])params.get("meta_file_id"))[0]);
873
      query.append("</meta_file_id>");
874
    }
875

    
876
    if (params.containsKey("returndoctype"))
877
    {
878
      String[] returnDoctypes = ((String[])params.get("returndoctype"));
879
      for(int i=0; i<returnDoctypes.length; i++)
880
      {
881
        String doctype = (String)returnDoctypes[i];
882

    
883
        if (!doctype.equals("any") &&
884
            !doctype.equals("ANY") &&
885
            !doctype.equals("") )
886
        {
887
          query.append("<returndoctype>").append(doctype);
888
          query.append("</returndoctype>");
889
        }
890
      }
891
    }
892

    
893
    if (params.containsKey("filterdoctype"))
894
    {
895
      String[] filterDoctypes = ((String[])params.get("filterdoctype"));
896
      for(int i=0; i<filterDoctypes.length; i++)
897
      {
898
        query.append("<filterdoctype>").append(filterDoctypes[i]);
899
        query.append("</filterdoctype>");
900
      }
901
    }
902

    
903
    if (params.containsKey("returnfield"))
904
    {
905
      String[] returnfield = ((String[])params.get("returnfield"));
906
      for(int i=0; i<returnfield.length; i++)
907
      {
908
        query.append("<returnfield>").append(returnfield[i]);
909
        query.append("</returnfield>");
910
      }
911
    }
912

    
913
    if (params.containsKey("owner"))
914
    {
915
      String[] owner = ((String[])params.get("owner"));
916
      for(int i=0; i<owner.length; i++)
917
      {
918
        query.append("<owner>").append(owner[i]);
919
        query.append("</owner>");
920
      }
921
    }
922

    
923
    if (params.containsKey("site"))
924
    {
925
      String[] site = ((String[])params.get("site"));
926
      for(int i=0; i<site.length; i++)
927
      {
928
        query.append("<site>").append(site[i]);
929
        query.append("</site>");
930
      }
931
    }
932

    
933
    //allows the dynamic switching of boolean operators
934
    if (params.containsKey("operator"))
935
    {
936
      query.append("<querygroup operator=\"" +
937
                ((String[])params.get("operator"))[0] + "\">");
938
    }
939
    else
940
    { //the default operator is UNION
941
      query.append("<querygroup operator=\"UNION\">");
942
    }
943

    
944
    if (params.containsKey("casesensitive"))
945
    {
946
      casesensitive = ((String[])params.get("casesensitive"))[0];
947
    }
948
    else
949
    {
950
      casesensitive = "false";
951
    }
952

    
953
    if (params.containsKey("searchmode"))
954
    {
955
      searchmode = ((String[])params.get("searchmode"))[0];
956
    }
957
    else
958
    {
959
      searchmode = "contains";
960
    }
961

    
962
    //anyfield is a special case because it does a
963
    //free text search.  It does not have a <pathexpr>
964
    //tag.  This allows for a free text search within the structured
965
    //query.  This is useful if the INTERSECT operator is used.
966
    if (params.containsKey("anyfield"))
967
    {
968
       String[] anyfield = ((String[])params.get("anyfield"));
969
       //allow for more than one value for anyfield
970
       for(int i=0; i<anyfield.length; i++)
971
       {
972
         if (!anyfield[i].equals(""))
973
         {
974
           query.append("<queryterm casesensitive=\"" + casesensitive +
975
                        "\" " + "searchmode=\"" + searchmode + "\"><value>" +
976
                        anyfield[i] +
977
                        "</value></queryterm>");
978
         }
979
       }
980
    }
981

    
982
    //this while loop finds the rest of the parameters
983
    //and attempts to query for the field specified
984
    //by the parameter.
985
    elements = params.elements();
986
    keys = params.keys();
987
    while(keys.hasMoreElements() && elements.hasMoreElements())
988
    {
989
      nextkey = keys.nextElement();
990
      nextelement = elements.nextElement();
991

    
992
      //make sure we aren't querying for any of these
993
      //parameters since the are already in the query
994
      //in one form or another.
995
      Vector ignoredParams = new Vector();
996
      ignoredParams.add("returndoctype");
997
      ignoredParams.add("filterdoctype");
998
      ignoredParams.add("action");
999
      ignoredParams.add("qformat");
1000
      ignoredParams.add("anyfield");
1001
      ignoredParams.add("returnfield");
1002
      ignoredParams.add("owner");
1003
      ignoredParams.add("site");
1004
      ignoredParams.add("operator");
1005

    
1006
      // Also ignore parameters listed in the properties file
1007
      // so that they can be passed through to stylesheets
1008
      String paramsToIgnore = MetaCatUtil.getOption("query.ignored.params");
1009
      StringTokenizer st = new StringTokenizer(paramsToIgnore, ",");
1010
      while (st.hasMoreTokens()) {
1011
          ignoredParams.add(st.nextToken());
1012
      }
1013
      if (!ignoredParams.contains(nextkey.toString())) {
1014
        //allow for more than value per field name
1015
        for(int i=0; i<((String[])nextelement).length; i++) {
1016
          if (!((String[])nextelement)[i].equals("")) {
1017
            query.append("<queryterm casesensitive=\"" + casesensitive +"\" " +
1018
                         "searchmode=\"" + searchmode + "\">" +
1019
                         "<value>" +
1020
                         //add the query value
1021
                         ((String[])nextelement)[i] +
1022
                         "</value><pathexpr>" +
1023
                         //add the path to query by
1024
                         nextkey.toString() +
1025
                         "</pathexpr></queryterm>");
1026
          }
1027
        }
1028
      }
1029
    }
1030
    query.append("</querygroup></pathquery>");
1031
    //append on the end of the xml and return the result as a string
1032
    return query.toString();
1033
  }
1034

    
1035
  /**
1036
   * format a simple free-text value query as an XML document that conforms
1037
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
1038
   * structured query engine
1039
   *
1040
   * @param value the text string to search for in the xml catalog
1041
   * @param doctype the type of documents to include in the result set -- use
1042
   *        "any" or "ANY" for unfiltered result sets
1043
   */
1044
   public static String createQuery(String value, String doctype) {
1045
     StringBuffer xmlquery = new StringBuffer();
1046
     xmlquery.append("<?xml version=\"1.0\"?>\n");
1047
     xmlquery.append("<pathquery version=\"1.0\">");
1048

    
1049
     if (!doctype.equals("any") && !doctype.equals("ANY")) {
1050
       xmlquery.append("<returndoctype>");
1051
       xmlquery.append(doctype).append("</returndoctype>");
1052
     }
1053

    
1054
     xmlquery.append("<querygroup operator=\"UNION\">");
1055
     //chad added - 8/14
1056
     //the if statement allows a query to gracefully handle a null
1057
     //query.  Without this if a nullpointerException is thrown.
1058
     if (!value.equals(""))
1059
     {
1060
       xmlquery.append("<queryterm casesensitive=\"false\" ");
1061
       xmlquery.append("searchmode=\"contains\">");
1062
       xmlquery.append("<value>").append(value).append("</value>");
1063
       xmlquery.append("</queryterm>");
1064
     }
1065
     xmlquery.append("</querygroup>");
1066
     xmlquery.append("</pathquery>");
1067

    
1068

    
1069
     return (xmlquery.toString());
1070
   }
1071

    
1072
  /**
1073
   * format a simple free-text value query as an XML document that conforms
1074
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
1075
   * structured query engine
1076
   *
1077
   * @param value the text string to search for in the xml catalog
1078
   */
1079
   public static String createQuery(String value) {
1080
     return createQuery(value, "any");
1081
   }
1082

    
1083
  /**
1084
    * Check for "READ" permission on @docid for @user and/or @group
1085
    * from DB connection
1086
    */
1087
  private boolean hasPermission (String user,
1088
                                  String[] groups, String docid )
1089
                  throws SQLException, Exception
1090
  {
1091
    // Check for READ permission on @docid for @user and/or @groups
1092
   PermissionController controller = new PermissionController(docid);
1093
   return controller.hasPermission(user,groups,
1094
                                 AccessControlInterface.READSTRING);
1095
  }
1096

    
1097
  /**
1098
    * Get all docIds list for a data packadge
1099
    * @param dataPackageDocid, the string in docId field of xml_relation table
1100
    */
1101
  private Vector getCurrentDocidListForDataPackage(String dataPackageDocid)
1102
  {
1103
    DBConnection dbConn = null;
1104
    int serialNumber = -1;
1105
    Vector docIdList=new Vector();//return value
1106
    PreparedStatement pStmt = null;
1107
    ResultSet rs=null;
1108
    String docIdInSubjectField=null;
1109
    String docIdInObjectField=null;
1110

    
1111
    // Check the parameter
1112
    if (dataPackageDocid == null || dataPackageDocid.equals(""))
1113
    {
1114
      return docIdList;
1115
    }//if
1116

    
1117
    //the query stirng
1118
    String query="SELECT subject, object from xml_relation where docId = ?";
1119
    try
1120
    {
1121
      dbConn=DBConnectionPool.
1122
                  getDBConnection("DBQuery.getCurrentDocidListForDataPackage");
1123
      serialNumber=dbConn.getCheckOutSerialNumber();
1124
      pStmt=dbConn.prepareStatement(query);
1125
      //bind the value to query
1126
      pStmt.setString(1, dataPackageDocid);
1127

    
1128
      //excute the query
1129
      pStmt.execute();
1130
      //get the result set
1131
      rs=pStmt.getResultSet();
1132
      //process the result
1133
      while (rs.next())
1134
      {
1135
        //In order to get the whole docIds in a data packadge,
1136
        //we need to put the docIds of subject and object field in xml_relation
1137
        //into the return vector
1138
        docIdInSubjectField=rs.getString(1);//the result docId in subject field
1139
        docIdInObjectField=rs.getString(2);//the result docId in object field
1140

    
1141
        //don't put the duplicate docId into the vector
1142
        if (!docIdList.contains(docIdInSubjectField))
1143
        {
1144
          docIdList.add(docIdInSubjectField);
1145
        }
1146

    
1147
        //don't put the duplicate docId into the vector
1148
        if (!docIdList.contains(docIdInObjectField))
1149
        {
1150
          docIdList.add(docIdInObjectField);
1151
        }
1152
      }//while
1153
      //close the pStmt
1154
      pStmt.close();
1155
    }//try
1156
    catch (SQLException e)
1157
    {
1158
      MetaCatUtil.debugMessage("Error in getDocidListForDataPackage: "
1159
                            +e.getMessage(), 30);
1160
    }//catch
1161
    finally
1162
    {
1163
      try
1164
      {
1165
        pStmt.close();
1166
      }//try
1167
      catch (SQLException ee)
1168
      {
1169
        MetaCatUtil.debugMessage("Error in getDocidListForDataPackage: "
1170
                            +ee.getMessage(), 30);
1171
      }//catch
1172
      finally
1173
      {
1174
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1175
      }//fianlly
1176
    }//finally
1177
    return docIdList;
1178
  }//getCurrentDocidListForDataPackadge()
1179

    
1180
  /**
1181
   * Get all docIds list for a data packadge
1182
   * @param dataPackageDocid, the string in docId field of xml_relation table
1183
   */
1184
  private Vector getOldVersionDocidListForDataPackage(String dataPackageDocid)
1185
  {
1186

    
1187
    Vector docIdList=new Vector();//return value
1188
    Vector tripleList=null;
1189
    String xml=null;
1190

    
1191
     // Check the parameter
1192
    if (dataPackageDocid == null || dataPackageDocid.equals(""))
1193
    {
1194
      return docIdList;
1195
    }//if
1196

    
1197
    try
1198
    {
1199
      //initial a documentImpl object
1200
      DocumentImpl packageDocument =
1201
                  new DocumentImpl(dataPackageDocid);
1202
      //transfer to documentImpl object to string
1203
      xml=packageDocument.toString();
1204

    
1205
      //create a tripcollection object
1206
      TripleCollection tripleForPackage = new
1207
                                     TripleCollection(new StringReader(xml));
1208
      //get the vetor of triples
1209
      tripleList=tripleForPackage.getCollection();
1210

    
1211
      for (int i= 0; i<tripleList.size(); i++)
1212
      {
1213
        //put subject docid  into docIdlist without duplicate
1214
        if (!docIdList.contains(((Triple)tripleList.elementAt(i)).getSubject()))
1215
        {
1216
          //put subject docid  into docIdlist
1217
          docIdList.add(((Triple)tripleList.get(i)).getSubject());
1218
        }
1219
        //put object docid into docIdlist without duplicate
1220
        if (!docIdList.contains(((Triple)tripleList.elementAt(i)).getObject()))
1221
        {
1222
          docIdList.add(((Triple)(tripleList.get(i))).getObject());
1223
        }
1224
      }//for
1225
    }//try
1226
    catch (Exception e)
1227
    {
1228
      MetaCatUtil.debugMessage("Error in getOldVersionAllDocumentImpl: "
1229
                            +e.getMessage(), 30);
1230
    }//catch
1231

    
1232
    // return result
1233
    return docIdList;
1234
  }//getDocidListForPackageInXMLRevisions()
1235

    
1236
  /**
1237
   * Check if the docId is a data packadge id. If the id is a data packadage
1238
   *id, it should be store in the docId fields in xml_relation table.
1239
   *So we can use a query to get the entries which the docId equals the given
1240
   *value. If the result is null. The docId is not a packadge id. Otherwise,
1241
   * it is.
1242
   * @param docId, the id need to be checked
1243
   */
1244
  private boolean isDataPackageId(String docId)
1245
  {
1246
    boolean result=false;
1247
    PreparedStatement pStmt = null;
1248
    ResultSet rs=null;
1249
    String query="SELECT docId from xml_relation where docId = ?";
1250
    DBConnection dbConn = null;
1251
    int serialNumber = -1;
1252
    try
1253
    {
1254
      dbConn=DBConnectionPool.
1255
                  getDBConnection("DBQuery.isDataPackageId");
1256
      serialNumber=dbConn.getCheckOutSerialNumber();
1257
      pStmt=dbConn.prepareStatement(query);
1258
      //bind the value to query
1259
      pStmt.setString(1, docId);
1260
      //execute the query
1261
      pStmt.execute();
1262
      rs=pStmt.getResultSet();
1263
      //process the result
1264
      if (rs.next()) //There are some records for the id in docId fields
1265
      {
1266
        result=true;//It is a data packadge id
1267
      }
1268
      pStmt.close();
1269
    }//try
1270
    catch (SQLException e)
1271
    {
1272
        MetaCatUtil.debugMessage("Error in isDataPackageId: "
1273
                            +e.getMessage(), 30);
1274
    }
1275
    finally
1276
    {
1277
      try
1278
      {
1279
        pStmt.close();
1280
      }//try
1281
      catch (SQLException ee)
1282
      {
1283
        MetaCatUtil.debugMessage("Error in isDataPackageId: "
1284
                                                        + ee.getMessage(), 30);
1285
      }//catch
1286
      finally
1287
      {
1288
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1289
      }//finally
1290
    }//finally
1291
    return result;
1292
  }//isDataPackageId()
1293

    
1294
  /**
1295
   * Check if the user has the permission to export data package
1296
   * @param conn, the connection
1297
   * @param docId, the id need to be checked
1298
   * @param user, the name of user
1299
   * @param groups, the user's group
1300
   */
1301
   private boolean hasPermissionToExportPackage(String docId,
1302
                                        String user, String[] groups)
1303
                   throws Exception
1304
   {
1305
     //DocumentImpl doc=new DocumentImpl(conn,docId);
1306
     return DocumentImpl.hasReadPermission(user, groups,docId);
1307
   }
1308

    
1309
  /**
1310
   *Get the current Rev for a docid in xml_documents table
1311
   * @param docId, the id need to get version numb
1312
   * If the return value is -5, means no value in rev field for this docid
1313
   */
1314
  private int getCurrentRevFromXMLDoumentsTable(String docId)
1315
                                                throws SQLException
1316
  {
1317
    int rev=-5;
1318
    PreparedStatement pStmt = null;
1319
    ResultSet rs=null;
1320
    String query="SELECT rev from xml_documents where docId = ?";
1321
    DBConnection dbConn=null;
1322
    int serialNumber = -1;
1323
    try
1324
    {
1325
      dbConn=DBConnectionPool.
1326
                  getDBConnection("DBQuery.getCurrentRevFromXMLDocumentsTable");
1327
      serialNumber=dbConn.getCheckOutSerialNumber();
1328
      pStmt=dbConn.prepareStatement(query);
1329
      //bind the value to query
1330
      pStmt.setString(1, docId);
1331
      //execute the query
1332
      pStmt.execute();
1333
      rs=pStmt.getResultSet();
1334
      //process the result
1335
      if (rs.next()) //There are some records for rev
1336
      {
1337
        rev=rs.getInt(1);;//It is the version for given docid
1338
      }
1339
      else
1340
      {
1341
        rev=-5;
1342
      }
1343

    
1344
    }//try
1345
    catch (SQLException e)
1346
    {
1347
      MetaCatUtil.debugMessage("Error in getCurrentRevFromXMLDoumentsTable: "
1348
                            +e.getMessage(), 30);
1349
      throw e;
1350
    }//catch
1351
    finally
1352
    {
1353
      try
1354
      {
1355
        pStmt.close();
1356
      }//try
1357
      catch (SQLException ee)
1358
      {
1359
        MetaCatUtil.debugMessage("Error in getCurrentRevFromXMLDoumentsTable: "
1360
                                  +ee.getMessage(), 30);
1361
      }//catch
1362
      finally
1363
      {
1364
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1365
      }//finally
1366
    }//finally
1367
    return rev;
1368
  }//getCurrentRevFromXMLDoumentsTable
1369

    
1370
 /**
1371
   *put a doc into a zip output stream
1372
   *@param docImpl, docmentImpl object which will be sent to zip output stream
1373
   *@param zipOut, zip output stream which the docImpl will be put
1374
   *@param packageZipEntry, the zip entry name for whole package
1375
   */
1376
  private void addDocToZipOutputStream(DocumentImpl docImpl,
1377
                                ZipOutputStream zipOut, String packageZipEntry)
1378
               throws ClassNotFoundException, IOException, SQLException,
1379
                      McdbException, Exception
1380
  {
1381
    byte[] byteString = null;
1382
    ZipEntry zEntry = null;
1383

    
1384
    byteString = docImpl.toString().getBytes();
1385
    //use docId as the zip entry's name
1386
    zEntry = new ZipEntry(packageZipEntry+"/metadata/"+docImpl.getDocID());
1387
    zEntry.setSize(byteString.length);
1388
    zipOut.putNextEntry(zEntry);
1389
    zipOut.write(byteString, 0, byteString.length);
1390
    zipOut.closeEntry();
1391

    
1392
  }//addDocToZipOutputStream()
1393

    
1394

    
1395
  /**
1396
   * Transfer a docid vetor to a documentImpl vector. The documentImpl vetor
1397
   * only inlcudes current version. If a DocumentImple object
1398
   * couldn't find for a docid, then the String of this docid was added to vetor
1399
   * rather than DocumentImple object.
1400
   * @param docIdList, a vetor hold a docid list for a data package. In docid,
1401
   * there is not version number in it.
1402
   */
1403

    
1404
  private Vector getCurrentAllDocumentImpl( Vector docIdList)
1405
                              throws McdbException,Exception
1406
  {
1407
    //Connection dbConn=null;
1408
    Vector documentImplList=new Vector();
1409
    int rev=0;
1410

    
1411
    // Check the parameter
1412
    if (docIdList.isEmpty())
1413
    {
1414
      return documentImplList;
1415
    }//if
1416

    
1417
    //for every docid in vector
1418
    for (int i=0;i<docIdList.size();i++)
1419
    {
1420
      try
1421
      {
1422
        //get newest version for this docId
1423
        rev=getCurrentRevFromXMLDoumentsTable((String)docIdList.elementAt(i));
1424

    
1425
        // There is no record for this docId in xml_documents table
1426
        if (rev ==-5)
1427
        {
1428
          // Rather than put DocumentImple object, put a String Object(docid)
1429
          // into the documentImplList
1430
          documentImplList.add((String)docIdList.elementAt(i));
1431
          // Skip other code
1432
          continue;
1433
        }
1434

    
1435
        String docidPlusVersion=((String)docIdList.elementAt(i))
1436
                        +MetaCatUtil.getOption("accNumSeparator")+rev;
1437

    
1438

    
1439
        //create new documentImpl object
1440
        DocumentImpl documentImplObject =
1441
                                    new DocumentImpl(docidPlusVersion);
1442
       //add them to vector
1443
        documentImplList.add(documentImplObject);
1444
      }//try
1445
      catch (Exception e)
1446
      {
1447
        MetaCatUtil.debugMessage("Error in getCurrentAllDocumentImpl: "
1448
                            +e.getMessage(), 30);
1449
        // continue the for loop
1450
        continue;
1451
      }
1452
    }//for
1453
    return documentImplList;
1454
  }
1455

    
1456
  /**
1457
   * Transfer a docid vetor to a documentImpl vector. If a DocumentImple object
1458
   * couldn't find for a docid, then the String of this docid was added to vetor
1459
   * rather than DocumentImple object.
1460
   * @param docIdList, a vetor hold a docid list for a data package. In docid,
1461
   *t here is version number in it.
1462
   */
1463
  private Vector getOldVersionAllDocumentImpl( Vector docIdList)
1464
  {
1465
    //Connection dbConn=null;
1466
    Vector documentImplList=new Vector();
1467
    String siteCode=null;
1468
    String uniqueId=null;
1469
    int rev=0;
1470

    
1471
    // Check the parameter
1472
    if (docIdList.isEmpty())
1473
    {
1474
      return documentImplList;
1475
    }//if
1476

    
1477
    //for every docid in vector
1478
    for (int i=0;i<docIdList.size();i++)
1479
    {
1480

    
1481
        String docidPlusVersion=(String)(docIdList.elementAt(i));
1482

    
1483
        try
1484
        {
1485
          //create new documentImpl object
1486
          DocumentImpl documentImplObject =
1487
                                    new DocumentImpl(docidPlusVersion);
1488
          //add them to vector
1489
          documentImplList.add(documentImplObject);
1490
        }//try
1491
        catch (McdbDocNotFoundException notFoundE)
1492
        {
1493
          MetaCatUtil.debugMessage("Error in DBQuery.getOldVersionAllDocument"+
1494
                                  "Imple" + notFoundE.getMessage(), 30);
1495
          // Rather than add a DocumentImple object into vetor, a String object
1496
          // - the doicd was added to the vector
1497
          documentImplList.add(docidPlusVersion);
1498
          // Continue the for loop
1499
          continue;
1500
        }//catch
1501
        catch (Exception e)
1502
        {
1503
          MetaCatUtil.debugMessage("Error in DBQuery.getOldVersionAllDocument"+
1504
                                  "Imple" + e.getMessage(), 30);
1505
          // Continue the for loop
1506
          continue;
1507
        }//catch
1508

    
1509

    
1510
    }//for
1511
    return documentImplList;
1512
  }//getOldVersionAllDocumentImple
1513

    
1514
  /**
1515
   *put a data file into a zip output stream
1516
   *@param docImpl, docmentImpl object which will be sent to zip output stream
1517
   *@param zipOut, the zip output stream which the docImpl will be put
1518
   *@param packageZipEntry, the zip entry name for whole package
1519
   */
1520
  private void addDataFileToZipOutputStream(DocumentImpl docImpl,
1521
                                ZipOutputStream zipOut, String packageZipEntry)
1522
               throws ClassNotFoundException, IOException, SQLException,
1523
                      McdbException, Exception
1524
  {
1525
    byte[] byteString = null;
1526
    ZipEntry zEntry = null;
1527
    // this is data file; add file to zip
1528
    String filePath = MetaCatUtil.getOption("datafilepath");
1529
    if (!filePath.endsWith("/"))
1530
    {
1531
      filePath += "/";
1532
    }
1533
    String fileName = filePath + docImpl.getDocID();
1534
    zEntry = new ZipEntry(packageZipEntry+"/data/"+docImpl.getDocID());
1535
    zipOut.putNextEntry(zEntry);
1536
    FileInputStream fin = null;
1537
    try
1538
    {
1539
      fin = new FileInputStream(fileName);
1540
      byte[] buf = new byte[4 * 1024]; // 4K buffer
1541
      int b = fin.read(buf);
1542
      while (b != -1)
1543
      {
1544
        zipOut.write(buf, 0, b);
1545
        b = fin.read(buf);
1546
      }//while
1547
      zipOut.closeEntry();
1548
    }//try
1549
    catch (IOException ioe)
1550
    {
1551
        MetaCatUtil.debugMessage("There is an exception: "+ioe.getMessage(), 30);
1552
    }//catch
1553
  }//addDataFileToZipOutputStream()
1554

    
1555
  /**
1556
   *create a html summary for data package and put it into zip output stream
1557
   *@param docImplList, the documentImpl ojbects in data package
1558
   *@param zipOut, the zip output stream which the html should be put
1559
   *@param packageZipEntry, the zip entry name for whole package
1560
   */
1561
   private void addHtmlSummaryToZipOutputStream(Vector docImplList,
1562
                                ZipOutputStream zipOut, String packageZipEntry)
1563
                                           throws Exception
1564
  {
1565
    StringBuffer htmlDoc = new StringBuffer();
1566
    ZipEntry zEntry = null;
1567
    byte[] byteString=null;
1568
    InputStream source;
1569
    DBTransform xmlToHtml;
1570

    
1571
    //create a DBTransform ojbect
1572
    xmlToHtml = new DBTransform();
1573
    //head of html
1574
    htmlDoc.append("<html><head></head><body>");
1575
    for (int i=0; i<docImplList.size(); i++)
1576
    {
1577
      // If this String object, this means it is missed data file
1578
      if ((((docImplList.elementAt(i)).getClass()).toString())
1579
                                             .equals("class java.lang.String"))
1580
      {
1581

    
1582
        htmlDoc.append("<a href=\"");
1583
        String dataFileid =(String)docImplList.elementAt(i);
1584
        htmlDoc.append("./data/").append(dataFileid).append("\">");
1585
        htmlDoc.append("Data File: ");
1586
        htmlDoc.append(dataFileid).append("</a><br>");
1587
        htmlDoc.append("<br><hr><br>");
1588

    
1589
      }//if
1590
      else if ((((DocumentImpl)docImplList.elementAt(i)).getDoctype()).
1591
                                                         compareTo("BIN")!=0)
1592
      { //this is an xml file so we can transform it.
1593
        //transform each file individually then concatenate all of the
1594
        //transformations together.
1595

    
1596
        //for metadata xml title
1597
        htmlDoc.append("<h2>");
1598
        htmlDoc.append(((DocumentImpl)docImplList.elementAt(i)).getDocID());
1599
        //htmlDoc.append(".");
1600
        //htmlDoc.append(((DocumentImpl)docImplList.elementAt(i)).getRev());
1601
        htmlDoc.append("</h2>");
1602
        //do the actual transform
1603
        StringWriter docString = new StringWriter();
1604
        xmlToHtml.transformXMLDocument(
1605
                        ((DocumentImpl)docImplList.elementAt(i)).toString(),
1606
           "-//NCEAS//eml-generic//EN", "-//W3C//HTML//EN", "html", docString);
1607
        htmlDoc.append(docString.toString());
1608
        htmlDoc.append("<br><br><hr><br><br>");
1609
      }//if
1610
      else
1611
      { //this is a data file so we should link to it in the html
1612
        htmlDoc.append("<a href=\"");
1613
        String dataFileid =((DocumentImpl)docImplList.elementAt(i)).getDocID();
1614
        htmlDoc.append("./data/").append(dataFileid).append("\">");
1615
        htmlDoc.append("Data File: ");
1616
        htmlDoc.append(dataFileid).append("</a><br>");
1617
        htmlDoc.append("<br><hr><br>");
1618
      }//else
1619
    }//for
1620
    htmlDoc.append("</body></html>");
1621
    byteString = htmlDoc.toString().getBytes();
1622
    zEntry = new ZipEntry(packageZipEntry+"/metadata.html");
1623
    zEntry.setSize(byteString.length);
1624
    zipOut.putNextEntry(zEntry);
1625
    zipOut.write(byteString, 0, byteString.length);
1626
    zipOut.closeEntry();
1627
    //dbConn.close();
1628

    
1629
  }//addHtmlSummaryToZipOutputStream
1630

    
1631

    
1632

    
1633
  /**
1634
   * put a data packadge into a zip output stream
1635
   * @param docId, which the user want to put into zip output stream
1636
   * @param out, a servletoutput stream which the zip output stream will be put
1637
   * @param user, the username of the user
1638
   * @param groups, the group of the user
1639
   */
1640
  public ZipOutputStream getZippedPackage(String docIdString,
1641
        ServletOutputStream out, String user, String[] groups, String passWord)
1642
                    throws ClassNotFoundException, IOException, SQLException,
1643
                      McdbException, NumberFormatException, Exception
1644
  {
1645
    ZipOutputStream zOut = null;
1646
    String elementDocid=null;
1647
    DocumentImpl docImpls=null;
1648
    //Connection dbConn = null;
1649
    Vector docIdList=new Vector();
1650
    Vector documentImplList=new Vector();
1651
    Vector htmlDocumentImplList=new Vector();
1652
    String packageId=null;
1653
    String rootName="package";//the package zip entry name
1654

    
1655
    String docId=null;
1656
    int version=-5;
1657
    // Docid without revision
1658
    docId=MetaCatUtil.getDocIdFromString(docIdString);
1659
    // revision number
1660
    version=MetaCatUtil.getVersionFromString(docIdString);
1661

    
1662
    //check if the reqused docId is a data package id
1663
    if (!isDataPackageId(docId))
1664
    {
1665

    
1666
      /*Exception e = new Exception("The request the doc id " +docIdString+
1667
                                    " is not a data package id");
1668
      throw e;*/
1669

    
1670

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

    
1674
      if(!hasPermissionToExportPackage(docId, user, groups))
1675
      {
1676

    
1677
        Exception e = new Exception("User " + user + " does not have permission"
1678
                         +" to export the data package " + docIdString);
1679
        throw e;
1680
      }
1681

    
1682
      docImpls=new DocumentImpl(docId);
1683
      //checking if the user has the permission to read the documents
1684
      if (DocumentImpl.hasReadPermission(user,groups,docImpls.getDocID()))
1685
      {
1686
        zOut = new ZipOutputStream(out);
1687
        //if the docImpls is metadata
1688
        if ((docImpls.getDoctype()).compareTo("BIN")!=0)
1689
        {
1690
          //add metadata into zip output stream
1691
          addDocToZipOutputStream(docImpls, zOut, rootName);
1692
        }//if
1693
        else
1694
        {
1695
          //it is data file
1696
          addDataFileToZipOutputStream(docImpls, zOut, rootName);
1697
          htmlDocumentImplList.add(docImpls);
1698
        }//else
1699
      }//if
1700

    
1701
      zOut.finish(); //terminate the zip file
1702
      return zOut;
1703
    }
1704
    // Check the permission of user
1705
    else if(!hasPermissionToExportPackage(docId, user, groups))
1706
    {
1707

    
1708
      Exception e = new Exception("User " + user + " does not have permission"
1709
                       +" to export the data package " + docIdString);
1710
      throw e;
1711
    }
1712
    else //it is a packadge id
1713
    {
1714
      //store the package id
1715
      packageId=docId;
1716
      //get current version in database
1717
      int currentVersion = getCurrentRevFromXMLDoumentsTable(packageId);
1718
      //If it is for current version (-1 means user didn't specify revision)
1719
      if ((version ==-1)||version==currentVersion)
1720
      {
1721
        //get current version number
1722
        version=currentVersion;
1723
        //get package zip entry name
1724
        //it should be docId.revsion.package
1725
        rootName=packageId+MetaCatUtil.getOption("accNumSeparator")+version+
1726
                 MetaCatUtil.getOption("accNumSeparator")+"package";
1727
        //get the whole id list for data packadge
1728
        docIdList=getCurrentDocidListForDataPackage(packageId);
1729
        //get the whole documentImple object
1730
        documentImplList=getCurrentAllDocumentImpl(docIdList);
1731

    
1732
      }//if
1733
      else if (version > currentVersion || version < -1)
1734
      {
1735
        throw new Exception ("The user specified docid: "+docId+"."+version
1736
                                              +" doesn't exist");
1737
      }//else if
1738
      else  //for an old version
1739
      {
1740

    
1741
        rootName=docIdString+MetaCatUtil.getOption("accNumSeparator")+"package";
1742
        //get the whole id list for data packadge
1743
        docIdList=getOldVersionDocidListForDataPackage(docIdString);
1744

    
1745
        //get the whole documentImple object
1746
        documentImplList=getOldVersionAllDocumentImpl(docIdList);
1747
      }//else
1748

    
1749
      // Make sure documentImplist is not empty
1750
      if (documentImplList.isEmpty())
1751
      {
1752
        throw new Exception ("Couldn't find component for data package: "
1753
                                              + packageId);
1754
      }//if
1755

    
1756

    
1757
       zOut = new ZipOutputStream(out);
1758
      //put every element into zip output stream
1759
      for (int i=0; i < documentImplList.size(); i++ )
1760
      {
1761
        // if the object in the vetor is String, this means we couldn't find
1762
        // the document locally, we need find it remote
1763
       if ((((documentImplList.elementAt(i)).getClass()).toString())
1764
                                             .equals("class java.lang.String"))
1765
        {
1766
          // Get String object from vetor
1767
          String documentId = (String) documentImplList.elementAt(i);
1768
          MetaCatUtil.debugMessage("docid: "+documentId, 30);
1769
          // Get doicd without revision
1770
          String docidWithoutRevision =
1771
                                     MetaCatUtil.getDocIdFromString(documentId);
1772
          MetaCatUtil.debugMessage("docidWithoutRevsion: "
1773
                                                     +docidWithoutRevision, 30);
1774
          // Get revision
1775
          String revision = MetaCatUtil.getRevisionStringFromString(documentId);
1776
          MetaCatUtil.debugMessage("revsion from docIdentifier: "+revision, 30);
1777
          // Zip entry string
1778
          String zipEntryPath = rootName+"/data/";
1779
          // Create a RemoteDocument object
1780
          RemoteDocument remoteDoc =
1781
                          new RemoteDocument(docidWithoutRevision,revision,user,
1782
                                                     passWord, zipEntryPath);
1783
          // Here we only read data file from remote metacat
1784
          String docType = remoteDoc.getDocType();
1785
          if (docType!=null)
1786
          {
1787
            if (docType.equals("BIN"))
1788
            {
1789
              // Put remote document to zip output
1790
              remoteDoc.readDocumentFromRemoteServerByZip(zOut);
1791
              // Add String object to htmlDocumentImplList
1792
              String elementInHtmlList = remoteDoc.getDocIdWithoutRevsion()+
1793
               MetaCatUtil.getOption("accNumSeparator")+remoteDoc.getRevision();
1794
              htmlDocumentImplList.add(elementInHtmlList);
1795
            }//if
1796
          }//if
1797

    
1798
        }//if
1799
        else
1800
        {
1801
          //create a docmentImpls object (represent xml doc) base on the docId
1802
          docImpls=(DocumentImpl)documentImplList.elementAt(i);
1803
          //checking if the user has the permission to read the documents
1804
          if (DocumentImpl.hasReadPermission(user,groups,docImpls.getDocID()))
1805
          {
1806
            //if the docImpls is metadata
1807
            if ((docImpls.getDoctype()).compareTo("BIN")!=0)
1808
            {
1809
              //add metadata into zip output stream
1810
              addDocToZipOutputStream(docImpls, zOut, rootName);
1811
              //add the documentImpl into the vetor which will be used in html
1812
              htmlDocumentImplList.add(docImpls);
1813

    
1814
            }//if
1815
            else
1816
            {
1817
              //it is data file
1818
              addDataFileToZipOutputStream(docImpls, zOut, rootName);
1819
              htmlDocumentImplList.add(docImpls);
1820
            }//else
1821
          }//if
1822
        }//else
1823
      }//for
1824

    
1825
      //add html summary file
1826
      addHtmlSummaryToZipOutputStream(htmlDocumentImplList, zOut, rootName);
1827
      zOut.finish(); //terminate the zip file
1828
      //dbConn.close();
1829
      return zOut;
1830
    }//else
1831
  }//getZippedPackage()
1832

    
1833
   private class ReturnFieldValue
1834
  {
1835
    private String docid          = null; //return field value for this docid
1836
    private String fieldValue     = null;
1837
    private String xmlFieldValue  = null; //return field value in xml format
1838

    
1839

    
1840
    public void setDocid(String myDocid)
1841
    {
1842
      docid = myDocid;
1843
    }
1844

    
1845
    public String getDocid()
1846
    {
1847
      return docid;
1848
    }
1849

    
1850
    public void setFieldValue(String myValue)
1851
    {
1852
      fieldValue = myValue;
1853
    }
1854

    
1855
    public String getFieldValue()
1856
    {
1857
      return fieldValue;
1858
    }
1859

    
1860
    public void setXMLFieldValue(String xml)
1861
    {
1862
      xmlFieldValue = xml;
1863
    }
1864

    
1865
    public String getXMLFieldValue()
1866
    {
1867
      return xmlFieldValue;
1868
    }
1869

    
1870
  }
1871
}
(22-22/58)