Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that searches a relational DB for elements and
4
 *             attributes that have free text matches a query string,
5
 *             or structured query matches to a path specified node in the
6
 *             XML hierarchy.  It returns a result set consisting of the
7
 *             document ID for each document that satisfies the query
8
 *  Copyright: 2000 Regents of the University of California and the
9
 *             National Center for Ecological Analysis and Synthesis
10
 *    Authors: Matt Jones
11
 *    Release: @release@
12
 *
13
 *   '$Author: jones $'
14
 *     '$Date: 2004-03-29 13:59:21 -0800 (Mon, 29 Mar 2004) $'
15
 * '$Revision: 2072 $'
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
  /**
68
   * the main routine used to test the DBQuery utility.
69
   * <p>
70
   * Usage: java DBQuery <xmlfile>
71
   *
72
   * @param xmlfile the filename of the xml file containing the query
73
   */
74
  static public void main(String[] args) {
75

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

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

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

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

    
104
          double connTime = System.currentTimeMillis();
105

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

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

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

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

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

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

    
183
  /**
184
   * routine to search the elements and attributes looking to match query
185
   *
186
   * @param xmlquery the xml serialization of the query (@see pathquery.dtd)
187
   * @param user the username of the user
188
   * @param group the group of the user
189
   */
190
  public Hashtable findDocuments(Reader xmlquery, String user, String[] groups)
191
  {
192
    boolean useXMLIndex = (new Boolean(
193
            MetaCatUtil.getOption("usexmlindex"))).booleanValue();
194
    return findDocuments(xmlquery, user, groups, useXMLIndex);
195
  }
196

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

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

    
253
      try {
254

    
255

    
256
        dbconn=DBConnectionPool.getDBConnection("DBQuery.findDocuments");
257
        serialNumber=dbconn.getCheckOutSerialNumber();
258

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

    
276
        double startTime = System.currentTimeMillis()/1000;
277
        pstmt = dbconn.prepareStatement(query);
278

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

    
300
          docname = rs.getString(2);
301
          doctype = rs.getString(3);
302
          createDate = rs.getString(4);
303
          updateDate = rs.getString(5);
304
          rev = rs.getInt(6);
305

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

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

    
329
            btBuf.append("and (subject like '");
330
            btBuf.append(docid).append("'");
331
            btBuf.append("or object like '");
332
            btBuf.append(docid).append("')");
333

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

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

    
374
              document = new StringBuffer();
375

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

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

    
404
            document = new StringBuffer();
405

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

    
424
          }
425

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

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

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

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

    
495
              String parentId = rs.getString(4);
496

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

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

    
560

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

    
566
        }//if has extended query
567

    
568

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

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

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

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

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

    
655
    Vector tempVector = null;
656

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

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

    
672
    Vector tempVector = null;
673

    
674
    for(int count = 0; count < parentidList.size(); count++){
675
      tempVector = (Vector)parentidList.get(count);
676

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

    
684
    tempVector = new Vector();
685
    tempVector.add(0, key);
686
    tempVector.add(1, value);
687
    parentidList.add(tempVector);
688
    return;
689
  }
690

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

    
697
    Vector tempVector = null;
698

    
699
    for(int count = 0; count < parentidList.size(); count++){
700
      tempVector = (Vector)parentidList.get(count);
701

    
702
      if(key.compareTo((String)tempVector.get(0)) == 0){
703
        return (ReturnFieldValue)tempVector.get(1);
704
      }
705
    }
706
    return null;
707
  }
708

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

    
716
    for(int count = 0; count < parentidList.size(); count++){
717
      tempVector = (Vector)parentidList.get(count);
718

    
719
      enum.add(tempVector.get(1));
720
    }
721
    return enum;
722
  }
723

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

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

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

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

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

    
812
  }
813

    
814

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

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

    
861
    if (params.containsKey("meta_file_id"))
862
    {
863
      query.append("<meta_file_id>");
864
      query.append( ((String[])params.get("meta_file_id"))[0]);
865
      query.append("</meta_file_id>");
866
    }
867

    
868
    if (params.containsKey("returndoctype"))
869
    {
870
      String[] returnDoctypes = ((String[])params.get("returndoctype"));
871
      for(int i=0; i<returnDoctypes.length; i++)
872
      {
873
        String doctype = (String)returnDoctypes[i];
874

    
875
        if (!doctype.equals("any") &&
876
            !doctype.equals("ANY") &&
877
            !doctype.equals("") )
878
        {
879
          query.append("<returndoctype>").append(doctype);
880
          query.append("</returndoctype>");
881
        }
882
      }
883
    }
