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

    
32
package edu.ucsb.nceas.metacat;
33

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

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

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

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

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

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

    
103
          double connTime = System.currentTimeMillis();
104

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

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

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

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

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

    
326
            btBuf.append("and (subject like '");
327
            btBuf.append(docid).append("'");
328
            btBuf.append("or object like '");
329
            btBuf.append(docid).append("')");
330
            
331
            PreparedStatement npstmt = dbconn.
332
                                       prepareStatement(btBuf.toString());
333
            //should incease usage count
334
            dbconn.increaseUsageCount(1);
335
            npstmt.execute();
336
            ResultSet btrs = npstmt.getResultSet();
337
            boolean hasBtRows = btrs.next();
338
            while (hasBtRows)
339
            { //there was a backtrackable document found
340
              DocumentImpl xmldoc = null;
341
              String packageDocid = btrs.getString(1);
342
              util.debugMessage("Getting document for docid: "+packageDocid,40);
343
              try
344
              {
345
                //  THIS CONSTRUCTOR BUILDS THE WHOLE XML doc not needed here
346
                // xmldoc = new DocumentImpl(dbconn, packageDocid);
347
                //  thus use the following to get the doc info only
348
                //  xmldoc = new DocumentImpl(dbconn);
349
                xmldoc = new DocumentImpl(packageDocid, false);
350
                if (xmldoc == null) {
351
                  util.debugMessage("Document was null for: "+packageDocid, 50);
352
                }
353
              }
354
              catch(Exception e)
355
              {
356
                System.out.println("Error getting document in " + 
357
                                   "DBQuery.findDocuments: " + e.getMessage());
358
              }
359
              
360
              String docid_org = xmldoc.getDocID();
361
              if (docid_org == null) {
362
                util.debugMessage("Docid_org was null.", 40);
363
              }
364
              docid   = docid_org.trim();
365
              docname = xmldoc.getDocname();
366
              doctype = xmldoc.getDoctype();
367
              createDate = xmldoc.getCreateDate();
368
              updateDate = xmldoc.getUpdateDate();
369
              rev = xmldoc.getRev();
370

    
371
              document = new StringBuffer();
372

    
373
              String completeDocid = docid + util.getOption("accNumSeparator");
374
              completeDocid += rev;
375
              document.append("<docid>").append(completeDocid);
376
              document.append("</docid>");
377
              if (docname != null) {
378
                document.append("<docname>" + docname + "</docname>");
379
              }
380
              if (doctype != null) {
381
                document.append("<doctype>" + doctype + "</doctype>");
382
              }
383
              if (createDate != null) {
384
                document.append("<createdate>" + createDate + "</createdate>");
385
              }
386
              if (updateDate != null) {
387
                document.append("<updatedate>" + updateDate + "</updatedate>");
388
              }
389
              // Store the document id and the root node id
390
              docListResult.put(docid,(String)document.toString());
391
         
392
              // Get the next package document linked to our hit
393
              hasBtRows = btrs.next();
394
            }
395
            npstmt.close();
396
            btrs.close();
397
          } 
398
          else if (returndocVec.size() != 0 && returndocVec.contains(doctype)) 
399
          {
400
          
401
            document = new StringBuffer();
402

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

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

    
744
    self.append("SELECT docid,docname,doctype,");
745
    self.append("date_created, date_updated, rev ");
746
    self.append("FROM xml_documents WHERE docid IN (");
747
    self.append("(");
748
    self.append("SELECT DISTINCT docid FROM xml_nodes WHERE \n");
749
    self.append("nodedata LIKE '%%%' ");
750
    self.append(") \n");
751
    self.append(") ");
752
    self.append(" AND (");
753
    self.append(" user_owner = '" + owner + "'");
754
    self.append(") ");
755
    return self.toString();
756
  }
757
  /**
758
   * returns a string array of the contents of a particular node. 
759
   * If the node appears more than once, the contents are returned 
760
   * in the order in which they appearred in the document.
761
   * @param nodename the name or path of the particular node.
762
   * @param docid the docid of the document you want the node from.
763
   */
764
  public static Object[] getNodeContent(String nodename, String docid)
