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: 2003-03-03 18:06:36 -0800 (Mon, 03 Mar 2003) $'
15
 * '$Revision: 1445 $'
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.Vector;
37
import java.util.zip.*;
38
import java.net.URL;
39
import java.net.MalformedURLException;
40
import java.sql.*;
41
import java.util.Stack;
42
import java.util.Hashtable;
43
import java.util.Enumeration;
44
import java.io.File;
45
import java.io.FileWriter;
46
import java.io.BufferedWriter;
47
import javax.servlet.ServletOutputStream;
48

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

    
58
  static final int ALL = 1;
59
  static final int WRITE = 2;
60
  static final int READ = 4;
61
 
62
  //private Connection  conn = null;
63
  private String  parserName = null;
64
  private MetaCatUtil util = new MetaCatUtil();
65
  /**
66
   * the main routine used to test the DBQuery utility.
67
   * <p>
68
   * Usage: java DBQuery <xmlfile>
69
   *
70
   * @param xmlfile the filename of the xml file containing the query
71
   */
72
  static public void main(String[] args) {
73
     
74
     if (args.length < 1)
75
     {
76
        System.err.println("Wrong number of arguments!!!");
77
        System.err.println("USAGE: java DBQuery [-t] [-index] <xmlfile>");
78
        return;
79
     } else {
80
        try {
81

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

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

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

    
102
          double connTime = System.currentTimeMillis();
103

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

    
110
          // Print the reulting document listing
111
          StringBuffer result = new StringBuffer();
112
          String document = null;
113
          String docid = null;
114
          result.append("<?xml version=\"1.0\"?>\n");
115
          result.append("<resultset>\n"); 
116
  
117
          if (!showRuntime)
118
          {
119
            Enumeration doclist = nodelist.keys();
120
            while (doclist.hasMoreElements()) {
121
              docid = (String)doclist.nextElement();
122
              document = (String)nodelist.get(docid);
123
              result.append("  <document>\n    " + document + 
124
                            "\n  </document>\n");
125
            }
126
            
127
            result.append("</resultset>\n");
128
          }
129
          // Time the request if asked for
130
          double stopTime = System.currentTimeMillis();
131
          double dbOpenTime = (connTime - startTime)/1000;
132
          double readTime = (stopTime - connTime)/1000;
133
          double executionTime = (stopTime - startTime)/1000;
134
          if (showRuntime) {
135
            System.out.print("  " + executionTime);
136
            System.out.print("  " + dbOpenTime);
137
            System.out.print("  " + readTime);
138
            System.out.print("  " + nodelist.size());
139
            System.out.println();
140
          }
141
          //System.out.println(result);
142
          //write into a file "result.txt"
143
          if (!showRuntime)
144
          {
145
            File f = new File("./result.txt");
146
            FileWriter fw = new FileWriter(f);
147
            BufferedWriter out = new BufferedWriter(fw);
148
            out.write(result.toString());          
149
            out.flush();
150
            out.close();
151
            fw.close();
152
          }
153
          
154
        } 
155
        catch (Exception e) {
156
          System.err.println("Error in DBQuery.main");
157
          System.err.println(e.getMessage());
158
          e.printStackTrace(System.err);
159
        }
160
     }
161
  }
162
  
163
  /**
164
   * construct an instance of the DBQuery class 
165
   *
166
   * <p>Generally, one would call the findDocuments() routine after creating 
167
   * an instance to specify the search query</p>
168
   *
169
   * @param conn the JDBC connection that we use for the query
170
   * @param parserName the fully qualified name of a Java class implementing
171
   *                   the org.xml.sax.XMLReader interface
172
   */
173
  public DBQuery(String parserName ) 
174
                  throws IOException, 
175
                         SQLException, 
176
                         ClassNotFoundException {
177
    //this.conn = conn;
178
    this.parserName = parserName;
179
  }
180
  
181
  /** 
182
   * routine to search the elements and attributes looking to match query
183
   *
184
   * @param xmlquery the xml serialization of the query (@see pathquery.dtd)
185
   * @param user the username of the user
186
   * @param group the group of the user
187
   */
188
  public Hashtable findDocuments(Reader xmlquery, String user, String[] groups)
189
  {
190
    return findDocuments(xmlquery, user, groups, true);
191
  }
192

    
193
  /** 
194
   * routine to search the elements and attributes looking to match query
195
   *
196
   * @param xmlquery the xml serialization of the query (@see pathquery.dtd)
197
   * @param user the username of the user
198
   * @param group the group of the user
199
   * @param useXMLIndex flag whether to search using the path index
200
   */
201
  public Hashtable findDocuments(Reader xmlquery, String user, String[] groups,
202
                                 boolean useXMLIndex)