884

    
885
    if (params.containsKey("filterdoctype"))
886
    {
887
      String[] filterDoctypes = ((String[])params.get("filterdoctype"));
888
      for(int i=0; i<filterDoctypes.length; i++)
889
      {
890
        query.append("<filterdoctype>").append(filterDoctypes[i]);
891
        query.append("</filterdoctype>");
892
      }
893
    }
894

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

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

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

    
925
    //allows the dynamic switching of boolean operators
926
    if (params.containsKey("operator"))
927
    {
928
      query.append("<querygroup operator=\"" +
929
                ((String[])params.get("operator"))[0] + "\">");
930
    }
931
    else
932
    { //the default operator is UNION
933
      query.append("<querygroup operator=\"UNION\">");
934
    }
935

    
936
    if (params.containsKey("casesensitive"))
937
    {
938
      casesensitive = ((String[])params.get("casesensitive"))[0];
939
    }
940
    else
941
    {
942
      casesensitive = "false";
943
    }
944

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

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

    
974
    //this while loop finds the rest of the parameters
975
    //and attempts to query for the field specified
976
    //by the parameter.
977
    elements = params.elements();
978
    keys = params.keys();
979
    while(keys.hasMoreElements() && elements.hasMoreElements())
980
    {
981
      nextkey = keys.nextElement();
982
      nextelement = elements.nextElement();
983

    
984
      //make sure we aren't querying for any of these
985
      //parameters since the are already in the query
986
      //in one form or another.
987
      Vector ignoredParams = new Vector();
988
      ignoredParams.add("returndoctype");
989
      ignoredParams.add("filterdoctype");
990
      ignoredParams.add("action");
991
      ignoredParams.add("qformat");
992
      ignoredParams.add("anyfield");
993
      ignoredParams.add("returnfield");
994
      ignoredParams.add("owner");
995
      ignoredParams.add("site");
996
      ignoredParams.add("operator");
997

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

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

    
1041
     if (!doctype.equals("any") && !doctype.equals("ANY")) {
1042
       xmlquery.append("<returndoctype>");
1043
       xmlquery.append(doctype).append("</returndoctype>");
1044
     }
1045

    
1046
     xmlquery.append("<querygroup operator=\"UNION\">");
1047
     //chad added - 8/14
1048
     //the if statement allows a query to gracefully handle a null
1049
     //query.  Without this if a nullpointerException is thrown.
1050
     if (!value.equals(""))
1051
     {
1052
       xmlquery.append("<queryterm casesensitive=\"false\" ");
1053
       xmlquery.append("searchmode=\"contains\">");
1054
       xmlquery.append("<value>").append(value).append("</value>");
1055
       xmlquery.append("</queryterm>");
1056
     }
1057
     xmlquery.append("</querygroup>");
1058
     xmlquery.append("</pathquery>");
1059

    
1060

    
1061
     return (xmlquery.toString());
1062
   }
1063

    
1064
  /**
1065
   * format a simple free-text value query as an XML document that conforms
1066
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
1067
   * structured query engine
1068
   *
1069
   * @param value the text string to search for in the xml catalog
1070
   */
1071
   public static String createQuery(String value) {
1072
     return createQuery(value, "any");
1073
   }
1074

    
1075
  /**
1076
    * Check for "READ" permission on @docid for @user and/or @group
1077
    * from DB connection
1078
    */
1079
  private boolean hasPermission (String user,
1080
                                  String[] groups, String docid )
1081
                  throws SQLException, Exception
1082
  {
1083
    // Check for READ permission on @docid for @user and/or @groups
1084
   PermissionController controller = new PermissionController(docid);
1085
   return controller.hasPermission(user,groups,
1086
                                 AccessControlInterface.READSTRING);
1087
  }
1088

    
1089
  /**
1090
    * Get all docIds list for a data packadge
1091
    * @param dataPackageDocid, the string in docId field of xml_relation table
1092
    */
1093
  private Vector getCurrentDocidListForDataPackage(String dataPackageDocid)