765
  {
766
    DBConnection dbconn = null;
767
    int serialNumber = -1;
768
    StringBuffer query = new StringBuffer();
769
    Vector result = new Vector();
770
    PreparedStatement pstmt = null;
771
    query.append("select nodedata from xml_nodes where parentnodeid in ");
772
    query.append("(select nodeid from xml_index where path like '");
773
    query.append(nodename);
774
    query.append("' and docid like '").append(docid).append("')");
775
    try
776
    {
777
      dbconn=DBConnectionPool.getDBConnection("DBQuery.getNodeContent");
778
        serialNumber=dbconn.getCheckOutSerialNumber();
779
      pstmt = dbconn.prepareStatement(query.toString());
780

    
781
      // Execute the SQL query using the JDBC connection
782
      pstmt.execute();
783
      ResultSet rs = pstmt.getResultSet();
784
      boolean tableHasRows = rs.next();
785
      while (tableHasRows) 
786
      {
787
        result.add(rs.getString(1));
788
        //System.out.println(rs.getString(1));
789
        tableHasRows = rs.next();
790
      }
791
    } 
792
    catch (SQLException e) 
793
    {
794
      System.err.println("Error in DBQuery.getNodeContent: " + e.getMessage());
795
    } finally {
796
      try
797
      {
798
        pstmt.close();
799
      }
800
      catch(SQLException sqle) 
801
      {}
802
      finally
803
      {
804
        DBConnectionPool.returnDBConnection(dbconn, serialNumber);
805
      }
806
      
807
    }
808
    return result.toArray();
809
  }
810
  
811
  /**
812
   * format a structured query as an XML document that conforms
813
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
814
   * structured query engine
815
   *
816
   * @param params The list of parameters that should be included in the query
817
   */
818
  public static String createSQuery(Hashtable params)