203
  {
204
      Hashtable   docListResult = new Hashtable();
205
      PreparedStatement pstmt = null;
206
      String docid = null;
207
      String docname = null;
208
      String doctype = null;
209
      String createDate = null;
210
      String updateDate = null;
211
      String fieldname = null;
212
      String fielddata = null;
213
      String relation = null;
214
      //Connection dbconn = null;
215
      //Connection dbconn2 = null;
216
      int rev = 0;
217
      StringBuffer document = null;
218
      DBConnection dbconn = null;
219
      int serialNumber = -1;
220
      
221
      try {
222
       
223
        
224
        dbconn=DBConnectionPool.getDBConnection("DBQuery.findDocuments");
225
        serialNumber=dbconn.getCheckOutSerialNumber();
226
      
227
        // Get the XML query and covert it into a SQL statment
228
        QuerySpecification qspec = new QuerySpecification(xmlquery, 
229
                                   parserName, 
230
                                   util.getOption("accNumSeparator"));
231
       
232
        String query = qspec.printSQL(useXMLIndex);
233
        String ownerQuery = getOwnerQuery(user);
234
        MetaCatUtil.debugMessage("query: "+query, 30);
235
        //MetaCatUtil.debugMessage("query: "+ownerQuery, 30);
236
        // if query is not the owner query, we need to check the permission
237
        // otherwise we don't need (owner has all permission by default)
238
        if (!query.equals(ownerQuery))
239
        {
240
          // set user name and group
241
          qspec.setUserName(user);
242
          qspec.setGroup(groups);
243
          // Get access query
244
          String accessQuery = qspec.getAccessQuery();
245
          query = query + accessQuery;
246
          MetaCatUtil.debugMessage(" final query: "+query, 30);
247
        }
248
        
249
        double startTime = System.currentTimeMillis()/1000;
250
        pstmt = dbconn.prepareStatement(query);
251
  
252
        // Execute the SQL query using the JDBC connection
253
        pstmt.execute();
254
        ResultSet rs = pstmt.getResultSet();
255
        double queryExecuteTime =System.currentTimeMillis()/1000; 
256
        MetaCatUtil.debugMessage("Time for execute query: "+ 
257
                                            (queryExecuteTime -startTime), 30);
258
        boolean tableHasRows = rs.next();
259
        while (tableHasRows) 
260
        {
261
          docid = rs.getString(1).trim();
262
          //long checkTimeStart = System.currentTimeMillis();
263
          //boolean permit =hasPermission(user, groups, docid);
264
          //long checkTimeEnd = System.currentTimeMillis();
265
          //MetaCatUtil.debugMessage("check permission time: "+
266
                                  //(checkTimeEnd - checkTimeStart), 30);
267
          //if ( !permit ) {
268
            // Advance to the next record in the cursor
269
            //tableHasRows = rs.next();
270
            //continue;
271
          //}
272
          
273
          docname = rs.getString(2);
274
          doctype = rs.getString(3);
275
          createDate = rs.getString(4);
276
          updateDate = rs.getString(5);
277
          rev = rs.getInt(6);
278

    
279
          // if there are returndocs to match, backtracking can be performed
280
          // otherwise, just return the document that was hit
281
          Vector returndocVec = qspec.getReturnDocList();
282
          if (returndocVec.size() != 0 && !returndocVec.contains(doctype) 
283
              && !qspec.isPercentageSearch())
284
          { 
285
            MetaCatUtil.debugMessage("Back tracing now...", 20);
286
            String sep = util.getOption("accNumSeparator");
287
            StringBuffer btBuf = new StringBuffer();
288
            btBuf.append("select docid from xml_relation where ");
289

    
290
            //build the doctype list for the backtracking sql statement
291
            btBuf.append("packagetype in (");
292
            for(int i=0; i<returndocVec.size(); i++)
293
            {
294
              btBuf.append("'").append((String)returndocVec.get(i)).append("'");
295
              if (i != (returndocVec.size() - 1))
296
              {
297
                btBuf.append(", ");
298
              } 
299
            }
300
            btBuf.append(") ");
301

    
302
            btBuf.append("and (subject like '");
303
            btBuf.append(docid).append("'");
304
            btBuf.append("or object like '");
305
            btBuf.append(docid).append("')");
306
            
307
            PreparedStatement npstmt = dbconn.
308
                                       prepareStatement(btBuf.toString());
309
            //should incease usage count
310
            dbconn.increaseUsageCount(1);
311
            npstmt.execute();
312
            ResultSet btrs = npstmt.getResultSet();
313
            boolean hasBtRows = btrs.next();
314
            while (hasBtRows)
315
            { //there was a backtrackable document found
316
              DocumentImpl xmldoc = null;
317
              String packageDocid = btrs.getString(1);
318
              util.debugMessage("Getting document for docid: "+packageDocid,40);
319
              try
320
              {
321
                //  THIS CONSTRUCTOR BUILDS THE WHOLE XML doc not needed here
322
                // xmldoc = new DocumentImpl(dbconn, packageDocid);
323
                //  thus use the following to get the doc info only
324
                //  xmldoc = new DocumentImpl(dbconn);
325
                xmldoc = new DocumentImpl(packageDocid, false);
326
                if (xmldoc == null) {
327
                  util.debugMessage("Document was null for: "+packageDocid, 50);
328
                }
329
              }
330
              catch(Exception e)
331
              {
332
                System.out.println("Error getting document in " + 
333
                                   "DBQuery.findDocuments: " + e.getMessage());
334
              }
335
              
336
              String docid_org = xmldoc.getDocID();
337
              if (docid_org == null) {
338
                util.debugMessage("Docid_org was null.", 40);
339
              }
340
              docid   = docid_org.trim();
341
              docname = xmldoc.getDocname();
342
              doctype = xmldoc.getDoctype();
343
              createDate = xmldoc.getCreateDate();
344
              updateDate = xmldoc.getUpdateDate();
345
              rev = xmldoc.getRev();
346

    
347
              document = new StringBuffer();
348

    
349
              String completeDocid = docid + util.getOption("accNumSeparator");
350
              completeDocid += rev;
351
              document.append("<docid>").append(completeDocid);
352
              document.append("</docid>");
353
              if (docname != null) {
354
                document.append("<docname>" + docname + "</docname>");
355
              }
356
              if (doctype != null) {
357
                document.append("<doctype>" + doctype + "</doctype>");
358
              }
359
              if (createDate != null) {
360
                document.append("<createdate>" + createDate + "</createdate>");
361
              }
362
              if (updateDate != null) {
363
                document.append("<updatedate>" + updateDate + "</updatedate>");
364
              }
365
              // Store the document id and the root node id
366
              docListResult.put(docid,(String)document.toString());
367
         
368
              // Get the next package document linked to our hit
369
              hasBtRows = btrs.next();
370
            }
371
            npstmt.close();
372
            btrs.close();
373
          } 
374
          else if (returndocVec.size() != 0 && returndocVec.contains(doctype)) 
375
          {
376
          
377
            document = new StringBuffer();
378

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

    
399
          // Advance to the next record in the cursor
400
          tableHasRows = rs.next();
401
        }
402
        rs.close();
403
        pstmt.close();
404
        double docListTime =System.currentTimeMillis()/1000;
405
        MetaCatUtil.debugMessage("prepare docid list time: "
406
                                          +(docListTime-queryExecuteTime), 30);
407
        
408
        if (qspec.containsExtendedSQL())
409
        {
410
          Vector extendedFields = new Vector(qspec.getReturnFieldList());
411
          Vector results = new Vector();
412
          Enumeration keylist = docListResult.keys();
413
          StringBuffer doclist = new StringBuffer();
414
          Hashtable parentidList = new Hashtable();
415
          Hashtable returnFieldValue = new Hashtable();
416
          while(keylist.hasMoreElements())
417
          {
418
            doclist.append("'");
419
            doclist.append((String)keylist.nextElement());
420
            doclist.append("',");
421
          }
422
          if (doclist.length() > 0) 
423
          {
424
            Hashtable controlPairs = new Hashtable();
425
            double extendedQueryStart = System.currentTimeMillis()/1000;
426
            doclist.deleteCharAt(doclist.length()-1); //remove the last comma
427
            // check if user has permission to see the return field data
428
            String accessControlSQL = qspec.
429
                        printAccessControlSQLForReturnField(doclist.toString());
430
            pstmt = dbconn.prepareStatement(accessControlSQL);
431
            //increase dbconnection usage count
432
            dbconn.increaseUsageCount(1);
433
            pstmt.execute();
434
            rs = pstmt.getResultSet();
435
            tableHasRows = rs.next();
436
            while(tableHasRows)
437
            {
438
              long startNodeId = rs.getLong(1);
439
              long endNodeId = rs.getLong(2);
440
              controlPairs.put(new Long(startNodeId), new Long(endNodeId));
441
            }
442
            
443
            double extendedAccessQueryEnd = System.currentTimeMillis()/1000;
444
            MetaCatUtil.debugMessage("Time for execute access extended query: "
445
                              +(extendedAccessQueryEnd-extendedQueryStart), 30);
446
            
447
            String extendedQuery = qspec.printExtendedSQL(doclist.toString());
448
            MetaCatUtil.debugMessage("Extended query: "+ extendedQuery, 30);
449
            pstmt = dbconn.prepareStatement(extendedQuery);
450
            //increase dbconnection usage count
451
            dbconn.increaseUsageCount(1);
452
            pstmt.execute();
453
            rs = pstmt.getResultSet();
454
            double extendedQueryEnd = System.currentTimeMillis()/1000;
455
            MetaCatUtil.debugMessage("Time for execute extended query: "
456
                                    +(extendedQueryEnd-extendedQueryStart), 30);
457
            tableHasRows = rs.next();
458
            while(tableHasRows) 
459
            {
460
              ReturnFieldValue returnValue = new ReturnFieldValue();
461
              docid = rs.getString(1).trim();
462
              fieldname = rs.getString(2);
463
              fielddata = rs.getString(3);
464
              String parentId = rs.getString(4);
465
                         
466
              StringBuffer value = new StringBuffer();
467
              if (!parentidList.containsKey(parentId))
468
              {
469
                // don't need to merger nodedata 
470
                value.append("<param name=\"");
471
                value.append(fieldname);
472
                value.append("\">");
473
                value.append(fielddata);
474
                value.append("</param>");
475
                //set returnvalue
476
                returnValue.setDocid(docid);
477
                returnValue.setFieldValue(fielddata);
478
                returnValue.setXMLFieldValue(value.toString());
479
                // Store it in hastable
480
                parentidList.put(parentId, returnValue);
481
              }
482
              else
483
              {
484
                // need to merge nodedata if they have same parent id ant
485
                // node type is text
486
                fielddata = (String)((ReturnFieldValue)
487
                       parentidList.get(parentId)).getFieldValue() +  fielddata;
488
                value.append("<param name=\"");
489
                value.append(fieldname);
490
                value.append("\">");
491
                value.append(fielddata);
492
                value.append("</param>");
493
                returnValue.setDocid(docid);
494
                returnValue.setFieldValue(fielddata);
495
                returnValue.setXMLFieldValue(value.toString());
496
                // remove the old return value from paretnidList
497
                parentidList.remove(parentId);
498
                // store the new return value in parentidlit
499
                parentidList.put(parentId, returnValue);
500
              }
501
               tableHasRows = rs.next();
502
            }//while
503
            rs.close();
504
            pstmt.close();
505
            
506
            // put the merger node data info into doclistReult
507
            Enumeration xmlFieldValue = parentidList.elements();
508
            while( xmlFieldValue.hasMoreElements() )
509
            {
510
              ReturnFieldValue object = (ReturnFieldValue)
511
                                         xmlFieldValue.nextElement();
512
              docid = object.getDocid();
513
              if (docListResult.containsKey(docid))
514
              {
515
                  String removedelement = (String)docListResult.remove(docid);
516
                  docListResult.put(docid, removedelement +
517
                                    object.getXMLFieldValue());
518
              }
519
              else
520
              {
521
                  docListResult.put(docid, object.getXMLFieldValue()); 
522
              }
523
            }//while
524
            double docListResultEnd = System.currentTimeMillis()/1000;
525
            MetaCatUtil.debugMessage("Time for prepare doclistresult after"+
526
                                      " execute extended query: "
527
                                    +(docListResultEnd-extendedQueryEnd), 30);
528
            
529
            
530
            // get attribures return
531
            docListResult = getAttributeValueForReturn
532
                                      (qspec,docListResult, doclist.toString());
533
          }//if doclist lenght is great than zero
534
          
535
        }//if has extended query
536
        
537
        
538
        //this loop adds the relation data to the resultdoc
539
        //this code might be able to be added to the backtracking code above
540
        double startRelation = System.currentTimeMillis()/1000;
541
        Enumeration docidkeys = docListResult.keys();
542
        while(docidkeys.hasMoreElements())
543
        {
544
          //String connstring = "metacat://"+util.getOption("server")+"?docid=";
545
          String connstring = "%docid=";
546
          String docidkey = (String)docidkeys.nextElement();
547
          pstmt = dbconn.prepareStatement(qspec.printRelationSQL(docidkey));
548
          pstmt.execute();
549
          rs = pstmt.getResultSet();
550
          tableHasRows = rs.next();
551
          while(tableHasRows)
552
          {
553
            String sub = rs.getString(1);
554
            String rel = rs.getString(2);
555
            String obj = rs.getString(3);
556
            String subDT = rs.getString(4);
557
            String objDT = rs.getString(5);
558
            
559
            document = new StringBuffer();
560
            document.append("<triple>");
561
            document.append("<subject>").append(MetaCatUtil.normalize(sub));
562
            document.append("</subject>");
563
            if ( subDT != null ) {
564
              document.append("<subjectdoctype>").append(subDT);
565
              document.append("</subjectdoctype>");
566
            }
567
            document.append("<relationship>").
568
                                          append(MetaCatUtil.normalize(rel));
569
            document.append("</relationship>");
570
            document.append("<object>").append(MetaCatUtil.normalize(obj));
571
            document.append("</object>");
572
            if ( objDT != null ) {
573
              document.append("<objectdoctype>").append(objDT);
574
              document.append("</objectdoctype>");
575
            }
576
            document.append("</triple>");
577
            
578
            String removedelement = (String)docListResult.remove(docidkey);
579
            docListResult.put(docidkey, removedelement + 
580
                              document.toString());
581
            tableHasRows = rs.next();
582
          }
583
          rs.close();
584
          pstmt.close();
585
        }
586
        double endRelation = System.currentTimeMillis()/1000;
587
        MetaCatUtil.debugMessage("Time for adding relation to docListResult: "+
588
                                (endRelation-startRelation), 30);
589
        
590
      } catch (SQLException e) {
591
        System.err.println("SQL Error in DBQuery.findDocuments: " + 
592
                           e.getMessage());
593
      } catch (IOException ioe) {
594
        System.err.println("IO error in DBQuery.findDocuments:");
595
        System.err.println(ioe.getMessage());
596
      } catch (Exception ee) {
597
        System.err.println("Exception in DBQuery.findDocuments: " + 
598
                           ee.getMessage());
599
        ee.printStackTrace(System.err);
600
      }
601
      finally 
602
      {
603
        try
604
        {
605
          pstmt.close();
606
        }//try
607
        catch (SQLException sqlE)
608
        {
609
          MetaCatUtil.debugMessage("Error in DBQuery.findDocuments: "
610
                                      +sqlE.getMessage(), 30);
611
        }//catch
612
        finally
613
        {
614
          DBConnectionPool.returnDBConnection(dbconn, serialNumber);
615
        }//finally
616
      }//finally
617
    //System.out.println("docListResult: ");
618
    //System.out.println(docListResult.toString());
619
    return docListResult;
620
  }
621
  
622
  /*
623
   * A method to return search result after running a query which return
624
   * field have attribue
625
   */
626
  private Hashtable getAttributeValueForReturn(QuerySpecification squery,
627
                                               Hashtable docInformationList,
628
                                               String docList)
629
  {
630
    StringBuffer XML = null;
631
    String sql = null;
632
    DBConnection dbconn = null;
633
    PreparedStatement pstmt = null;
634
    ResultSet rs = null;
635
    int serialNumber = -1;
636
    boolean tableHasRows =false;
637
    
638
    //check the parameter
639
    if (squery == null || docList==null || docList.length() <0)
640
    {
641
      return docInformationList;
642
    }
643
    
644
    // if has attribute as return field
645
    if (squery.containAttributeReturnField())
646
    {
647
      sql = squery.printAttributeQuery(docList);
648
      try 
649
      {
650
        dbconn=DBConnectionPool.getDBConnection("DBQuery.getAttributeValue");
651
        serialNumber=dbconn.getCheckOutSerialNumber();
652
        pstmt = dbconn.prepareStatement(sql);
653
        pstmt.execute();
654
        rs = pstmt.getResultSet();
655
        tableHasRows = rs.next();
656
        while(tableHasRows) 
657
        {
658
          String docid = rs.getString(1).trim();
659
          String fieldname = rs.getString(2);
660
          String fielddata = rs.getString(3);
661
          String attirbuteName = rs.getString(4);
662
          XML = new StringBuffer();
663
  
664
          XML.append("<param name=\"");
665
          XML.append(fieldname);
666
          XML.append(QuerySpecification.ATTRIBUTESYMBOL);
667
          XML.append(attirbuteName);
668
          XML.append("\">");
669
          XML.append(fielddata);
670
          XML.append("</param>");
671
          tableHasRows = rs.next();
672
          
673
          if (docInformationList.containsKey(docid))
674
          {
675
            String removedelement = (String)docInformationList.remove(docid);
676
            docInformationList.put(docid, removedelement + XML.toString());
677
          }
678
          else
679
          {
680
            docInformationList.put(docid, XML.toString()); 
681
          }
682
        }//while
683
        rs.close();
684
        pstmt.close();
685
      }
686
      catch(Exception se)
687
      {
688
        MetaCatUtil.debugMessage("Error in DBQuery.getAttributeValue1: "
689
                                      +se.getMessage(), 30);
690
      }
691
      finally
692
      {
693
        try
694
        {
695
          pstmt.close();
696
        }//try
697
        catch (SQLException sqlE)
698
        {
699
          MetaCatUtil.debugMessage("Error in DBQuery.getAttributeValue2: "
700
                                      +sqlE.getMessage(), 30);
701
        }//catch
702
        finally
703
        {
704
          DBConnectionPool.returnDBConnection(dbconn, serialNumber);
705
        }//finally
706
      }//finally
707
    }//if
708
    return docInformationList;
709
      
710
  }
711
   
712
  
713
  /*
714
   * A method to create a query to get owner's docid list
715
   */
716
  private String getOwnerQuery(String owner)
717
  {
718
    StringBuffer self = new StringBuffer();
719

    
720
    self.append("SELECT docid,docname,doctype,");
721
    self.append("date_created, date_updated, rev ");
722
    self.append("FROM xml_documents WHERE docid IN (");
723
    self.append("(");
724
    self.append("SELECT DISTINCT docid FROM xml_nodes WHERE \n");
725
    self.append("nodedata LIKE '%%%' ");
726
    self.append(") \n");
727
    self.append(") ");
728
    self.append(" AND (");
729
    self.append(" user_owner = '" + owner + "'");
730
    self.append(") ");
731
    return self.toString();
732
  }
733
  /**
734
   * returns a string array of the contents of a particular node. 
735
   * If the node appears more than once, the contents are returned 
736
   * in the order in which they appearred in the document.
737
   * @param nodename the name or path of the particular node.
738
   * @param docid the docid of the document you want the node from.
739
   */
740
  public static Object[] getNodeContent(String nodename, String docid)
741
  {
742
    DBConnection dbconn = null;
743
    int serialNumber = -1;
744
    StringBuffer query = new StringBuffer();
745
    Vector result = new Vector();
746
    PreparedStatement pstmt = null;
747
    query.append("select nodedata from xml_nodes where parentnodeid in ");
748
    query.append("(select nodeid from xml_index where path like '");
749
    query.append(nodename);
750
    query.append("' and docid like '").append(docid).append("')");
751
    try
752
    {
753
      dbconn=DBConnectionPool.getDBConnection("DBQuery.getNodeContent");
754
        serialNumber=dbconn.getCheckOutSerialNumber();
755
      pstmt = dbconn.prepareStatement(query.toString());
756

    
757
      // Execute the SQL query using the JDBC connection
758
      pstmt.execute();
759
      ResultSet rs = pstmt.getResultSet();
760
      boolean tableHasRows = rs.next();
761
      while (tableHasRows) 
762
      {
763
        result.add(rs.getString(1));
764
        //System.out.println(rs.getString(1));
765
        tableHasRows = rs.next();
766
      }
767
    } 
768
    catch (SQLException e) 
769
    {
770
      System.err.println("Error in DBQuery.getNodeContent: " + e.getMessage());
771
    } finally {
772
      try
773
      {
774
        pstmt.close();
775
      }
776
      catch(SQLException sqle) 
777
      {}
778
      finally
779
      {
780
        DBConnectionPool.returnDBConnection(dbconn, serialNumber);
781
      }
782
      
783
    }
784
    return result.toArray();
785
  }
786
  
787
  /**
788
   * format a structured query as an XML document that conforms
789
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
790
   * structured query engine
791
   *
792
   * @param params The list of parameters that should be included in the query
793
   */
794
  public static String createSQuery(Hashtable params)
795
  { 
796
    StringBuffer query = new StringBuffer();
797
    Enumeration elements;
798
    Enumeration keys;
799
    String filterDoctype = null;
800
    String casesensitive = null;
801
    String searchmode = null;
802
    Object nextkey;
803
    Object nextelement;
804
    //add the xml headers
805
    query.append("<?xml version=\"1.0\"?>\n");
806
    query.append("<pathquery version=\"1.0\">\n");
807

    
808
    if (params.containsKey("meta_file_id"))
809
    {
810
      query.append("<meta_file_id>");
811
      query.append( ((String[])params.get("meta_file_id"))[0]);
812
      query.append("</meta_file_id>");
813
    }
814
    
815
    if (params.containsKey("returndoctype"))
816
    {
817
      String[] returnDoctypes = ((String[])params.get("returndoctype"));
818
      for(int i=0; i<returnDoctypes.length; i++)
819
      {
820
        String doctype = (String)returnDoctypes[i];
821

    
822
        if (!doctype.equals("any") && 
823
            !doctype.equals("ANY") &&
824
            !doctype.equals("") ) 
825
        {
826
          query.append("<returndoctype>").append(doctype);
827
          query.append("</returndoctype>");
828
        }
829
      }
830
    }
831
    
832
    if (params.containsKey("filterdoctype"))
833
    {
834
      String[] filterDoctypes = ((String[])params.get("filterdoctype"));
835
      for(int i=0; i<filterDoctypes.length; i++)
836
      {
837
        query.append("<filterdoctype>").append(filterDoctypes[i]);
838
        query.append("</filterdoctype>");
839
      }
840
    }
841
    
842
    if (params.containsKey("returnfield"))
843
    {
844
      String[] returnfield = ((String[])params.get("returnfield"));
845
      for(int i=0; i<returnfield.length; i++)
846
      {
847
        query.append("<returnfield>").append(returnfield[i]);
848
        query.append("</returnfield>");
849
      }
850
    }
851
    
852
    if (params.containsKey("owner"))
853
    {
854
      String[] owner = ((String[])params.get("owner"));
855
      for(int i=0; i<owner.length; i++)
856
      {
857
        query.append("<owner>").append(owner[i]);
858
        query.append("</owner>");
859
      }
860
    }
861
    
862
    if (params.containsKey("site"))
863
    {
864
      String[] site = ((String[])params.get("site"));
865
      for(int i=0; i<site.length; i++)
866
      {
867
        query.append("<site>").append(site[i]);
868
        query.append("</site>");
869
      }
870
    }
871
    
872
    //allows the dynamic switching of boolean operators
873
    if (params.containsKey("operator"))
874
    {
875
      query.append("<querygroup operator=\"" + 
876
                ((String[])params.get("operator"))[0] + "\">");
877
    }
878
    else
879
    { //the default operator is UNION
880
      query.append("<querygroup operator=\"UNION\">"); 
881
    }
882
        
883
    if (params.containsKey("casesensitive"))
884
    {
885
      casesensitive = ((String[])params.get("casesensitive"))[0]; 
886
    }
887
    else
888
    {
889
      casesensitive = "false"; 
890
    }
891
    
892
    if (params.containsKey("searchmode"))
893
    {
894
      searchmode = ((String[])params.get("searchmode"))[0]; 
895
    }
896
    else
897
    {
898
      searchmode = "contains"; 
899
    }
900
        
901
    //anyfield is a special case because it does a 
902
    //free text search.  It does not have a <pathexpr>
903
    //tag.  This allows for a free text search within the structured
904
    //query.  This is useful if the INTERSECT operator is used.
905
    if (params.containsKey("anyfield"))
906
    {
907
       String[] anyfield = ((String[])params.get("anyfield"));
908
       //allow for more than one value for anyfield
909
       for(int i=0; i<anyfield.length; i++)
910
       {
911
         if (!anyfield[i].equals(""))
912
         {
913
           query.append("<queryterm casesensitive=\"" + casesensitive + 
914
                        "\" " + "searchmode=\"" + searchmode + "\"><value>" +
915
                        anyfield[i] +
916
                        "</value></queryterm>"); 
917
         }
918
       }
919
    }
920
        
921
    //this while loop finds the rest of the parameters
922
    //and attempts to query for the field specified
923
    //by the parameter.
924
    elements = params.elements();
925
    keys = params.keys();
926
    while(keys.hasMoreElements() && elements.hasMoreElements())
927
    {
928
      nextkey = keys.nextElement();
929
      nextelement = elements.nextElement();
930

    
931
      //make sure we aren't querying for any of these
932
      //parameters since the are already in the query
933
      //in one form or another.
934
      if (!nextkey.toString().equals("returndoctype") && 
935
         !nextkey.toString().equals("filterdoctype")  &&
936
         !nextkey.toString().equals("action")  &&
937
         !nextkey.toString().equals("qformat") && 
938
         !nextkey.toString().equals("anyfield") &&
939
         !nextkey.toString().equals("returnfield") &&
940
         !nextkey.toString().equals("owner") &&
941
         !nextkey.toString().equals("site") &&
942
         !nextkey.toString().equals("operator") )
943
      {
944
        //allow for more than value per field name
945
        for(int i=0; i<((String[])nextelement).length; i++)
946
        {
947
          if (!((String[])nextelement)[i].equals(""))
948
          {
949
            query.append("<queryterm casesensitive=\"" + casesensitive +"\" " + 
950
                         "searchmode=\"" + searchmode + "\">" +
951
                         "<value>" +
952
                         //add the query value
953
                         ((String[])nextelement)[i] +
954
                         "</value><pathexpr>" +
955
                         //add the path to query by 
956
                         nextkey.toString() + 
957
                         "</pathexpr></queryterm>");
958
          }
959
        }
960
      }
961
    }
962
    query.append("</querygroup></pathquery>");
963
    //append on the end of the xml and return the result as a string
964
    return query.toString();
965
  }
966
  
967
  /**
968
   * format a simple free-text value query as an XML document that conforms
969
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
970
   * structured query engine
971
   *
972
   * @param value the text string to search for in the xml catalog
973
   * @param doctype the type of documents to include in the result set -- use
974
   *        "any" or "ANY" for unfiltered result sets
975
   */
976
   public static String createQuery(String value, String doctype) {
977
     StringBuffer xmlquery = new StringBuffer();
978
     xmlquery.append("<?xml version=\"1.0\"?>\n");
979
     xmlquery.append("<pathquery version=\"1.0\">");
980

    
981
     if (!doctype.equals("any") && !doctype.equals("ANY")) {
982
       xmlquery.append("<returndoctype>");
983
       xmlquery.append(doctype).append("</returndoctype>");
984
     }
985

    
986
     xmlquery.append("<querygroup operator=\"UNION\">");
987
     //chad added - 8/14
988
     //the if statement allows a query to gracefully handle a null 
989
     //query.  Without this if a nullpointerException is thrown.
990
     if (!value.equals(""))
991
     {
992
       xmlquery.append("<queryterm casesensitive=\"false\" ");
993
       xmlquery.append("searchmode=\"contains\">");
994
       xmlquery.append("<value>").append(value).append("</value>");
995
       xmlquery.append("</queryterm>");
996
     }
997
     xmlquery.append("</querygroup>");
998
     xmlquery.append("</pathquery>");
999

    
1000
     
1001
     return (xmlquery.toString());
1002
   }
1003

    
1004
  /**
1005
   * format a simple free-text value query as an XML document that conforms
1006
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
1007
   * structured query engine
1008
   *
1009
   * @param value the text string to search for in the xml catalog
1010
   */
1011
   public static String createQuery(String value) {
1012
     return createQuery(value, "any");
1013
   }
1014
   
1015
  /** 
1016
    * Check for "READ" permission on @docid for @user and/or @group 
1017
    * from DB connection 
1018
    */
1019
  private boolean hasPermission (String user,
1020
                                  String[] groups, String docid ) 
1021
                  throws SQLException, Exception
1022
  {
1023
    // Check for READ permission on @docid for @user and/or @groups
1024
   PermissionController controller = new PermissionController(docid);
1025
   return controller.hasPermission(user,groups,
1026
                                 AccessControlInterface.READSTRING);
1027
  }
1028

    
1029
  /**
1030
    * Get all docIds list for a data packadge
1031
    * @param dataPackageDocid, the string in docId field of xml_relation table
1032
    */
1033
  private Vector getCurrentDocidListForDataPackage(String dataPackageDocid)
1034
  {
1035
    DBConnection dbConn = null;
1036
    int serialNumber = -1;
1037
    Vector docIdList=new Vector();//return value
1038
    PreparedStatement pStmt = null;
1039
    ResultSet rs=null;
1040
    String docIdInSubjectField=null;
1041
    String docIdInObjectField=null;
1042
    
1043
    // Check the parameter
1044
    if (dataPackageDocid == null || dataPackageDocid.equals(""))
1045
    {
1046
      return docIdList;
1047
    }//if
1048
    
1049
    //the query stirng
1050
    String query="SELECT subject, object from xml_relation where docId = ?";
1051
    try
1052
    {
1053
      dbConn=DBConnectionPool.
1054
                  getDBConnection("DBQuery.getCurrentDocidListForDataPackage");
1055
      serialNumber=dbConn.getCheckOutSerialNumber();
1056
      pStmt=dbConn.prepareStatement(query);
1057
      //bind the value to query
1058
      pStmt.setString(1, dataPackageDocid);
1059

    
1060
      //excute the query
1061
      pStmt.execute();
1062
      //get the result set
1063
      rs=pStmt.getResultSet();
1064
      //process the result
1065
      while (rs.next())
1066
      {
1067
        //In order to get the whole docIds in a data packadge,
1068
        //we need to put the docIds of subject and object field in xml_relation
1069
        //into the return vector
1070
        docIdInSubjectField=rs.getString(1);//the result docId in subject field
1071
        docIdInObjectField=rs.getString(2);//the result docId in object field
1072

    
1073
        //don't put the duplicate docId into the vector
1074
        if (!docIdList.contains(docIdInSubjectField))
1075
        {
1076
          docIdList.add(docIdInSubjectField);
1077
        }
1078

    
1079
        //don't put the duplicate docId into the vector
1080
        if (!docIdList.contains(docIdInObjectField))
1081
        {
1082
          docIdList.add(docIdInObjectField);
1083
        }
1084
      }//while
1085
      //close the pStmt
1086
      pStmt.close();
1087
    }//try
1088
    catch (SQLException e)
1089
    {
1090
      MetaCatUtil.debugMessage("Error in getDocidListForDataPackage: "
1091
                            +e.getMessage(), 30);
1092
    }//catch
1093
    finally
1094
    {
1095
      try
1096
      {
1097
        pStmt.close();
1098
      }//try
1099
      catch (SQLException ee)
1100
      {
1101
        MetaCatUtil.debugMessage("Error in getDocidListForDataPackage: "
1102
                            +ee.getMessage(), 30);
1103
      }//catch     
1104
      finally
1105
      {
1106
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1107
      }//fianlly
1108
    }//finally
1109
    return docIdList;
1110
  }//getCurrentDocidListForDataPackadge()
1111
  
1112
  /**
1113
   * Get all docIds list for a data packadge
1114
   * @param dataPackageDocid, the string in docId field of xml_relation table
1115
   */
1116
  private Vector getOldVersionDocidListForDataPackage(String dataPackageDocid)
1117
  {
1118
   
1119
    Vector docIdList=new Vector();//return value
1120
    Vector tripleList=null;
1121
    String xml=null;
1122
    
1123
     // Check the parameter
1124
    if (dataPackageDocid == null || dataPackageDocid.equals(""))
1125
    {
1126
      return docIdList;
1127
    }//if
1128
    
1129
    try
1130
    {
1131
      //initial a documentImpl object 
1132
      DocumentImpl packageDocument = 
1133
                  new DocumentImpl(dataPackageDocid);
1134
      //transfer to documentImpl object to string
1135
      xml=packageDocument.toString();
1136
    
1137
      //create a tripcollection object
1138
      TripleCollection tripleForPackage = new 
1139
                                     TripleCollection(new StringReader(xml));
1140
      //get the vetor of triples 
1141
      tripleList=tripleForPackage.getCollection();
1142
    
1143
      for (int i= 0; i<tripleList.size(); i++)
1144
      {
1145
        //put subject docid  into docIdlist without duplicate
1146
        if (!docIdList.contains(((Triple)tripleList.elementAt(i)).getSubject()))
1147
        {
1148
          //put subject docid  into docIdlist
1149
          docIdList.add(((Triple)tripleList.get(i)).getSubject());
1150
        }
1151
        //put object docid into docIdlist without duplicate
1152
        if (!docIdList.contains(((Triple)tripleList.elementAt(i)).getObject()))
1153
        {
1154
          docIdList.add(((Triple)(tripleList.get(i))).getObject());
1155
        }
1156
      }//for
1157
    }//try
1158
    catch (Exception e)
1159
    {
1160
      MetaCatUtil.debugMessage("Error in getOldVersionAllDocumentImpl: "
1161
                            +e.getMessage(), 30);
1162
    }//catch
1163
  
1164
    // return result
1165
    return docIdList;
1166
  }//getDocidListForPackageInXMLRevisions()  
1167
  
1168
  /**
1169
   * Check if the docId is a data packadge id. If the id is a data packadage 
1170
   *id, it should be store in the docId fields in xml_relation table.
1171
   *So we can use a query to get the entries which the docId equals the given 
1172
   *value. If the result is null. The docId is not a packadge id. Otherwise,
1173
   * it is.
1174
   * @param docId, the id need to be checked
1175
   */
1176
  private boolean isDataPackageId(String docId)
1177
  {
1178
    boolean result=false;
1179
    PreparedStatement pStmt = null;
1180
    ResultSet rs=null;
1181
    String query="SELECT docId from xml_relation where docId = ?";
1182
    DBConnection dbConn = null;
1183
    int serialNumber = -1;
1184
    try
1185
    {
1186
      dbConn=DBConnectionPool.
1187
                  getDBConnection("DBQuery.isDataPackageId");
1188
      serialNumber=dbConn.getCheckOutSerialNumber();
1189
      pStmt=dbConn.prepareStatement(query);
1190
      //bind the value to query
1191
      pStmt.setString(1, docId);
1192
      //execute the query
1193
      pStmt.execute();
1194
      rs=pStmt.getResultSet();
1195
      //process the result
1196
      if (rs.next()) //There are some records for the id in docId fields
1197
      {
1198
        result=true;//It is a data packadge id
1199
      }
1200
      pStmt.close();
1201
    }//try
1202
    catch (SQLException e)
1203
    {
1204
      util.debugMessage("Error in isDataPackageId: "
1205
                            +e.getMessage(), 30);
1206
    }
1207
    finally
1208
    {
1209
      try
1210
      {
1211
        pStmt.close();
1212
      }//try
1213
      catch (SQLException ee)
1214
      {
1215
        MetaCatUtil.debugMessage("Error in isDataPackageId: "
1216
                                                        + ee.getMessage(), 30);
1217
      }//catch
1218
      finally
1219
      {
1220
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1221
      }//finally
1222
    }//finally
1223
    return result;
1224
  }//isDataPackageId()
1225
  
1226
  /**
1227
   * Check if the user has the permission to export data package
1228
   * @param conn, the connection
1229
   * @param docId, the id need to be checked
1230
   * @param user, the name of user
1231
   * @param groups, the user's group
1232
   */ 
1233
   private boolean hasPermissionToExportPackage(String docId, 
1234
                                        String user, String[] groups)
1235
                   throws Exception
1236
   {
1237
     //DocumentImpl doc=new DocumentImpl(conn,docId);
1238
     return DocumentImpl.hasReadPermission(user, groups,docId);
1239
   }
1240
   
1241
  /**
1242
   *Get the current Rev for a docid in xml_documents table
1243
   * @param docId, the id need to get version numb
1244
   * If the return value is -5, means no value in rev field for this docid
1245
   */
1246
  private int getCurrentRevFromXMLDoumentsTable(String docId)
1247
                                                throws SQLException
1248
  {
1249
    int rev=-5;
1250
    PreparedStatement pStmt = null;
1251
    ResultSet rs=null;
1252
    String query="SELECT rev from xml_documents where docId = ?";
1253
    DBConnection dbConn=null;
1254
    int serialNumber = -1;
1255
    try
1256
    {
1257
      dbConn=DBConnectionPool.
1258
                  getDBConnection("DBQuery.getCurrentRevFromXMLDocumentsTable");
1259
      serialNumber=dbConn.getCheckOutSerialNumber();
1260
      pStmt=dbConn.prepareStatement(query);
1261
      //bind the value to query
1262
      pStmt.setString(1, docId);
1263
      //execute the query
1264
      pStmt.execute();
1265
      rs=pStmt.getResultSet();
1266
      //process the result
1267
      if (rs.next()) //There are some records for rev
1268
      {
1269
        rev=rs.getInt(1);;//It is the version for given docid
1270
      }
1271
      else
1272
      {
1273
        rev=-5;
1274
      }
1275
     
1276
    }//try
1277
    catch (SQLException e)
1278
    {
1279
      MetaCatUtil.debugMessage("Error in getCurrentRevFromXMLDoumentsTable: "
1280
                            +e.getMessage(), 30);
1281
      throw e;
1282
    }//catch
1283
    finally
1284
    {
1285
      try
1286
      {
1287
        pStmt.close();
1288
      }//try
1289
      catch (SQLException ee)
1290
      {
1291
        MetaCatUtil.debugMessage("Error in getCurrentRevFromXMLDoumentsTable: "
1292
                                  +ee.getMessage(), 30);
1293
      }//catch
1294
      finally
1295
      {
1296
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1297
      }//finally
1298
    }//finally
1299
    return rev;
1300
  }//getCurrentRevFromXMLDoumentsTable
1301
 
1302
 /**
1303
   *put a doc into a zip output stream
1304
   *@param docImpl, docmentImpl object which will be sent to zip output stream
1305
   *@param zipOut, zip output stream which the docImpl will be put
1306
   *@param packageZipEntry, the zip entry name for whole package
1307
   */
1308
  private void addDocToZipOutputStream(DocumentImpl docImpl, 
1309
                                ZipOutputStream zipOut, String packageZipEntry)
1310
               throws ClassNotFoundException, IOException, SQLException, 
1311
                      McdbException, Exception
1312
  {
1313
    byte[] byteString = null;
1314
    ZipEntry zEntry = null;
1315

    
1316
    byteString = docImpl.toString().getBytes();
1317
    //use docId as the zip entry's name
1318
    zEntry = new ZipEntry(packageZipEntry+"/metadata/"+docImpl.getDocID());
1319
    zEntry.setSize(byteString.length);
1320
    zipOut.putNextEntry(zEntry);
1321
    zipOut.write(byteString, 0, byteString.length);
1322
    zipOut.closeEntry();
1323
  
1324
  }//addDocToZipOutputStream()
1325

    
1326
  
1327
  /**
1328
   * Transfer a docid vetor to a documentImpl vector. The documentImpl vetor 
1329
   * only inlcudes current version. If a DocumentImple object
1330
   * couldn't find for a docid, then the String of this docid was added to vetor
1331
   * rather than DocumentImple object.
1332
   * @param docIdList, a vetor hold a docid list for a data package. In docid,
1333
   * there is not version number in it.
1334
   */  
1335
  
1336
  private Vector getCurrentAllDocumentImpl( Vector docIdList)
1337
                              throws McdbException,Exception
1338
  {
1339
    //Connection dbConn=null;
1340
    Vector documentImplList=new Vector();
1341
    int rev=0; 
1342
    
1343
    // Check the parameter
1344
    if (docIdList.isEmpty())
1345
    {
1346
      return documentImplList;
1347
    }//if
1348
  
1349
    //for every docid in vector
1350
    for (int i=0;i<docIdList.size();i++)
1351
    {
1352
      try
1353
      {
1354
        //get newest version for this docId
1355
        rev=getCurrentRevFromXMLDoumentsTable((String)docIdList.elementAt(i));
1356
      
1357
        // There is no record for this docId in xml_documents table
1358
        if (rev ==-5)
1359
        {
1360
          // Rather than put DocumentImple object, put a String Object(docid)
1361
          // into the documentImplList
1362
          documentImplList.add((String)docIdList.elementAt(i));
1363
          // Skip other code
1364
          continue;
1365
        }
1366
     
1367
        String docidPlusVersion=((String)docIdList.elementAt(i))
1368
                        +util.getOption("accNumSeparator")+rev;
1369
      
1370
      
1371
        //create new documentImpl object
1372
        DocumentImpl documentImplObject = 
1373
                                    new DocumentImpl(docidPlusVersion);
1374
       //add them to vector                            
1375
        documentImplList.add(documentImplObject);
1376
      }//try
1377
      catch (Exception e)
1378
      {
1379
        MetaCatUtil.debugMessage("Error in getCurrentAllDocumentImpl: "
1380
                            +e.getMessage(), 30);
1381
        // continue the for loop
1382
        continue;
1383
      }
1384
    }//for
1385
    return documentImplList;
1386
  }
1387
  
1388
  /**
1389
   * Transfer a docid vetor to a documentImpl vector. If a DocumentImple object
1390
   * couldn't find for a docid, then the String of this docid was added to vetor
1391
   * rather than DocumentImple object.
1392
   * @param docIdList, a vetor hold a docid list for a data package. In docid,
1393
   *t here is version number in it.
1394
   */    
1395
  private Vector getOldVersionAllDocumentImpl( Vector docIdList)
1396
  {
1397
    //Connection dbConn=null;
1398
    Vector documentImplList=new Vector();
1399
    String siteCode=null;
1400
    String uniqueId=null;
1401
    int rev=0; 
1402
    
1403
    // Check the parameter
1404
    if (docIdList.isEmpty())
1405
    {
1406
      return documentImplList;
1407
    }//if
1408
    
1409
    //for every docid in vector
1410
    for (int i=0;i<docIdList.size();i++)
1411
    {
1412
      
1413
        String docidPlusVersion=(String)(docIdList.elementAt(i));
1414
        
1415
        try
1416
        {
1417
          //create new documentImpl object
1418
          DocumentImpl documentImplObject = 
1419
                                    new DocumentImpl(docidPlusVersion);
1420
          //add them to vector                            
1421
          documentImplList.add(documentImplObject);
1422
        }//try
1423
        catch (McdbDocNotFoundException notFoundE)
1424
        {
1425
          MetaCatUtil.debugMessage("Error in DBQuery.getOldVersionAllDocument"+
1426
                                  "Imple" + notFoundE.getMessage(), 30);
1427
          // Rather than add a DocumentImple object into vetor, a String object
1428
          // - the doicd was added to the vector
1429
          documentImplList.add(docidPlusVersion);
1430
          // Continue the for loop
1431
          continue;
1432
        }//catch
1433
        catch (Exception e)
1434
        {
1435
          MetaCatUtil.debugMessage("Error in DBQuery.getOldVersionAllDocument"+
1436
                                  "Imple" + e.getMessage(), 30);
1437
          // Continue the for loop
1438
          continue;
1439
        }//catch
1440
          
1441
      
1442
    }//for
1443
    return documentImplList;
1444
  }//getOldVersionAllDocumentImple
1445
  
1446
  /**
1447
   *put a data file into a zip output stream
1448
   *@param docImpl, docmentImpl object which will be sent to zip output stream
1449
   *@param zipOut, the zip output stream which the docImpl will be put
1450
   *@param packageZipEntry, the zip entry name for whole package
1451
   */
1452
  private void addDataFileToZipOutputStream(DocumentImpl docImpl,
1453
                                ZipOutputStream zipOut, String packageZipEntry)
1454
               throws ClassNotFoundException, IOException, SQLException,
1455
                      McdbException, Exception
1456
  {
1457
    byte[] byteString = null;
1458
    ZipEntry zEntry = null;
1459
    // this is data file; add file to zip
1460
    String filePath = util.getOption("datafilepath");
1461
    if (!filePath.endsWith("/")) 
1462
    {
1463
      filePath += "/";
1464
    }
1465
    String fileName = filePath + docImpl.getDocID();
1466
    zEntry = new ZipEntry(packageZipEntry+"/data/"+docImpl.getDocID());
1467
    zipOut.putNextEntry(zEntry);
1468
    FileInputStream fin = null;
1469
    try
1470
    {
1471
      fin = new FileInputStream(fileName);
1472
      byte[] buf = new byte[4 * 1024]; // 4K buffer
1473
      int b = fin.read(buf);
1474
      while (b != -1)
1475
      {
1476
        zipOut.write(buf, 0, b);
1477
        b = fin.read(buf);
1478
      }//while
1479
      zipOut.closeEntry();
1480
    }//try
1481
    catch (IOException ioe)
1482
    {
1483
      util.debugMessage("There is an exception: "+ioe.getMessage(), 30);
1484
    }//catch
1485
  }//addDataFileToZipOutputStream()
1486

    
1487
  /**
1488
   *create a html summary for data package and put it into zip output stream
1489
   *@param docImplList, the documentImpl ojbects in data package
1490
   *@param zipOut, the zip output stream which the html should be put
1491
   *@param packageZipEntry, the zip entry name for whole package
1492
   */
1493
   private void addHtmlSummaryToZipOutputStream(Vector docImplList,
1494
                                ZipOutputStream zipOut, String packageZipEntry)
1495
                                           throws Exception
1496
  {
1497
    StringBuffer htmlDoc = new StringBuffer();
1498
    ZipEntry zEntry = null;
1499
    byte[] byteString=null;
1500
    InputStream source;
1501
    DBTransform xmlToHtml;
1502
  
1503
    //create a DBTransform ojbect
1504
    xmlToHtml = new DBTransform();
1505
    //head of html
1506
    htmlDoc.append("<html><head></head><body>");
1507
    for (int i=0; i<docImplList.size(); i++)
1508
    {
1509
      // If this String object, this means it is missed data file
1510
      if ((((docImplList.elementAt(i)).getClass()).toString())
1511
                                             .equals("class java.lang.String"))
1512
      {
1513
        
1514
        htmlDoc.append("<a href=\"");
1515
        String dataFileid =(String)docImplList.elementAt(i);
1516
        htmlDoc.append("./data/").append(dataFileid).append("\">");
1517
        htmlDoc.append("Data File: ");
1518
        htmlDoc.append(dataFileid).append("</a><br>");
1519
        htmlDoc.append("<br><hr><br>");
1520
        
1521
      }//if
1522
      else if ((((DocumentImpl)docImplList.elementAt(i)).getDoctype()).
1523
                                                         compareTo("BIN")!=0)
1524
      { //this is an xml file so we can transform it.
1525
        //transform each file individually then concatenate all of the
1526
        //transformations together.
1527

    
1528
        //for metadata xml title
1529
        htmlDoc.append("<h2>");
1530
        htmlDoc.append(((DocumentImpl)docImplList.elementAt(i)).getDocID());
1531
        //htmlDoc.append(".");
1532
        //htmlDoc.append(((DocumentImpl)docImplList.elementAt(i)).getRev());
1533
        htmlDoc.append("</h2>");
1534
        //do the actual transform
1535
        StringWriter docString = new StringWriter();
1536
        xmlToHtml.transformXMLDocument(
1537
                        ((DocumentImpl)docImplList.elementAt(i)).toString(),
1538
           "-//NCEAS//eml-generic//EN", "-//W3C//HTML//EN", "html", docString);
1539
        htmlDoc.append(docString.toString());
1540
        htmlDoc.append("<br><br><hr><br><br>");
1541
      }//if
1542
      else
1543
      { //this is a data file so we should link to it in the html
1544
        htmlDoc.append("<a href=\"");
1545
        String dataFileid =((DocumentImpl)docImplList.elementAt(i)).getDocID();
1546
        htmlDoc.append("./data/").append(dataFileid).append("\">");
1547
        htmlDoc.append("Data File: ");
1548
        htmlDoc.append(dataFileid).append("</a><br>");
1549
        htmlDoc.append("<br><hr><br>");
1550
      }//else
1551
    }//for
1552
    htmlDoc.append("</body></html>");
1553
    byteString = htmlDoc.toString().getBytes();
1554
    zEntry = new ZipEntry(packageZipEntry+"/metadata.html");
1555
    zEntry.setSize(byteString.length);
1556
    zipOut.putNextEntry(zEntry);
1557
    zipOut.write(byteString, 0, byteString.length);
1558
    zipOut.closeEntry();
1559
    //dbConn.close();
1560
        
1561
  }//addHtmlSummaryToZipOutputStream
1562
  
1563
  
1564
  
1565
  /**
1566
   * put a data packadge into a zip output stream
1567
   * @param docId, which the user want to put into zip output stream
1568
   * @param out, a servletoutput stream which the zip output stream will be put 
1569
   * @param user, the username of the user
1570
   * @param groups, the group of the user
1571
   */
1572
  public ZipOutputStream getZippedPackage(String docIdString, 
1573
        ServletOutputStream out, String user, String[] groups, String passWord)
1574
                    throws ClassNotFoundException, IOException, SQLException, 
1575
                      McdbException, NumberFormatException, Exception
1576
  { 
1577
    ZipOutputStream zOut = null;
1578
    String elementDocid=null;
1579
    DocumentImpl docImpls=null;
1580
    //Connection dbConn = null;
1581
    Vector docIdList=new Vector();
1582
    Vector documentImplList=new Vector();
1583
    Vector htmlDocumentImplList=new Vector();
1584
    String packageId=null;
1585
    String rootName="package";//the package zip entry name
1586
    
1587
    String docId=null;
1588
    int version=-5;
1589
    // Docid without revision
1590
    docId=MetaCatUtil.getDocIdFromString(docIdString);
1591
    // revision number
1592
    version=MetaCatUtil.getVersionFromString(docIdString);
1593
 
1594
    //check if the reqused docId is a data package id
1595
    if (!isDataPackageId(docId))
1596
    {
1597
      
1598
      /*Exception e = new Exception("The request the doc id " +docIdString+
1599
                                    " is not a data package id");
1600
      throw e;*/
1601
      
1602
      
1603
      //CB 1/6/03: if the requested docid is not a datapackage, we just zip
1604
      //up the single document and return the zip file.
1605

    
1606
      if(!hasPermissionToExportPackage(docId, user, groups))
1607
      {
1608

    
1609
        Exception e = new Exception("User " + user + " does not have permission"
1610
                         +" to export the data package " + docIdString);
1611
        throw e;
1612
      }
1613

    
1614
      docImpls=new DocumentImpl(docId);
1615
      //checking if the user has the permission to read the documents
1616
      if (docImpls.hasReadPermission(user,groups,docImpls.getDocID()))
1617
      {
1618
        zOut = new ZipOutputStream(out);
1619
        //if the docImpls is metadata
1620
        if ((docImpls.getDoctype()).compareTo("BIN")!=0)
1621
        {
1622
          //add metadata into zip output stream
1623
          addDocToZipOutputStream(docImpls, zOut, rootName);
1624
        }//if
1625
        else
1626
        {
1627
          //it is data file
1628
          addDataFileToZipOutputStream(docImpls, zOut, rootName);
1629
          htmlDocumentImplList.add(docImpls);
1630
        }//else
1631
      }//if
1632

    
1633
      zOut.finish(); //terminate the zip file
1634
      return zOut;
1635
    }
1636
    // Check the permission of user
1637
    else if(!hasPermissionToExportPackage(docId, user, groups))
1638
    {
1639
      
1640
      Exception e = new Exception("User " + user + " does not have permission"
1641
                       +" to export the data package " + docIdString);
1642
      throw e;
1643
    }
1644
    else //it is a packadge id
1645
    { 
1646
      //store the package id
1647
      packageId=docId;
1648
      //get current version in database
1649
      int currentVersion = getCurrentRevFromXMLDoumentsTable(packageId);
1650
      //If it is for current version (-1 means user didn't specify revision)
1651
      if ((version ==-1)||version==currentVersion)
1652
      { 
1653
        //get current version number
1654
        version=currentVersion;
1655
        //get package zip entry name
1656
        //it should be docId.revsion.package
1657
        rootName=packageId+util.getOption("accNumSeparator")+version+
1658
                                  util.getOption("accNumSeparator")+"package";
1659
        //get the whole id list for data packadge
1660
        docIdList=getCurrentDocidListForDataPackage(packageId);
1661
        //get the whole documentImple object
1662
        documentImplList=getCurrentAllDocumentImpl(docIdList);
1663
       
1664
      }//if
1665
      else if (version > currentVersion || version < -1)
1666
      {
1667
        throw new Exception ("The user specified docid: "+docId+"."+version
1668
                                              +" doesn't exist");
1669
      }//else if
1670
      else  //for an old version
1671
      {
1672
       
1673
        rootName=docIdString+util.getOption("accNumSeparator")+"package";
1674
        //get the whole id list for data packadge
1675
        docIdList=getOldVersionDocidListForDataPackage(docIdString);
1676

    
1677
        //get the whole documentImple object
1678
        documentImplList=getOldVersionAllDocumentImpl(docIdList);
1679
      }//else  
1680
      
1681
      // Make sure documentImplist is not empty
1682
      if (documentImplList.isEmpty())
1683
      {
1684
        throw new Exception ("Couldn't find component for data package: "
1685
                                              + packageId);
1686
      }//if
1687
      
1688
     
1689
       zOut = new ZipOutputStream(out);
1690
      //put every element into zip output stream
1691
      for (int i=0; i < documentImplList.size(); i++ )
1692
      {
1693
        // if the object in the vetor is String, this means we couldn't find
1694
        // the document locally, we need find it remote
1695
       if ((((documentImplList.elementAt(i)).getClass()).toString())
1696
                                             .equals("class java.lang.String"))
1697
        {
1698
          // Get String object from vetor
1699
          String documentId = (String) documentImplList.elementAt(i);
1700
          MetaCatUtil.debugMessage("docid: "+documentId, 30);
1701
          // Get doicd without revision
1702
          String docidWithoutRevision = 
1703
                                     MetaCatUtil.getDocIdFromString(documentId);
1704
          MetaCatUtil.debugMessage("docidWithoutRevsion: "
1705
                                                     +docidWithoutRevision, 30);
1706
          // Get revision
1707
          String revision = MetaCatUtil.getRevisionStringFromString(documentId);
1708
          MetaCatUtil.debugMessage("revsion from docIdentifier: "+revision, 30);
1709
          // Zip entry string
1710
          String zipEntryPath = rootName+"/data/"; 
1711
          // Create a RemoteDocument object
1712
          RemoteDocument remoteDoc = 
1713
                          new RemoteDocument(docidWithoutRevision,revision,user, 
1714
                                                     passWord, zipEntryPath);
1715
          // Here we only read data file from remote metacat
1716
          String docType = remoteDoc.getDocType();
1717
          if (docType!=null)
1718
          {
1719
            if (docType.equals("BIN"))
1720
            {
1721
              // Put remote document to zip output
1722
              remoteDoc.readDocumentFromRemoteServerByZip(zOut);
1723
              // Add String object to htmlDocumentImplList
1724
              String elementInHtmlList = remoteDoc.getDocIdWithoutRevsion()+
1725
               MetaCatUtil.getOption("accNumSeparator")+remoteDoc.getRevision();
1726
              htmlDocumentImplList.add(elementInHtmlList);
1727
            }//if
1728
          }//if
1729
         
1730
        }//if
1731
        else
1732
        {
1733
          //create a docmentImpls object (represent xml doc) base on the docId
1734
          docImpls=(DocumentImpl)documentImplList.elementAt(i);
1735
          //checking if the user has the permission to read the documents
1736
          if (docImpls.hasReadPermission(user,groups,docImpls.getDocID()))
1737
          {  
1738
            //if the docImpls is metadata 
1739
            if ((docImpls.getDoctype()).compareTo("BIN")!=0)  
1740
            {
1741
              //add metadata into zip output stream
1742
              addDocToZipOutputStream(docImpls, zOut, rootName);
1743
              //add the documentImpl into the vetor which will be used in html
1744
              htmlDocumentImplList.add(docImpls);
1745
           
1746
            }//if
1747
            else 
1748
            {
1749
              //it is data file 
1750
              addDataFileToZipOutputStream(docImpls, zOut, rootName);
1751
              htmlDocumentImplList.add(docImpls);
1752
            }//else
1753
          }//if
1754
        }//else
1755
      }//for
1756

    
1757
      //add html summary file
1758
      addHtmlSummaryToZipOutputStream(htmlDocumentImplList, zOut, rootName);
1759
      zOut.finish(); //terminate the zip file
1760
      //dbConn.close();
1761
      return zOut;
1762
    }//else
1763
  }//getZippedPackage()
1764
  
1765
   private class ReturnFieldValue
1766
  {
1767
    private String docid          = null; //return field value for this docid
1768
    private String fieldValue     = null;
1769
    private String xmlFieldValue  = null; //return field value in xml format
1770

    
1771
    
1772
    public void setDocid(String myDocid)
1773
    {
1774
      docid = myDocid;
1775
    }
1776
    
1777
    public String getDocid()
1778
    {
1779
      return docid;
1780
    }
1781
    
1782
    public void setFieldValue(String myValue)
1783
    {
1784
      fieldValue = myValue;
1785
    }
1786
    
1787
    public String getFieldValue()
1788
    {
1789
      return fieldValue;
1790
    }
1791
    
1792
    public void setXMLFieldValue(String xml)
1793
    {
1794
      xmlFieldValue = xml;
1795
    }
1796
    
1797
    public String getXMLFieldValue()
1798
    {
1799
      return xmlFieldValue;
1800
    }
1801
    
1802
   
1803
  }
1804
   
1805
}
(20-20/54)