1094
  {
1095
    DBConnection dbConn = null;
1096
    int serialNumber = -1;
1097
    Vector docIdList=new Vector();//return value
1098
    PreparedStatement pStmt = null;
1099
    ResultSet rs=null;
1100
    String docIdInSubjectField=null;
1101
    String docIdInObjectField=null;
1102

    
1103
    // Check the parameter
1104
    if (dataPackageDocid == null || dataPackageDocid.equals(""))
1105
    {
1106
      return docIdList;
1107
    }//if
1108

    
1109
    //the query stirng
1110
    String query="SELECT subject, object from xml_relation where docId = ?";
1111
    try
1112
    {
1113
      dbConn=DBConnectionPool.
1114
                  getDBConnection("DBQuery.getCurrentDocidListForDataPackage");
1115
      serialNumber=dbConn.getCheckOutSerialNumber();
1116
      pStmt=dbConn.prepareStatement(query);
1117
      //bind the value to query
1118
      pStmt.setString(1, dataPackageDocid);
1119

    
1120
      //excute the query
1121
      pStmt.execute();
1122
      //get the result set
1123
      rs=pStmt.getResultSet();
1124
      //process the result
1125
      while (rs.next())
1126
      {
1127
        //In order to get the whole docIds in a data packadge,
1128
        //we need to put the docIds of subject and object field in xml_relation
1129
        //into the return vector
1130
        docIdInSubjectField=rs.getString(1);//the result docId in subject field
1131
        docIdInObjectField=rs.getString(2);//the result docId in object field
1132

    
1133
        //don't put the duplicate docId into the vector
1134
        if (!docIdList.contains(docIdInSubjectField))
1135
        {
1136
          docIdList.add(docIdInSubjectField);
1137
        }
1138

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

    
1172
  /**
1173
   * Get all docIds list for a data packadge
1174
   * @param dataPackageDocid, the string in docId field of xml_relation table
1175
   */
1176
  private Vector getOldVersionDocidListForDataPackage(String dataPackageDocid)
1177
  {
1178

    
1179
    Vector docIdList=new Vector();//return value
1180
    Vector tripleList=null;
1181
    String xml=null;
1182

    
1183
     // Check the parameter
1184
    if (dataPackageDocid == null || dataPackageDocid.equals(""))
1185
    {
1186
      return docIdList;
1187
    }//if
1188

    
1189
    try
1190
    {
1191
      //initial a documentImpl object
1192
      DocumentImpl packageDocument =
1193
                  new DocumentImpl(dataPackageDocid);
1194
      //transfer to documentImpl object to string
1195
      xml=packageDocument.toString();
1196

    
1197
      //create a tripcollection object
1198
      TripleCollection tripleForPackage = new
1199
                                     TripleCollection(new StringReader(xml));
1200
      //get the vetor of triples
1201
      tripleList=tripleForPackage.getCollection();
1202

    
1203
      for (int i= 0; i<tripleList.size(); i++)
1204
      {
1205
        //put subject docid  into docIdlist without duplicate
1206
        if (!docIdList.contains(((Triple)tripleList.elementAt(i)).getSubject()))
1207
        {
1208
          //put subject docid  into docIdlist
1209
          docIdList.add(((Triple)tripleList.get(i)).getSubject());
1210
        }
1211
        //put object docid into docIdlist without duplicate
1212
        if (!docIdList.contains(((Triple)tripleList.elementAt(i)).getObject()))
1213
        {
1214
          docIdList.add(((Triple)(tripleList.get(i))).getObject());
1215
        }
1216
      }//for
1217
    }//try
1218
    catch (Exception e)
1219
    {
1220
      MetaCatUtil.debugMessage("Error in getOldVersionAllDocumentImpl: "
1221
                            +e.getMessage(), 30);
1222
    }//catch
1223

    
1224
    // return result
1225
    return docIdList;
1226
  }//getDocidListForPackageInXMLRevisions()
1227

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

    
1286
  /**
1287
   * Check if the user has the permission to export data package
1288
   * @param conn, the connection
1289
   * @param docId, the id need to be checked
1290
   * @param user, the name of user
1291
   * @param groups, the user's group
1292
   */
1293
   private boolean hasPermissionToExportPackage(String docId,
1294
                                        String user, String[] groups)
1295
                   throws Exception
1296
   {
1297
     //DocumentImpl doc=new DocumentImpl(conn,docId);
1298
     return DocumentImpl.hasReadPermission(user, groups,docId);
1299
   }
1300

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

    
1336
    }//try
1337
    catch (SQLException e)
1338
    {
1339
      MetaCatUtil.debugMessage("Error in getCurrentRevFromXMLDoumentsTable: "
1340
                            +e.getMessage(), 30);
1341
      throw e;
1342
    }//catch
1343
    finally
1344
    {
1345
      try
1346
      {
1347
        pStmt.close();
1348
      }//try
1349
      catch (SQLException ee)
1350
      {
1351
        MetaCatUtil.debugMessage("Error in getCurrentRevFromXMLDoumentsTable: "
1352
                                  +ee.getMessage(), 30);
1353
      }//catch
1354
      finally
1355
      {
1356
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1357
      }//finally
1358
    }//finally
1359
    return rev;
1360
  }//getCurrentRevFromXMLDoumentsTable
1361

    
1362
 /**
1363
   *put a doc into a zip output stream
1364
   *@param docImpl, docmentImpl object which will be sent to zip output stream
1365
   *@param zipOut, zip output stream which the docImpl will be put
1366
   *@param packageZipEntry, the zip entry name for whole package
1367
   */
1368
  private void addDocToZipOutputStream(DocumentImpl docImpl,
1369
                                ZipOutputStream zipOut, String packageZipEntry)
1370
               throws ClassNotFoundException, IOException, SQLException,
1371
                      McdbException, Exception
1372
  {
1373
    byte[] byteString = null;
1374
    ZipEntry zEntry = null;
1375

    
1376
    byteString = docImpl.toString().getBytes();
1377
    //use docId as the zip entry's name
1378
    zEntry = new ZipEntry(packageZipEntry+"/metadata/"+docImpl.getDocID());
1379
    zEntry.setSize(byteString.length);
1380
    zipOut.putNextEntry(zEntry);
1381
    zipOut.write(byteString, 0, byteString.length);
1382
    zipOut.closeEntry();
1383

    
1384
  }//addDocToZipOutputStream()
1385

    
1386

    
1387
  /**
1388
   * Transfer a docid vetor to a documentImpl vector. The documentImpl vetor
1389
   * only inlcudes current version. 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
   * there is not version number in it.
1394
   */
1395

    
1396
  private Vector getCurrentAllDocumentImpl( Vector docIdList)
1397
                              throws McdbException,Exception
1398
  {
1399
    //Connection dbConn=null;
1400
    Vector documentImplList=new Vector();
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
      try
1413
      {
1414
        //get newest version for this docId
1415
        rev=getCurrentRevFromXMLDoumentsTable((String)docIdList.elementAt(i));
1416

    
1417
        // There is no record for this docId in xml_documents table
1418
        if (rev ==-5)
1419
        {
1420
          // Rather than put DocumentImple object, put a String Object(docid)
1421
          // into the documentImplList
1422
          documentImplList.add((String)docIdList.elementAt(i));
1423
          // Skip other code
1424
          continue;
1425
        }
1426

    
1427
        String docidPlusVersion=((String)docIdList.elementAt(i))
1428
                        +util.getOption("accNumSeparator")+rev;
1429

    
1430

    
1431
        //create new documentImpl object
1432
        DocumentImpl documentImplObject =
1433
                                    new DocumentImpl(docidPlusVersion);
1434
       //add them to vector
1435
        documentImplList.add(documentImplObject);
1436
      }//try
1437
      catch (Exception e)
1438
      {
1439
        MetaCatUtil.debugMessage("Error in getCurrentAllDocumentImpl: "
1440
                            +e.getMessage(), 30);
1441
        // continue the for loop
1442
        continue;
1443
      }
1444
    }//for
1445
    return documentImplList;
1446
  }