819
  { 
820
    StringBuffer query = new StringBuffer();
821
    Enumeration elements;
822
    Enumeration keys;
823
    String filterDoctype = null;
824
    String casesensitive = null;
825
    String searchmode = null;
826
    Object nextkey;
827
    Object nextelement;
828
    //add the xml headers
829
    query.append("<?xml version=\"1.0\"?>\n");
830
    query.append("<pathquery version=\"1.0\">\n");
831

    
832
    if (params.containsKey("meta_file_id"))
833
    {
834
      query.append("<meta_file_id>");
835
      query.append( ((String[])params.get("meta_file_id"))[0]);
836
      query.append("</meta_file_id>");
837
    }
838
    
839
    if (params.containsKey("returndoctype"))
840
    {
841
      String[] returnDoctypes = ((String[])params.get("returndoctype"));
842
      for(int i=0; i<returnDoctypes.length; i++)
843
      {
844
        String doctype = (String)returnDoctypes[i];
845

    
846
        if (!doctype.equals("any") && 
847
            !doctype.equals("ANY") &&
848
            !doctype.equals("") ) 
849
        {
850
          query.append("<returndoctype>").append(doctype);
851
          query.append("</returndoctype>");
852
        }
853
      }
854
    }
855
    
856
    if (params.containsKey("filterdoctype"))
857
    {
858
      String[] filterDoctypes = ((String[])params.get("filterdoctype"));
859
      for(int i=0; i<filterDoctypes.length; i++)
860
      {
861
        query.append("<filterdoctype>").append(filterDoctypes[i]);
862
        query.append("</filterdoctype>");
863
      }
864
    }
865
    
866
    if (params.containsKey("returnfield"))
867
    {
868
      String[] returnfield = ((String[])params.get("returnfield"));
869
      for(int i=0; i<returnfield.length; i++)
870
      {
871
        query.append("<returnfield>").append(returnfield[i]);
872
        query.append("</returnfield>");
873
      }
874
    }
875
    
876
    if (params.containsKey("owner"))
877
    {
878
      String[] owner = ((String[])params.get("owner"));
879
      for(int i=0; i<owner.length; i++)
880
      {
881
        query.append("<owner>").append(owner[i]);
882
        query.append("</owner>");
883
      }
884
    }
885
    
886
    if (params.containsKey("site"))
887
    {
888
      String[] site = ((String[])params.get("site"));
889
      for(int i=0; i<site.length; i++)
890
      {
891
        query.append("<site>").append(site[i]);
892
        query.append("</site>");
893
      }
894
    }
895
    
896
    //allows the dynamic switching of boolean operators
897
    if (params.containsKey("operator"))
898
    {
899
      query.append("<querygroup operator=\"" + 
900
                ((String[])params.get("operator"))[0] + "\">");
901
    }
902
    else
903
    { //the default operator is UNION
904
      query.append("<querygroup operator=\"UNION\">"); 
905
    }
906
        
907
    if (params.containsKey("casesensitive"))
908
    {
909
      casesensitive = ((String[])params.get("casesensitive"))[0]; 
910
    }
911
    else
912
    {
913
      casesensitive = "false"; 
914
    }
915
    
916
    if (params.containsKey("searchmode"))
917
    {
918
      searchmode = ((String[])params.get("searchmode"))[0]; 
919
    }
920
    else
921
    {
922
      searchmode = "contains"; 
923
    }
924
        
925
    //anyfield is a special case because it does a 
926
    //free text search.  It does not have a <pathexpr>
927
    //tag.  This allows for a free text search within the structured
928
    //query.  This is useful if the INTERSECT operator is used.
929
    if (params.containsKey("anyfield"))
930
    {
931
       String[] anyfield = ((String[])params.get("anyfield"));
932
       //allow for more than one value for anyfield
933
       for(int i=0; i<anyfield.length; i++)
934
       {
935
         if (!anyfield[i].equals(""))
936
         {
937
           query.append("<queryterm casesensitive=\"" + casesensitive + 
938
                        "\" " + "searchmode=\"" + searchmode + "\"><value>" +
939
                        anyfield[i] +
940
                        "</value></queryterm>"); 
941
         }
942
       }
943
    }
944
        
945
    //this while loop finds the rest of the parameters
946
    //and attempts to query for the field specified
947
    //by the parameter.
948
    elements = params.elements();
949
    keys = params.keys();
950
    while(keys.hasMoreElements() && elements.hasMoreElements())
951
    {
952
      nextkey = keys.nextElement();
953
      nextelement = elements.nextElement();
954

    
955
      //make sure we aren't querying for any of these
956
      //parameters since the are already in the query
957
      //in one form or another.
958
      Vector ignoredParams = new Vector();
959
      ignoredParams.add("returndoctype");
960
      ignoredParams.add("filterdoctype");
961
      ignoredParams.add("action");
962
      ignoredParams.add("qformat");
963
      ignoredParams.add("anyfield");
964
      ignoredParams.add("returnfield");
965
      ignoredParams.add("owner");
966
      ignoredParams.add("site");
967
      ignoredParams.add("operator");
968

    
969
      // Also ignore parameters listed in the properties file
970
      // so that they can be passed through to stylesheets
971
      String paramsToIgnore = MetaCatUtil.getOption("query.ignored.params");
972
      StringTokenizer st = new StringTokenizer(paramsToIgnore, ",");
973
      while (st.hasMoreTokens()) {
974
          ignoredParams.add(st.nextToken());
975
      }
976
      if (!ignoredParams.contains(nextkey.toString())) {
977
        //allow for more than value per field name
978
        for(int i=0; i<((String[])nextelement).length; i++) {
979
          if (!((String[])nextelement)[i].equals("")) {
980
            query.append("<queryterm casesensitive=\"" + casesensitive +"\" " + 
981
                         "searchmode=\"" + searchmode + "\">" +
982
                         "<value>" +
983
                         //add the query value
984
                         ((String[])nextelement)[i] +
985
                         "</value><pathexpr>" +
986
                         //add the path to query by 
987
                         nextkey.toString() + 
988
                         "</pathexpr></queryterm>");
989
          }
990
        }
991
      }
992
    }
993
    query.append("</querygroup></pathquery>");
994
    //append on the end of the xml and return the result as a string
995
    return query.toString();
996
  }
997
  
998
  /**
999
   * format a simple free-text value query as an XML document that conforms
1000
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
1001
   * structured query engine
1002
   *
1003
   * @param value the text string to search for in the xml catalog
1004
   * @param doctype the type of documents to include in the result set -- use
1005
   *        "any" or "ANY" for unfiltered result sets
1006
   */