1447

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

    
1463
    // Check the parameter
1464
    if (docIdList.isEmpty())
1465
    {
1466
      return documentImplList;
1467
    }//if
1468

    
1469
    //for every docid in vector
1470
    for (int i=0;i<docIdList.size();i++)
1471
    {
1472

    
1473
        String docidPlusVersion=(String)(docIdList.elementAt(i));
1474

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

    
1501

    
1502
    }//for
1503
    return documentImplList;
1504
  }//getOldVersionAllDocumentImple
1505

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

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

    
1563
    //create a DBTransform ojbect
1564
    xmlToHtml = new DBTransform();
1565
    //head of html
1566
    htmlDoc.append("<html><head></head><body>");
1567
    for (int i=0; i<docImplList.size(); i++)
1568
    {
1569
      // If this String object, this means it is missed data file
1570
      if ((((docImplList.elementAt(i)).getClass()).toString())
1571
                                             .equals("class java.lang.String"))
1572
      {
1573

    
1574
        htmlDoc.append("<a href=\"");
1575
        String dataFileid =(String)docImplList.elementAt(i);
1576
        htmlDoc.append("./data/").append(dataFileid).append("\">");
1577
        htmlDoc.append("Data File: ");
1578
        htmlDoc.append(dataFileid).append("</a><br>");
1579
        htmlDoc.append("<br><hr><br>");
1580

    
1581
      }//if
1582
      else if ((((DocumentImpl)docImplList.elementAt(i)).getDoctype()).
1583
                                                         compareTo("BIN")!=0)
1584
      { //this is an xml file so we can transform it.
1585
        //transform each file individually then concatenate all of the
1586
        //transformations together.
1587

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

    
1621
  }//addHtmlSummaryToZipOutputStream
1622

    
1623

    
1624

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

    
1647
    String docId=null;
1648
    int version=-5;
1649
    // Docid without revision
1650
    docId=MetaCatUtil.getDocIdFromString(docIdString);
1651
    // revision number
1652
    version=MetaCatUtil.getVersionFromString(docIdString);
1653

    
1654
    //check if the reqused docId is a data package id
1655
    if (!isDataPackageId(docId))
1656
    {
1657

    
1658
      /*Exception e = new Exception("The request the doc id " +docIdString+
1659
                                    " is not a data package id");
1660
      throw e;*/
1661

    
1662

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

    
1666
      if(!hasPermissionToExportPackage(docId, user, groups))
1667
      {
1668

    
1669
        Exception e = new Exception("User " + user + " does not have permission"
1670
                         +" to export the data package " + docIdString);
1671
        throw e;
1672
      }
1673

    
1674
      docImpls=new DocumentImpl(docId);
1675
      //checking if the user has the permission to read the documents
1676
      if (docImpls.hasReadPermission(user,groups,docImpls.getDocID()))
1677
      {
1678
        zOut = new ZipOutputStream(out);
1679
        //if the docImpls is metadata
1680
        if ((docImpls.getDoctype()).compareTo("BIN")!=0)
1681
        {
1682
          //add metadata into zip output stream
1683
          addDocToZipOutputStream(docImpls, zOut, rootName);
1684
        }//if
1685
        else
1686
        {
1687
          //it is data file
1688
          addDataFileToZipOutputStream(docImpls, zOut, rootName);
1689
          htmlDocumentImplList.add(docImpls);
1690
        }//else
1691
      }//if
1692

    
1693
      zOut.finish(); //terminate the zip file
1694
      return zOut;
1695
    }
1696
    // Check the permission of user
1697
    else if(!hasPermissionToExportPackage(docId, user, groups))
1698
    {
1699

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

    
1724
      }//if
1725
      else if (version > currentVersion || version < -1)
1726
      {
1727
        throw new Exception ("The user specified docid: "+docId+"."+version
1728
                                              +" doesn't exist");
1729
      }//else if
1730
      else  //for an old version
1731
      {
1732

    
1733
        rootName=docIdString+util.getOption("accNumSeparator")+"package";
1734
        //get the whole id list for data packadge
1735
        docIdList=getOldVersionDocidListForDataPackage(docIdString);
1736

    
1737
        //get the whole documentImple object
1738
        documentImplList=getOldVersionAllDocumentImpl(docIdList);
1739
      }//else
1740

    
1741
      // Make sure documentImplist is not empty
1742
      if (documentImplList.isEmpty())
1743
      {
1744
        throw new Exception ("Couldn't find component for data package: "
1745
                                              + packageId);
1746
      }//if
1747

    
1748

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

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

    
1806
            }//if
1807
            else
1808
            {
1809
              //it is data file
1810
              addDataFileToZipOutputStream(docImpls, zOut, rootName);
1811
              htmlDocumentImplList.add(docImpls);
1812
            }//else
1813
          }//if
1814
        }//else
1815
      }//for
1816

    
1817
      //add html summary file
1818
      addHtmlSummaryToZipOutputStream(htmlDocumentImplList, zOut, rootName);
1819
      zOut.finish(); //terminate the zip file
1820
      //dbConn.close();
1821
      return zOut;
1822
    }//else
1823
  }//getZippedPackage()
1824

    
1825
   private class ReturnFieldValue
1826
  {
1827
    private String docid          = null; //return field value for this docid
1828
    private String fieldValue     = null;
1829
    private String xmlFieldValue  = null; //return field value in xml format
1830

    
1831

    
1832
    public void setDocid(String myDocid)
1833
    {
1834
      docid = myDocid;
1835
    }
1836

    
1837
    public String getDocid()
1838
    {
1839
      return docid;
1840
    }
1841

    
1842
    public void setFieldValue(String myValue)
1843
    {
1844
      fieldValue = myValue;
1845
    }
1846

    
1847
    public String getFieldValue()
1848
    {
1849
      return fieldValue;
1850
    }
1851

    
1852
    public void setXMLFieldValue(String xml)
1853
    {
1854
      xmlFieldValue = xml;
1855
    }
1856

    
1857
    public String getXMLFieldValue()
1858
    {
1859
      return xmlFieldValue;
1860
    }
1861

    
1862

    
1863
  }
1864

    
1865
}
(22-22/58)