1007
   public static String createQuery(String value, String doctype) {
1008
     StringBuffer xmlquery = new StringBuffer();
1009
     xmlquery.append("<?xml version=\"1.0\"?>\n");
1010
     xmlquery.append("<pathquery version=\"1.0\">");
1011

    
1012
     if (!doctype.equals("any") && !doctype.equals("ANY")) {
1013
       xmlquery.append("<returndoctype>");
1014
       xmlquery.append(doctype).append("</returndoctype>");
1015
     }
1016

    
1017
     xmlquery.append("<querygroup operator=\"UNION\">");
1018
     //chad added - 8/14
1019
     //the if statement allows a query to gracefully handle a null 
1020
     //query.  Without this if a nullpointerException is thrown.
1021
     if (!value.equals(""))
1022
     {
1023
       xmlquery.append("<queryterm casesensitive=\"false\" ");
1024
       xmlquery.append("searchmode=\"contains\">");
1025
       xmlquery.append("<value>").append(value).append("</value>");
1026
       xmlquery.append("</queryterm>");
1027
     }
1028
     xmlquery.append("</querygroup>");
1029
     xmlquery.append("</pathquery>");
1030

    
1031
     
1032
     return (xmlquery.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
   */
1042
   public static String createQuery(String value) {
1043
     return createQuery(value, "any");
1044
   }
1045
   
1046
  /** 
1047
    * Check for "READ" permission on @docid for @user and/or @group 
1048
    * from DB connection 
1049
    */
1050
  private boolean hasPermission (String user,
1051
                                  String[] groups, String docid ) 
1052
                  throws SQLException, Exception
1053
  {
1054
    // Check for READ permission on @docid for @user and/or @groups
1055
   PermissionController controller = new PermissionController(docid);
1056
   return controller.hasPermission(user,groups,
1057
                                 AccessControlInterface.READSTRING);
1058
  }
1059

    
1060
  /**
1061
    * Get all docIds list for a data packadge
1062
    * @param dataPackageDocid, the string in docId field of xml_relation table
1063
    */
1064
  private Vector getCurrentDocidListForDataPackage(String dataPackageDocid)
1065
  {
1066
    DBConnection dbConn = null;
1067
    int serialNumber = -1;
1068
    Vector docIdList=new Vector();//return value
1069
    PreparedStatement pStmt = null;
1070
    ResultSet rs=null;
1071
    String docIdInSubjectField=null;
1072
    String docIdInObjectField=null;
1073
    
1074
    // Check the parameter
1075
    if (dataPackageDocid == null || dataPackageDocid.equals(""))
1076
    {
1077
      return docIdList;
1078
    }//if
1079
    
1080
    //the query stirng
1081
    String query="SELECT subject, object from xml_relation where docId = ?";
1082
    try
1083
    {
1084
      dbConn=DBConnectionPool.
1085
                  getDBConnection("DBQuery.getCurrentDocidListForDataPackage");
1086
      serialNumber=dbConn.getCheckOutSerialNumber();
1087
      pStmt=dbConn.prepareStatement(query);
1088
      //bind the value to query
1089
      pStmt.setString(1, dataPackageDocid);
1090

    
1091
      //excute the query
1092
      pStmt.execute();
1093
      //get the result set
1094
      rs=pStmt.getResultSet();
1095
      //process the result
1096
      while (rs.next())
1097
      {
1098
        //In order to get the whole docIds in a data packadge,
1099
        //we need to put the docIds of subject and object field in xml_relation
1100
        //into the return vector
1101
        docIdInSubjectField=rs.getString(1);//the result docId in subject field
1102
        docIdInObjectField=rs.getString(2);//the result docId in object field
1103

    
1104
        //don't put the duplicate docId into the vector
1105
        if (!docIdList.contains(docIdInSubjectField))
1106
        {
1107
          docIdList.add(docIdInSubjectField);
1108
        }
1109

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

    
1347
    byteString = docImpl.toString().getBytes();
1348
    //use docId as the zip entry's name
1349
    zEntry = new ZipEntry(packageZipEntry+"/metadata/"+docImpl.getDocID());
1350
    zEntry.setSize(byteString.length);
1351
    zipOut.putNextEntry(zEntry);
1352
    zipOut.write(byteString, 0, byteString.length);
1353
    zipOut.closeEntry();
1354
  
1355
  }//addDocToZipOutputStream()
1356

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

    
1518
  /**
1519
   *create a html summary for data package and put it into zip output stream
1520
   *@param docImplList, the documentImpl ojbects in data package
1521
   *@param zipOut, the zip output stream which the html should be put
1522
   *@param packageZipEntry, the zip entry name for whole package
1523
   */
1524
   private void addHtmlSummaryToZipOutputStream(Vector docImplList,
1525
                                ZipOutputStream zipOut, String packageZipEntry)
1526
                                           throws Exception
1527
  {
1528
    StringBuffer htmlDoc = new StringBuffer();
1529
    ZipEntry zEntry = null;
1530
    byte[] byteString=null;
1531
    InputStream source;
1532
    DBTransform xmlToHtml;
1533
  
1534
    //create a DBTransform ojbect
1535
    xmlToHtml = new DBTransform();
1536
    //head of html
1537
    htmlDoc.append("<html><head></head><body>");
1538
    for (int i=0; i<docImplList.size(); i++)
1539
    {
1540
      // If this String object, this means it is missed data file
1541
      if ((((docImplList.elementAt(i)).getClass()).toString())
1542
                                             .equals("class java.lang.String"))
1543
      {
1544
        
1545
        htmlDoc.append("<a href=\"");
1546
        String dataFileid =(String)docImplList.elementAt(i);
1547
        htmlDoc.append("./data/").append(dataFileid).append("\">");
1548
        htmlDoc.append("Data File: ");
1549
        htmlDoc.append(dataFileid).append("</a><br>");
1550
        htmlDoc.append("<br><hr><br>");
1551
        
1552
      }//if
1553
      else if ((((DocumentImpl)docImplList.elementAt(i)).getDoctype()).
1554
                                                         compareTo("BIN")!=0)
1555
      { //this is an xml file so we can transform it.
1556
        //transform each file individually then concatenate all of the
1557
        //transformations together.
1558

    
1559
        //for metadata xml title
1560
        htmlDoc.append("<h2>");
1561
        htmlDoc.append(((DocumentImpl)docImplList.elementAt(i)).getDocID());
1562
        //htmlDoc.append(".");
1563
        //htmlDoc.append(((DocumentImpl)docImplList.elementAt(i)).getRev());
1564
        htmlDoc.append("</h2>");
1565
        //do the actual transform
1566
        StringWriter docString = new StringWriter();
1567
        xmlToHtml.transformXMLDocument(
1568
                        ((DocumentImpl)docImplList.elementAt(i)).toString(),
1569
           "-//NCEAS//eml-generic//EN", "-//W3C//HTML//EN", "html", docString);
1570
        htmlDoc.append(docString.toString());
1571
        htmlDoc.append("<br><br><hr><br><br>");
1572
      }//if
1573
      else
1574
      { //this is a data file so we should link to it in the html
1575
        htmlDoc.append("<a href=\"");
1576
        String dataFileid =((DocumentImpl)docImplList.elementAt(i)).getDocID();
1577
        htmlDoc.append("./data/").append(dataFileid).append("\">");
1578
        htmlDoc.append("Data File: ");
1579
        htmlDoc.append(dataFileid).append("</a><br>");
1580
        htmlDoc.append("<br><hr><br>");
1581
      }//else
1582
    }//for
1583
    htmlDoc.append("</body></html>");
1584
    byteString = htmlDoc.toString().getBytes();
1585
    zEntry = new ZipEntry(packageZipEntry+"/metadata.html");
1586
    zEntry.setSize(byteString.length);
1587
    zipOut.putNextEntry(zEntry);
1588
    zipOut.write(byteString, 0, byteString.length);
1589
    zipOut.closeEntry();
1590
    //dbConn.close();
1591
        
1592
  }//addHtmlSummaryToZipOutputStream
1593
  
1594
  
1595
  
1596
  /**
1597
   * put a data packadge into a zip output stream
1598
   * @param docId, which the user want to put into zip output stream
1599
   * @param out, a servletoutput stream which the zip output stream will be put 
1600
   * @param user, the username of the user
1601
   * @param groups, the group of the user
1602
   */
1603
  public ZipOutputStream getZippedPackage(String docIdString, 
1604
        ServletOutputStream out, String user, String[] groups, String passWord)
1605
                    throws ClassNotFoundException, IOException, SQLException, 
1606
                      McdbException, NumberFormatException, Exception
1607
  { 
1608
    ZipOutputStream zOut = null;
1609
    String elementDocid=null;
1610
    DocumentImpl docImpls=null;
1611
    //Connection dbConn = null;
1612
    Vector docIdList=new Vector();
1613
    Vector documentImplList=new Vector();
1614
    Vector htmlDocumentImplList=new Vector();
1615
    String packageId=null;
1616
    String rootName="package";//the package zip entry name
1617
    
1618
    String docId=null;
1619
    int version=-5;
1620
    // Docid without revision
1621
    docId=MetaCatUtil.getDocIdFromString(docIdString);
1622
    // revision number
1623
    version=MetaCatUtil.getVersionFromString(docIdString);
1624
 
1625
    //check if the reqused docId is a data package id
1626
    if (!isDataPackageId(docId))
1627
    {
1628
      
1629
      /*Exception e = new Exception("The request the doc id " +docIdString+
1630
                                    " is not a data package id");
1631
      throw e;*/
1632
      
1633
      
1634
      //CB 1/6/03: if the requested docid is not a datapackage, we just zip
1635
      //up the single document and return the zip file.
1636

    
1637
      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

    
1645
      docImpls=new DocumentImpl(docId);
1646
      //checking if the user has the permission to read the documents
1647
      if (docImpls.hasReadPermission(user,groups,docImpls.getDocID()))
1648
      {
1649
        zOut = new ZipOutputStream(out);
1650
        //if the docImpls is metadata
1651
        if ((docImpls.getDoctype()).compareTo("BIN")!=0)
1652
        {
1653
          //add metadata into zip output stream
1654
          addDocToZipOutputStream(docImpls, zOut, rootName);
1655
        }//if
1656
        else
1657
        {
1658
          //it is data file
1659
          addDataFileToZipOutputStream(docImpls, zOut, rootName);
1660
          htmlDocumentImplList.add(docImpls);
1661
        }//else
1662
      }//if
1663

    
1664
      zOut.finish(); //terminate the zip file
1665
      return zOut;
1666
    }
1667
    // Check the permission of user
1668
    else if(!hasPermissionToExportPackage(docId, user, groups))
1669
    {
1670
      
1671
      Exception e = new Exception("User " + user + " does not have permission"
1672
                       +" to export the data package " + docIdString);
1673
      throw e;
1674
    }
1675
    else //it is a packadge id
1676
    { 
1677
      //store the package id
1678
      packageId=docId;
1679
      //get current version in database
1680
      int currentVersion = getCurrentRevFromXMLDoumentsTable(packageId);
1681
      //If it is for current version (-1 means user didn't specify revision)
1682
      if ((version ==-1)||version==currentVersion)
1683
      { 
1684
        //get current version number
1685
        version=currentVersion;
1686
        //get package zip entry name
1687
        //it should be docId.revsion.package
1688
        rootName=packageId+util.getOption("accNumSeparator")+version+
1689
                                  util.getOption("accNumSeparator")+"package";
1690
        //get the whole id list for data packadge
1691
        docIdList=getCurrentDocidListForDataPackage(packageId);
1692
        //get the whole documentImple object
1693
        documentImplList=getCurrentAllDocumentImpl(docIdList);
1694
       
1695
      }//if
1696
      else if (version > currentVersion || version < -1)
1697
      {
1698
        throw new Exception ("The user specified docid: "+docId+"."+version
1699
                                              +" doesn't exist");
1700
      }//else if
1701
      else  //for an old version
1702
      {
1703
       
1704
        rootName=docIdString+util.getOption("accNumSeparator")+"package";
1705
        //get the whole id list for data packadge
1706
        docIdList=getOldVersionDocidListForDataPackage(docIdString);
1707

    
1708
        //get the whole documentImple object
1709
        documentImplList=getOldVersionAllDocumentImpl(docIdList);
1710
      }//else  
1711
      
1712
      // Make sure documentImplist is not empty
1713
      if (documentImplList.isEmpty())
1714
      {
1715
        throw new Exception ("Couldn't find component for data package: "
1716
                                              + packageId);
1717
      }//if
1718
      
1719
     
1720
       zOut = new ZipOutputStream(out);
1721
      //put every element into zip output stream
1722
      for (int i=0; i < documentImplList.size(); i++ )
1723
      {
1724
        // if the object in the vetor is String, this means we couldn't find
1725
        // the document locally, we need find it remote
1726
       if ((((documentImplList.elementAt(i)).getClass()).toString())
1727
                                             .equals("class java.lang.String"))
1728
        {
1729
          // Get String object from vetor
1730
          String documentId = (String) documentImplList.elementAt(i);
1731
          MetaCatUtil.debugMessage("docid: "+documentId, 30);
1732
          // Get doicd without revision
1733
          String docidWithoutRevision = 
1734
                                     MetaCatUtil.getDocIdFromString(documentId);
1735
          MetaCatUtil.debugMessage("docidWithoutRevsion: "
1736
                                                     +docidWithoutRevision, 30);
1737
          // Get revision
1738
          String revision = MetaCatUtil.getRevisionStringFromString(documentId);
1739
          MetaCatUtil.debugMessage("revsion from docIdentifier: "+revision, 30);
1740
          // Zip entry string
1741
          String zipEntryPath = rootName+"/data/"; 
1742
          // Create a RemoteDocument object
1743
          RemoteDocument remoteDoc = 
1744
                          new RemoteDocument(docidWithoutRevision,revision,user, 
1745
                                                     passWord, zipEntryPath);
1746
          // Here we only read data file from remote metacat
1747
          String docType = remoteDoc.getDocType();
1748
          if (docType!=null)
1749
          {
1750
            if (docType.equals("BIN"))
1751
            {
1752
              // Put remote document to zip output
1753
              remoteDoc.readDocumentFromRemoteServerByZip(zOut);
1754
              // Add String object to htmlDocumentImplList
1755
              String elementInHtmlList = remoteDoc.getDocIdWithoutRevsion()+
1756
               MetaCatUtil.getOption("accNumSeparator")+remoteDoc.getRevision();
1757
              htmlDocumentImplList.add(elementInHtmlList);
1758
            }//if
1759
          }//if
1760
         
1761
        }//if
1762
        else
1763
        {
1764
          //create a docmentImpls object (represent xml doc) base on the docId
1765
          docImpls=(DocumentImpl)documentImplList.elementAt(i);
1766
          //checking if the user has the permission to read the documents
1767
          if (docImpls.hasReadPermission(user,groups,docImpls.getDocID()))
1768
          {  
1769
            //if the docImpls is metadata 
1770
            if ((docImpls.getDoctype()).compareTo("BIN")!=0)  
1771
            {
1772
              //add metadata into zip output stream
1773
              addDocToZipOutputStream(docImpls, zOut, rootName);
1774
              //add the documentImpl into the vetor which will be used in html
1775
              htmlDocumentImplList.add(docImpls);
1776
           
1777
            }//if
1778
            else 
1779
            {
1780
              //it is data file 
1781
              addDataFileToZipOutputStream(docImpls, zOut, rootName);
1782
              htmlDocumentImplList.add(docImpls);
1783
            }//else
1784
          }//if
1785
        }//else
1786
      }//for
1787

    
1788
      //add html summary file
1789
      addHtmlSummaryToZipOutputStream(htmlDocumentImplList, zOut, rootName);
1790
      zOut.finish(); //terminate the zip file
1791
      //dbConn.close();
1792
      return zOut;
1793
    }//else
1794
  }//getZippedPackage()
1795
  
1796
   private class ReturnFieldValue
1797
  {
1798
    private String docid          = null; //return field value for this docid
1799
    private String fieldValue     = null;
1800
    private String xmlFieldValue  = null; //return field value in xml format
1801

    
1802
    
1803
    public void setDocid(String myDocid)
1804
    {
1805
      docid = myDocid;
1806
    }
1807
    
1808
    public String getDocid()
1809
    {
1810
      return docid;
1811
    }
1812
    
1813
    public void setFieldValue(String myValue)
1814
    {
1815
      fieldValue = myValue;
1816
    }
1817
    
1818
    public String getFieldValue()
1819
    {
1820
      return fieldValue;
1821
    }
1822
    
1823
    public void setXMLFieldValue(String xml)
1824
    {
1825
      xmlFieldValue = xml;
1826
    }
1827
    
1828
    public String getXMLFieldValue()
1829
    {
1830
      return xmlFieldValue;
1831
    }
1832
    
1833
   
1834
  }
1835
   
1836
}
(22-22/58)