Project

General

Profile

1 155 jones
/**
2 203 jones
 *  '$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 349 jones
 *    Release: @release@
12 155 jones
 *
13 203 jones
 *   '$Author$'
14
 *     '$Date$'
15
 * '$Revision$'
16 669 jones
 *
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 155 jones
 */
31
32 607 bojilova
package edu.ucsb.nceas.metacat;
33 155 jones
34 940 tao
import edu.ucsb.nceas.morpho.datapackage.*;
35 155 jones
import java.io.*;
36 401 berkley
import java.util.Vector;
37 940 tao
import java.util.zip.*;
38 155 jones
import java.net.URL;
39
import java.net.MalformedURLException;
40
import java.sql.*;
41
import java.util.Stack;
42
import java.util.Hashtable;
43
import java.util.Enumeration;
44 706 bojilova
import java.io.File;
45
import java.io.FileWriter;
46
import java.io.BufferedWriter;
47 940 tao
import javax.servlet.ServletOutputStream;
48 155 jones
49
/**
50 172 jones
 * A Class that searches a relational DB for elements and
51
 * attributes that have free text matches a query string,
52
 * or structured query matches to a path specified node in the
53
 * XML hierarchy.  It returns a result set consisting of the
54
 * document ID for each document that satisfies the query
55 155 jones
 */
56
public class DBQuery {
57
58 441 bojilova
  static final int ALL = 1;
59
  static final int WRITE = 2;
60
  static final int READ = 4;
61 940 tao
62 1217 tao
  //private Connection  conn = null;
63 535 jones
  private String  parserName = null;
64 465 berkley
  private MetaCatUtil util = new MetaCatUtil();
65 155 jones
  /**
66
   * the main routine used to test the DBQuery utility.
67 184 jones
   * <p>
68
   * Usage: java DBQuery <xmlfile>
69 155 jones
   *
70 170 jones
   * @param xmlfile the filename of the xml file containing the query
71 155 jones
   */
72
  static public void main(String[] args) {
73
74 184 jones
     if (args.length < 1)
75 155 jones
     {
76
        System.err.println("Wrong number of arguments!!!");
77 706 bojilova
        System.err.println("USAGE: java DBQuery [-t] [-index] <xmlfile>");
78 155 jones
        return;
79
     } else {
80
        try {
81
82 706 bojilova
          int i = 0;
83
          boolean showRuntime = false;
84
          boolean useXMLIndex = false;
85
          if ( args[i].equals( "-t" ) ) {
86
            showRuntime = true;
87
            i++;
88
          }
89
          if ( args[i].equals( "-index" ) ) {
90
            useXMLIndex = true;
91
            i++;
92
          }
93
          String xmlfile  = args[i];
94
95
          // Time the request if asked for
96
          double startTime = System.currentTimeMillis();
97
98 155 jones
          // Open a connection to the database
99 184 jones
          MetaCatUtil   util = new MetaCatUtil();
100 1217 tao
          //Connection dbconn = util.openDBConnection();
101 706 bojilova
102 705 berkley
          double connTime = System.currentTimeMillis();
103 706 bojilova
104 170 jones
          // Execute the query
105 1217 tao
          DBQuery queryobj = new DBQuery(util.getOption("saxparser"));
106 170 jones
          FileReader xml = new FileReader(new File(xmlfile));
107 155 jones
          Hashtable nodelist = null;
108 706 bojilova
          nodelist = queryobj.findDocuments(xml, null, null, useXMLIndex);
109
110 172 jones
          // Print the reulting document listing
111 155 jones
          StringBuffer result = new StringBuffer();
112
          String document = null;
113 170 jones
          String docid = null;
114 155 jones
          result.append("<?xml version=\"1.0\"?>\n");
115 296 higgins
          result.append("<resultset>\n");
116 940 tao
117 743 jones
          if (!showRuntime)
118 710 berkley
          {
119
            Enumeration doclist = nodelist.keys();
120
            while (doclist.hasMoreElements()) {
121
              docid = (String)doclist.nextElement();
122
              document = (String)nodelist.get(docid);
123
              result.append("  <document>\n    " + document +
124
                            "\n  </document>\n");
125
            }
126
127
            result.append("</resultset>\n");
128 155 jones
          }
129 706 bojilova
          // Time the request if asked for
130
          double stopTime = System.currentTimeMillis();
131 705 berkley
          double dbOpenTime = (connTime - startTime)/1000;
132 706 bojilova
          double readTime = (stopTime - connTime)/1000;
133 705 berkley
          double executionTime = (stopTime - startTime)/1000;
134 706 bojilova
          if (showRuntime) {
135 710 berkley
            System.out.print("  " + executionTime);
136
            System.out.print("  " + dbOpenTime);
137
            System.out.print("  " + readTime);
138
            System.out.print("  " + nodelist.size());
139
            System.out.println();
140 706 bojilova
          }
141
          //System.out.println(result);
142
          //write into a file "result.txt"
143 743 jones
          if (!showRuntime)
144 710 berkley
          {
145
            File f = new File("./result.txt");
146
            FileWriter fw = new FileWriter(f);
147
            BufferedWriter out = new BufferedWriter(fw);
148
            out.write(result.toString());
149
            out.flush();
150
            out.close();
151
            fw.close();
152
          }
153
154
        }
155
        catch (Exception e) {
156 675 berkley
          System.err.println("Error in DBQuery.main");
157 155 jones
          System.err.println(e.getMessage());
158
          e.printStackTrace(System.err);
159
        }
160
     }
161
  }
162
163
  /**
164
   * construct an instance of the DBQuery class
165
   *
166
   * <p>Generally, one would call the findDocuments() routine after creating
167
   * an instance to specify the search query</p>
168
   *
169
   * @param conn the JDBC connection that we use for the query
170 172 jones
   * @param parserName the fully qualified name of a Java class implementing
171 185 jones
   *                   the org.xml.sax.XMLReader interface
172 155 jones
   */
173 1217 tao
  public DBQuery(String parserName )
174 155 jones
                  throws IOException,
175
                         SQLException,
176 172 jones
                         ClassNotFoundException {
177 1217 tao
    //this.conn = conn;
178 172 jones
    this.parserName = parserName;
179 155 jones
  }
180
181 745 jones
  /**
182
   * routine to search the elements and attributes looking to match query
183
   *
184
   * @param xmlquery the xml serialization of the query (@see pathquery.dtd)
185
   * @param user the username of the user
186
   * @param group the group of the user
187
   */
188 802 bojilova
  public Hashtable findDocuments(Reader xmlquery, String user, String[] groups)
189 465 berkley
  {
190 802 bojilova
    return findDocuments(xmlquery, user, groups, true);
191 465 berkley
  }
192 706 bojilova
193 155 jones
  /**
194
   * routine to search the elements and attributes looking to match query
195
   *
196 178 jones
   * @param xmlquery the xml serialization of the query (@see pathquery.dtd)
197 465 berkley
   * @param user the username of the user
198
   * @param group the group of the user
199 745 jones
   * @param useXMLIndex flag whether to search using the path index
200 155 jones
   */
201 802 bojilova
  public Hashtable findDocuments(Reader xmlquery, String user, String[] groups,
202 745 jones
                                 boolean useXMLIndex)
203 453 berkley
  {
204 535 jones
      Hashtable   docListResult = new Hashtable();
205 667 berkley
      PreparedStatement pstmt = null;
206 170 jones
      String docid = null;
207 155 jones
      String docname = null;
208
      String doctype = null;
209 401 berkley
      String createDate = null;
210
      String updateDate = null;
211
      String fieldname = null;
212
      String fielddata = null;
213 453 berkley
      String relation = null;
214 1217 tao
      //Connection dbconn = null;
215
      //Connection dbconn2 = null;
216 624 berkley
      int rev = 0;
217 1217 tao
      StringBuffer document = null;
218
      DBConnection dbconn = null;
219
      int serialNumber = -1;
220 465 berkley
221 155 jones
      try {
222 1300 tao
223 1217 tao
224
        dbconn=DBConnectionPool.getDBConnection("DBQuery.findDocuments");
225
        serialNumber=dbconn.getCheckOutSerialNumber();
226 1300 tao
227 172 jones
        // Get the XML query and covert it into a SQL statment
228 178 jones
        QuerySpecification qspec = new QuerySpecification(xmlquery,
229 535 jones
                                   parserName,
230 624 berkley
                                   util.getOption("accNumSeparator"));
231 1303 tao
232 1297 tao
        String query = qspec.printSQL(useXMLIndex);
233 1303 tao
        String ownerQuery = getOwnerQuery(user);
234 1297 tao
        MetaCatUtil.debugMessage("query: "+query, 30);
235 1303 tao
        //MetaCatUtil.debugMessage("query: "+ownerQuery, 30);
236
        // if query is not the owner query, we need to check the permission
237
        // otherwise we don't need (owner has all permission by default)
238
        if (!query.equals(ownerQuery))
239
        {
240
          // set user name and group
241
          qspec.setUserName(user);
242
          qspec.setGroup(groups);
243
          // Get access query
244
          String accessQuery = qspec.getAccessQuery();
245
          query = query + accessQuery;
246
          MetaCatUtil.debugMessage(" final query: "+query, 30);
247
        }
248 1300 tao
249 1297 tao
        double startTime = System.currentTimeMillis()/1000;
250
        pstmt = dbconn.prepareStatement(query);
251 790 bojilova
252 172 jones
        // Execute the SQL query using the JDBC connection
253 155 jones
        pstmt.execute();
254
        ResultSet rs = pstmt.getResultSet();
255 1297 tao
        double queryExecuteTime =System.currentTimeMillis()/1000;
256
        MetaCatUtil.debugMessage("Time for execute query: "+
257
                                            (queryExecuteTime -startTime), 30);
258 155 jones
        boolean tableHasRows = rs.next();
259 667 berkley
        while (tableHasRows)
260
        {
261 768 bojilova
          docid = rs.getString(1).trim();
262 1300 tao
          //long checkTimeStart = System.currentTimeMillis();
263
          //boolean permit =hasPermission(user, groups, docid);
264
          //long checkTimeEnd = System.currentTimeMillis();
265
          //MetaCatUtil.debugMessage("check permission time: "+
266
                                  //(checkTimeEnd - checkTimeStart), 30);
267
          //if ( !permit ) {
268 612 bojilova
            // Advance to the next record in the cursor
269 1300 tao
            //tableHasRows = rs.next();
270
            //continue;
271
          //}
272 1297 tao
273 155 jones
          docname = rs.getString(2);
274
          doctype = rs.getString(3);
275 692 bojilova
          createDate = rs.getString(4);
276
          updateDate = rs.getString(5);
277
          rev = rs.getInt(6);
278 743 jones
279 745 jones
          // if there are returndocs to match, backtracking can be performed
280
          // otherwise, just return the document that was hit
281
          Vector returndocVec = qspec.getReturnDocList();
282 1349 tao
          if (returndocVec.size() != 0 && !returndocVec.contains(doctype)
283
              && !qspec.isPercentageSearch())
284 743 jones
          {
285 1349 tao
            MetaCatUtil.debugMessage("Back tracing now...", 20);
286 743 jones
            String sep = util.getOption("accNumSeparator");
287 465 berkley
            StringBuffer btBuf = new StringBuffer();
288 743 jones
            btBuf.append("select docid from xml_relation where ");
289
290 465 berkley
            //build the doctype list for the backtracking sql statement
291 743 jones
            btBuf.append("packagetype in (");
292 465 berkley
            for(int i=0; i<returndocVec.size(); i++)
293
            {
294
              btBuf.append("'").append((String)returndocVec.get(i)).append("'");
295 743 jones
              if (i != (returndocVec.size() - 1))
296 465 berkley
              {
297
                btBuf.append(", ");
298 475 berkley
              }
299 465 berkley
            }
300
            btBuf.append(") ");
301 743 jones
302
            btBuf.append("and (subject like '");
303 1347 tao
            btBuf.append(docid).append("'");
304 743 jones
            btBuf.append("or object like '");
305 1347 tao
            btBuf.append(docid).append("')");
306 667 berkley
307 743 jones
            PreparedStatement npstmt = dbconn.
308
                                       prepareStatement(btBuf.toString());
309 1217 tao
            //should incease usage count
310
            dbconn.increaseUsageCount(1);
311 671 berkley
            npstmt.execute();
312
            ResultSet btrs = npstmt.getResultSet();
313 465 berkley
            boolean hasBtRows = btrs.next();
314 743 jones
            while (hasBtRows)
315 465 berkley
            { //there was a backtrackable document found
316
              DocumentImpl xmldoc = null;
317 743 jones
              String packageDocid = btrs.getString(1);
318 1096 tao
              util.debugMessage("Getting document for docid: "+packageDocid,40);
319 465 berkley
              try
320
              {
321 800 jones
                //  THIS CONSTRUCTOR BUILDS THE WHOLE XML doc not needed here
322
                // xmldoc = new DocumentImpl(dbconn, packageDocid);
323
                //  thus use the following to get the doc info only
324
                //  xmldoc = new DocumentImpl(dbconn);
325 1217 tao
                xmldoc = new DocumentImpl(packageDocid, false);
326 800 jones
                if (xmldoc == null) {
327 1096 tao
                  util.debugMessage("Document was null for: "+packageDocid, 50);
328 800 jones
                }
329 465 berkley
              }
330
              catch(Exception e)
331
              {
332 675 berkley
                System.out.println("Error getting document in " +
333
                                   "DBQuery.findDocuments: " + e.getMessage());
334 465 berkley
              }
335
336 800 jones
              String docid_org = xmldoc.getDocID();
337
              if (docid_org == null) {
338 1096 tao
                util.debugMessage("Docid_org was null.", 40);
339 800 jones
              }
340
              docid   = docid_org.trim();
341 465 berkley
              docname = xmldoc.getDocname();
342
              doctype = xmldoc.getDoctype();
343
              createDate = xmldoc.getCreateDate();
344
              updateDate = xmldoc.getUpdateDate();
345 743 jones
              rev = xmldoc.getRev();
346
347
              document = new StringBuffer();
348
349
              String completeDocid = docid + util.getOption("accNumSeparator");
350
              completeDocid += rev;
351
              document.append("<docid>").append(completeDocid);
352
              document.append("</docid>");
353
              if (docname != null) {
354
                document.append("<docname>" + docname + "</docname>");
355
              }
356
              if (doctype != null) {
357
                document.append("<doctype>" + doctype + "</doctype>");
358
              }
359
              if (createDate != null) {
360
                document.append("<createdate>" + createDate + "</createdate>");
361
              }
362
              if (updateDate != null) {
363
                document.append("<updatedate>" + updateDate + "</updatedate>");
364
              }
365
              // Store the document id and the root node id
366
              docListResult.put(docid,(String)document.toString());
367
368
              // Get the next package document linked to our hit
369
              hasBtRows = btrs.next();
370 465 berkley
            }
371 671 berkley
            npstmt.close();
372 465 berkley
            btrs.close();
373 1349 tao
          }
374
          else if (returndocVec.size() != 0 && returndocVec.contains(doctype))
375
          {
376 465 berkley
377 743 jones
            document = new StringBuffer();
378
379 624 berkley
            String completeDocid = docid + util.getOption("accNumSeparator");
380
            completeDocid += rev;
381
            document.append("<docid>").append(completeDocid).append("</docid>");
382 465 berkley
            if (docname != null) {
383
              document.append("<docname>" + docname + "</docname>");
384
            }
385
            if (doctype != null) {
386
              document.append("<doctype>" + doctype + "</doctype>");
387
            }
388 743 jones
            if (createDate != null) {
389 465 berkley
              document.append("<createdate>" + createDate + "</createdate>");
390
            }
391 743 jones
            if (updateDate != null) {
392 465 berkley
              document.append("<updatedate>" + updateDate + "</updatedate>");
393
            }
394
            // Store the document id and the root node id
395
            docListResult.put(docid,(String)document.toString());
396 743 jones
397 155 jones
          }
398
399
          // Advance to the next record in the cursor
400
          tableHasRows = rs.next();
401
        }
402 667 berkley
        rs.close();
403 818 berkley
        pstmt.close();
404 1297 tao
        double docListTime =System.currentTimeMillis()/1000;
405
        MetaCatUtil.debugMessage("prepare docid list time: "
406
                                          +(docListTime-queryExecuteTime), 30);
407 401 berkley
408 743 jones
        if (qspec.containsExtendedSQL())
409 401 berkley
        {
410
          Vector extendedFields = new Vector(qspec.getReturnFieldList());
411
          Vector results = new Vector();
412 465 berkley
          Enumeration keylist = docListResult.keys();
413
          StringBuffer doclist = new StringBuffer();
414 1361 tao
          Hashtable parentidList = new Hashtable();
415
          Hashtable returnFieldValue = new Hashtable();
416 465 berkley
          while(keylist.hasMoreElements())
417
          {
418
            doclist.append("'");
419
            doclist.append((String)keylist.nextElement());
420
            doclist.append("',");
421
          }
422 1445 tao
          if (doclist.length() > 0)
423
          {
424
            Hashtable controlPairs = new Hashtable();
425
            double extendedQueryStart = System.currentTimeMillis()/1000;
426 834 jones
            doclist.deleteCharAt(doclist.length()-1); //remove the last comma
427 1445 tao
            // check if user has permission to see the return field data
428
            String accessControlSQL = qspec.
429
                        printAccessControlSQLForReturnField(doclist.toString());
430
            pstmt = dbconn.prepareStatement(accessControlSQL);
431
            //increase dbconnection usage count
432
            dbconn.increaseUsageCount(1);
433
            pstmt.execute();
434
            rs = pstmt.getResultSet();
435
            tableHasRows = rs.next();
436
            while(tableHasRows)
437
            {
438
              long startNodeId = rs.getLong(1);
439
              long endNodeId = rs.getLong(2);
440
              controlPairs.put(new Long(startNodeId), new Long(endNodeId));
441 1450 tao
              tableHasRows = rs.next();
442 1445 tao
            }
443
444
            double extendedAccessQueryEnd = System.currentTimeMillis()/1000;
445
            MetaCatUtil.debugMessage("Time for execute access extended query: "
446
                              +(extendedAccessQueryEnd-extendedQueryStart), 30);
447
448 1448 tao
            String extendedQuery = qspec.printExtendedSQL(doclist.toString(),
449
                                                          controlPairs);
450 1353 tao
            MetaCatUtil.debugMessage("Extended query: "+ extendedQuery, 30);
451 1297 tao
            pstmt = dbconn.prepareStatement(extendedQuery);
452 1217 tao
            //increase dbconnection usage count
453
            dbconn.increaseUsageCount(1);
454 834 jones
            pstmt.execute();
455
            rs = pstmt.getResultSet();
456 1297 tao
            double extendedQueryEnd = System.currentTimeMillis()/1000;
457
            MetaCatUtil.debugMessage("Time for execute extended query: "
458
                                    +(extendedQueryEnd-extendedQueryStart), 30);
459 401 berkley
            tableHasRows = rs.next();
460 834 jones
            while(tableHasRows)
461 401 berkley
            {
462 1361 tao
              ReturnFieldValue returnValue = new ReturnFieldValue();
463 834 jones
              docid = rs.getString(1).trim();
464
              fieldname = rs.getString(2);
465
              fielddata = rs.getString(3);
466 1630 tao
              fielddata = MetaCatUtil.normalize(fielddata);
467
468 1361 tao
              String parentId = rs.getString(4);
469
470
              StringBuffer value = new StringBuffer();
471
              if (!parentidList.containsKey(parentId))
472
              {
473
                // don't need to merger nodedata
474
                value.append("<param name=\"");
475
                value.append(fieldname);
476
                value.append("\">");
477
                value.append(fielddata);
478
                value.append("</param>");
479
                //set returnvalue
480
                returnValue.setDocid(docid);
481
                returnValue.setFieldValue(fielddata);
482
                returnValue.setXMLFieldValue(value.toString());
483
                // Store it in hastable
484
                parentidList.put(parentId, returnValue);
485
              }
486
              else
487
              {
488
                // need to merge nodedata if they have same parent id ant
489
                // node type is text
490
                fielddata = (String)((ReturnFieldValue)
491
                       parentidList.get(parentId)).getFieldValue() +  fielddata;
492
                value.append("<param name=\"");
493
                value.append(fieldname);
494
                value.append("\">");
495
                value.append(fielddata);
496
                value.append("</param>");
497
                returnValue.setDocid(docid);
498
                returnValue.setFieldValue(fielddata);
499
                returnValue.setXMLFieldValue(value.toString());
500
                // remove the old return value from paretnidList
501
                parentidList.remove(parentId);
502
                // store the new return value in parentidlit
503
                parentidList.put(parentId, returnValue);
504
              }
505
               tableHasRows = rs.next();
506
            }//while
507
            rs.close();
508
            pstmt.close();
509 1353 tao
510 1361 tao
            // put the merger node data info into doclistReult
511
            Enumeration xmlFieldValue = parentidList.elements();
512
            while( xmlFieldValue.hasMoreElements() )
513
            {
514
              ReturnFieldValue object = (ReturnFieldValue)
515
                                         xmlFieldValue.nextElement();
516
              docid = object.getDocid();
517 834 jones
              if (docListResult.containsKey(docid))
518
              {
519 1361 tao
                  String removedelement = (String)docListResult.remove(docid);
520
                  docListResult.put(docid, removedelement +
521
                                    object.getXMLFieldValue());
522 834 jones
              }
523
              else
524
              {
525 1361 tao
                  docListResult.put(docid, object.getXMLFieldValue());
526 834 jones
              }
527 1361 tao
            }//while
528 1297 tao
            double docListResultEnd = System.currentTimeMillis()/1000;
529
            MetaCatUtil.debugMessage("Time for prepare doclistresult after"+
530
                                      " execute extended query: "
531
                                    +(docListResultEnd-extendedQueryEnd), 30);
532 1353 tao
533 1361 tao
534 1353 tao
            // get attribures return
535
            docListResult = getAttributeValueForReturn
536
                                      (qspec,docListResult, doclist.toString());
537
          }//if doclist lenght is great than zero
538
539
        }//if has extended query
540 818 berkley
541 1353 tao
542 465 berkley
        //this loop adds the relation data to the resultdoc
543
        //this code might be able to be added to the backtracking code above
544 1297 tao
        double startRelation = System.currentTimeMillis()/1000;
545 465 berkley
        Enumeration docidkeys = docListResult.keys();
546
        while(docidkeys.hasMoreElements())
547 453 berkley
        {
548 602 berkley
          //String connstring = "metacat://"+util.getOption("server")+"?docid=";
549
          String connstring = "%docid=";
550 465 berkley
          String docidkey = (String)docidkeys.nextElement();
551 743 jones
          pstmt = dbconn.prepareStatement(qspec.printRelationSQL(docidkey));
552 465 berkley
          pstmt.execute();
553
          rs = pstmt.getResultSet();
554
          tableHasRows = rs.next();
555
          while(tableHasRows)
556
          {
557
            String sub = rs.getString(1);
558
            String rel = rs.getString(2);
559
            String obj = rs.getString(3);
560 489 berkley
            String subDT = rs.getString(4);
561
            String objDT = rs.getString(5);
562
563 894 berkley
            document = new StringBuffer();
564
            document.append("<triple>");
565
            document.append("<subject>").append(MetaCatUtil.normalize(sub));
566
            document.append("</subject>");
567
            if ( subDT != null ) {
568
              document.append("<subjectdoctype>").append(subDT);
569
              document.append("</subjectdoctype>");
570
            }
571 940 tao
            document.append("<relationship>").
572
                                          append(MetaCatUtil.normalize(rel));
573 894 berkley
            document.append("</relationship>");
574
            document.append("<object>").append(MetaCatUtil.normalize(obj));
575
            document.append("</object>");
576
            if ( objDT != null ) {
577
              document.append("<objectdoctype>").append(objDT);
578
              document.append("</objectdoctype>");
579
            }
580
            document.append("</triple>");
581
582
            String removedelement = (String)docListResult.remove(docidkey);
583
            docListResult.put(docidkey, removedelement +
584
                              document.toString());
585 465 berkley
            tableHasRows = rs.next();
586 453 berkley
          }
587 667 berkley
          rs.close();
588
          pstmt.close();
589 453 berkley
        }
590 1297 tao
        double endRelation = System.currentTimeMillis()/1000;
591
        MetaCatUtil.debugMessage("Time for adding relation to docListResult: "+
592
                                (endRelation-startRelation), 30);
593 667 berkley
594 155 jones
      } catch (SQLException e) {
595 667 berkley
        System.err.println("SQL Error in DBQuery.findDocuments: " +
596
                           e.getMessage());
597 170 jones
      } catch (IOException ioe) {
598 675 berkley
        System.err.println("IO error in DBQuery.findDocuments:");
599 170 jones
        System.err.println(ioe.getMessage());
600 667 berkley
      } catch (Exception ee) {
601 800 jones
        System.err.println("Exception in DBQuery.findDocuments: " +
602 667 berkley
                           ee.getMessage());
603 800 jones
        ee.printStackTrace(System.err);
604 155 jones
      }
605 1217 tao
      finally
606
      {
607 667 berkley
        try
608
        {
609 1217 tao
          pstmt.close();
610
        }//try
611
        catch (SQLException sqlE)
612 667 berkley
        {
613 1217 tao
          MetaCatUtil.debugMessage("Error in DBQuery.findDocuments: "
614
                                      +sqlE.getMessage(), 30);
615
        }//catch
616
        finally
617
        {
618
          DBConnectionPool.returnDBConnection(dbconn, serialNumber);
619
        }//finally
620
      }//finally
621 423 berkley
    //System.out.println("docListResult: ");
622
    //System.out.println(docListResult.toString());
623 155 jones
    return docListResult;
624
  }
625 342 berkley
626 1303 tao
  /*
627 1353 tao
   * A method to return search result after running a query which return
628
   * field have attribue
629
   */
630
  private Hashtable getAttributeValueForReturn(QuerySpecification squery,
631
                                               Hashtable docInformationList,
632
                                               String docList)
633
  {
634
    StringBuffer XML = null;
635
    String sql = null;
636
    DBConnection dbconn = null;
637
    PreparedStatement pstmt = null;
638
    ResultSet rs = null;
639
    int serialNumber = -1;
640
    boolean tableHasRows =false;
641
642
    //check the parameter
643
    if (squery == null || docList==null || docList.length() <0)
644
    {
645
      return docInformationList;
646
    }
647
648
    // if has attribute as return field
649
    if (squery.containAttributeReturnField())
650
    {
651
      sql = squery.printAttributeQuery(docList);
652
      try
653
      {
654
        dbconn=DBConnectionPool.getDBConnection("DBQuery.getAttributeValue");
655
        serialNumber=dbconn.getCheckOutSerialNumber();
656
        pstmt = dbconn.prepareStatement(sql);
657
        pstmt.execute();
658
        rs = pstmt.getResultSet();
659
        tableHasRows = rs.next();
660
        while(tableHasRows)
661
        {
662
          String docid = rs.getString(1).trim();
663
          String fieldname = rs.getString(2);
664
          String fielddata = rs.getString(3);
665
          String attirbuteName = rs.getString(4);
666
          XML = new StringBuffer();
667
668
          XML.append("<param name=\"");
669
          XML.append(fieldname);
670
          XML.append(QuerySpecification.ATTRIBUTESYMBOL);
671
          XML.append(attirbuteName);
672
          XML.append("\">");
673
          XML.append(fielddata);
674
          XML.append("</param>");
675
          tableHasRows = rs.next();
676
677
          if (docInformationList.containsKey(docid))
678
          {
679
            String removedelement = (String)docInformationList.remove(docid);
680
            docInformationList.put(docid, removedelement + XML.toString());
681
          }
682
          else
683
          {
684
            docInformationList.put(docid, XML.toString());
685
          }
686
        }//while
687
        rs.close();
688
        pstmt.close();
689
      }
690
      catch(Exception se)
691
      {
692
        MetaCatUtil.debugMessage("Error in DBQuery.getAttributeValue1: "
693
                                      +se.getMessage(), 30);
694
      }
695
      finally
696
      {
697
        try
698
        {
699
          pstmt.close();
700
        }//try
701
        catch (SQLException sqlE)
702
        {
703
          MetaCatUtil.debugMessage("Error in DBQuery.getAttributeValue2: "
704
                                      +sqlE.getMessage(), 30);
705
        }//catch
706
        finally
707
        {
708
          DBConnectionPool.returnDBConnection(dbconn, serialNumber);
709
        }//finally
710
      }//finally
711
    }//if
712
    return docInformationList;
713
714
  }
715
716
717
  /*
718 1303 tao
   * A method to create a query to get owner's docid list
719
   */
720
  private String getOwnerQuery(String owner)
721
  {
722
    StringBuffer self = new StringBuffer();
723
724
    self.append("SELECT docid,docname,doctype,");
725
    self.append("date_created, date_updated, rev ");
726
    self.append("FROM xml_documents WHERE docid IN (");
727
    self.append("(");
728
    self.append("SELECT DISTINCT docid FROM xml_nodes WHERE \n");
729
    self.append("nodedata LIKE '%%%' ");
730
    self.append(") \n");
731
    self.append(") ");
732
    self.append(" AND (");
733
    self.append(" user_owner = '" + owner + "'");
734
    self.append(") ");
735
    return self.toString();
736
  }
737 342 berkley
  /**
738 436 berkley
   * returns a string array of the contents of a particular node.
739
   * If the node appears more than once, the contents are returned
740
   * in the order in which they appearred in the document.
741
   * @param nodename the name or path of the particular node.
742
   * @param docid the docid of the document you want the node from.
743
   */
744 1217 tao
  public static Object[] getNodeContent(String nodename, String docid)
745 436 berkley
  {
746 1217 tao
    DBConnection dbconn = null;
747
    int serialNumber = -1;
748 436 berkley
    StringBuffer query = new StringBuffer();
749
    Vector result = new Vector();
750 667 berkley
    PreparedStatement pstmt = null;
751 436 berkley
    query.append("select nodedata from xml_nodes where parentnodeid in ");
752
    query.append("(select nodeid from xml_index where path like '");
753
    query.append(nodename);
754
    query.append("' and docid like '").append(docid).append("')");
755
    try
756
    {
757 1217 tao
      dbconn=DBConnectionPool.getDBConnection("DBQuery.getNodeContent");
758
        serialNumber=dbconn.getCheckOutSerialNumber();
759
      pstmt = dbconn.prepareStatement(query.toString());
760 436 berkley
761
      // Execute the SQL query using the JDBC connection
762
      pstmt.execute();
763
      ResultSet rs = pstmt.getResultSet();
764
      boolean tableHasRows = rs.next();
765
      while (tableHasRows)
766
      {
767
        result.add(rs.getString(1));
768 1297 tao
        //System.out.println(rs.getString(1));
769 436 berkley
        tableHasRows = rs.next();
770
      }
771
    }
772
    catch (SQLException e)
773
    {
774 675 berkley
      System.err.println("Error in DBQuery.getNodeContent: " + e.getMessage());
775 667 berkley
    } finally {
776
      try
777
      {
778
        pstmt.close();
779
      }
780 1217 tao
      catch(SQLException sqle)
781
      {}
782
      finally
783
      {
784
        DBConnectionPool.returnDBConnection(dbconn, serialNumber);
785
      }
786
787 667 berkley
    }
788 436 berkley
    return result.toArray();
789
  }
790
791
  /**
792 342 berkley
   * format a structured query as an XML document that conforms
793
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
794
   * structured query engine
795
   *
796 743 jones
   * @param params The list of parameters that should be included in the query
797 342 berkley
   */
798 372 berkley
  public static String createSQuery(Hashtable params)
799 350 berkley
  {
800
    StringBuffer query = new StringBuffer();
801 342 berkley
    Enumeration elements;
802
    Enumeration keys;
803 743 jones
    String filterDoctype = null;
804 372 berkley
    String casesensitive = null;
805
    String searchmode = null;
806 342 berkley
    Object nextkey;
807
    Object nextelement;
808 350 berkley
    //add the xml headers
809
    query.append("<?xml version=\"1.0\"?>\n");
810 743 jones
    query.append("<pathquery version=\"1.0\">\n");
811
812
    if (params.containsKey("meta_file_id"))
813 342 berkley
    {
814 743 jones
      query.append("<meta_file_id>");
815 342 berkley
      query.append( ((String[])params.get("meta_file_id"))[0]);
816 535 jones
      query.append("</meta_file_id>");
817 342 berkley
    }
818 350 berkley
819 743 jones
    if (params.containsKey("returndoctype"))
820 372 berkley
    {
821 744 jones
      String[] returnDoctypes = ((String[])params.get("returndoctype"));
822
      for(int i=0; i<returnDoctypes.length; i++)
823
      {
824
        String doctype = (String)returnDoctypes[i];
825
826
        if (!doctype.equals("any") &&
827
            !doctype.equals("ANY") &&
828
            !doctype.equals("") )
829
        {
830
          query.append("<returndoctype>").append(doctype);
831
          query.append("</returndoctype>");
832
        }
833
      }
834 372 berkley
    }
835 744 jones
836 743 jones
    if (params.containsKey("filterdoctype"))
837
    {
838
      String[] filterDoctypes = ((String[])params.get("filterdoctype"));
839
      for(int i=0; i<filterDoctypes.length; i++)
840
      {
841
        query.append("<filterdoctype>").append(filterDoctypes[i]);
842
        query.append("</filterdoctype>");
843
      }
844
    }
845 372 berkley
846 743 jones
    if (params.containsKey("returnfield"))
847 401 berkley
    {
848
      String[] returnfield = ((String[])params.get("returnfield"));
849
      for(int i=0; i<returnfield.length; i++)
850
      {
851
        query.append("<returnfield>").append(returnfield[i]);
852
        query.append("</returnfield>");
853
      }
854
    }
855
856 743 jones
    if (params.containsKey("owner"))
857 535 jones
    {
858
      String[] owner = ((String[])params.get("owner"));
859
      for(int i=0; i<owner.length; i++)
860
      {
861
        query.append("<owner>").append(owner[i]);
862
        query.append("</owner>");
863
      }
864
    }
865
866 743 jones
    if (params.containsKey("site"))
867 535 jones
    {
868
      String[] site = ((String[])params.get("site"));
869
      for(int i=0; i<site.length; i++)
870
      {
871
        query.append("<site>").append(site[i]);
872
        query.append("</site>");
873
      }
874
    }
875
876 350 berkley
    //allows the dynamic switching of boolean operators
877 743 jones
    if (params.containsKey("operator"))
878 350 berkley
    {
879
      query.append("<querygroup operator=\"" +
880 535 jones
                ((String[])params.get("operator"))[0] + "\">");
881 350 berkley
    }
882
    else
883
    { //the default operator is UNION
884
      query.append("<querygroup operator=\"UNION\">");
885
    }
886 535 jones
887 743 jones
    if (params.containsKey("casesensitive"))
888 372 berkley
    {
889
      casesensitive = ((String[])params.get("casesensitive"))[0];
890
    }
891
    else
892
    {
893
      casesensitive = "false";
894
    }
895
896 743 jones
    if (params.containsKey("searchmode"))
897 372 berkley
    {
898
      searchmode = ((String[])params.get("searchmode"))[0];
899
    }
900
    else
901
    {
902
      searchmode = "contains";
903
    }
904 535 jones
905 342 berkley
    //anyfield is a special case because it does a
906
    //free text search.  It does not have a <pathexpr>
907 350 berkley
    //tag.  This allows for a free text search within the structured
908
    //query.  This is useful if the INTERSECT operator is used.
909 743 jones
    if (params.containsKey("anyfield"))
910 342 berkley
    {
911 372 berkley
       String[] anyfield = ((String[])params.get("anyfield"));
912
       //allow for more than one value for anyfield
913
       for(int i=0; i<anyfield.length; i++)
914 350 berkley
       {
915 743 jones
         if (!anyfield[i].equals(""))
916 372 berkley
         {
917
           query.append("<queryterm casesensitive=\"" + casesensitive +
918
                        "\" " + "searchmode=\"" + searchmode + "\"><value>" +
919 535 jones
                        anyfield[i] +
920
                        "</value></queryterm>");
921 372 berkley
         }
922 350 berkley
       }
923 342 berkley
    }
924 535 jones
925 342 berkley
    //this while loop finds the rest of the parameters
926
    //and attempts to query for the field specified
927
    //by the parameter.
928
    elements = params.elements();
929
    keys = params.keys();
930
    while(keys.hasMoreElements() && elements.hasMoreElements())
931
    {
932
      nextkey = keys.nextElement();
933 535 jones
      nextelement = elements.nextElement();
934 372 berkley
935 535 jones
      //make sure we aren't querying for any of these
936
      //parameters since the are already in the query
937 342 berkley
      //in one form or another.
938 743 jones
      if (!nextkey.toString().equals("returndoctype") &&
939
         !nextkey.toString().equals("filterdoctype")  &&
940 535 jones
         !nextkey.toString().equals("action")  &&
941
         !nextkey.toString().equals("qformat") &&
942
         !nextkey.toString().equals("anyfield") &&
943 401 berkley
         !nextkey.toString().equals("returnfield") &&
944 535 jones
         !nextkey.toString().equals("owner") &&
945
         !nextkey.toString().equals("site") &&
946
         !nextkey.toString().equals("operator") )
947
      {
948 372 berkley
        //allow for more than value per field name
949
        for(int i=0; i<((String[])nextelement).length; i++)
950
        {
951 743 jones
          if (!((String[])nextelement)[i].equals(""))
952 372 berkley
          {
953
            query.append("<queryterm casesensitive=\"" + casesensitive +"\" " +
954 535 jones
                         "searchmode=\"" + searchmode + "\">" +
955
                         "<value>" +
956 372 berkley
                         //add the query value
957 535 jones
                         ((String[])nextelement)[i] +
958
                         "</value><pathexpr>" +
959
                         //add the path to query by
960 372 berkley
                         nextkey.toString() +
961
                         "</pathexpr></queryterm>");
962
          }
963
        }
964 535 jones
      }
965 342 berkley
    }
966
    query.append("</querygroup></pathquery>");
967 350 berkley
    //append on the end of the xml and return the result as a string
968 342 berkley
    return query.toString();
969
  }
970
971 181 jones
  /**
972
   * format a simple free-text value query as an XML document that conforms
973
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
974
   * structured query engine
975
   *
976
   * @param value the text string to search for in the xml catalog
977
   * @param doctype the type of documents to include in the result set -- use
978
   *        "any" or "ANY" for unfiltered result sets
979
   */
980
   public static String createQuery(String value, String doctype) {
981
     StringBuffer xmlquery = new StringBuffer();
982
     xmlquery.append("<?xml version=\"1.0\"?>\n");
983
     xmlquery.append("<pathquery version=\"1.0\">");
984
985
     if (!doctype.equals("any") && !doctype.equals("ANY")) {
986
       xmlquery.append("<returndoctype>");
987
       xmlquery.append(doctype).append("</returndoctype>");
988
     }
989
990
     xmlquery.append("<querygroup operator=\"UNION\">");
991 350 berkley
     //chad added - 8/14
992
     //the if statement allows a query to gracefully handle a null
993
     //query.  Without this if a nullpointerException is thrown.
994 743 jones
     if (!value.equals(""))
995 350 berkley
     {
996
       xmlquery.append("<queryterm casesensitive=\"false\" ");
997
       xmlquery.append("searchmode=\"contains\">");
998
       xmlquery.append("<value>").append(value).append("</value>");
999
       xmlquery.append("</queryterm>");
1000
     }
1001 181 jones
     xmlquery.append("</querygroup>");
1002
     xmlquery.append("</pathquery>");
1003
1004
1005
     return (xmlquery.toString());
1006
   }
1007
1008
  /**
1009
   * format a simple free-text value query as an XML document that conforms
1010
   * to the pathquery.dtd and is appropriate for submission to the DBQuery
1011
   * structured query engine
1012
   *
1013
   * @param value the text string to search for in the xml catalog
1014
   */
1015
   public static String createQuery(String value) {
1016
     return createQuery(value, "any");
1017
   }
1018 441 bojilova
1019 570 bojilova
  /**
1020
    * Check for "READ" permission on @docid for @user and/or @group
1021
    * from DB connection
1022
    */
1023 1217 tao
  private boolean hasPermission (String user,
1024 802 bojilova
                                  String[] groups, String docid )
1025 957 tao
                  throws SQLException, Exception
1026 570 bojilova
  {
1027 802 bojilova
    // Check for READ permission on @docid for @user and/or @groups
1028 1427 tao
   PermissionController controller = new PermissionController(docid);
1029
   return controller.hasPermission(user,groups,
1030
                                 AccessControlInterface.READSTRING);
1031 441 bojilova
  }
1032 940 tao
1033
  /**
1034
    * Get all docIds list for a data packadge
1035
    * @param dataPackageDocid, the string in docId field of xml_relation table
1036
    */
1037
  private Vector getCurrentDocidListForDataPackage(String dataPackageDocid)
1038
  {
1039 1217 tao
    DBConnection dbConn = null;
1040
    int serialNumber = -1;
1041 940 tao
    Vector docIdList=new Vector();//return value
1042 1217 tao
    PreparedStatement pStmt = null;
1043 940 tao
    ResultSet rs=null;
1044
    String docIdInSubjectField=null;
1045
    String docIdInObjectField=null;
1046 1292 tao
1047
    // Check the parameter
1048
    if (dataPackageDocid == null || dataPackageDocid.equals(""))
1049
    {
1050
      return docIdList;
1051
    }//if
1052
1053 940 tao
    //the query stirng
1054
    String query="SELECT subject, object from xml_relation where docId = ?";
1055
    try
1056
    {
1057 1217 tao
      dbConn=DBConnectionPool.
1058
                  getDBConnection("DBQuery.getCurrentDocidListForDataPackage");
1059
      serialNumber=dbConn.getCheckOutSerialNumber();
1060
      pStmt=dbConn.prepareStatement(query);
1061 940 tao
      //bind the value to query
1062
      pStmt.setString(1, dataPackageDocid);
1063
1064
      //excute the query
1065
      pStmt.execute();
1066
      //get the result set
1067
      rs=pStmt.getResultSet();
1068
      //process the result
1069
      while (rs.next())
1070
      {
1071
        //In order to get the whole docIds in a data packadge,
1072
        //we need to put the docIds of subject and object field in xml_relation
1073
        //into the return vector
1074
        docIdInSubjectField=rs.getString(1);//the result docId in subject field
1075
        docIdInObjectField=rs.getString(2);//the result docId in object field
1076
1077
        //don't put the duplicate docId into the vector
1078
        if (!docIdList.contains(docIdInSubjectField))
1079
        {
1080
          docIdList.add(docIdInSubjectField);
1081
        }
1082
1083
        //don't put the duplicate docId into the vector
1084
        if (!docIdList.contains(docIdInObjectField))
1085
        {
1086
          docIdList.add(docIdInObjectField);
1087
        }
1088
      }//while
1089
      //close the pStmt
1090
      pStmt.close();
1091
    }//try
1092
    catch (SQLException e)
1093
    {
1094 1292 tao
      MetaCatUtil.debugMessage("Error in getDocidListForDataPackage: "
1095 1096 tao
                            +e.getMessage(), 30);
1096 940 tao
    }//catch
1097 1217 tao
    finally
1098
    {
1099
      try
1100
      {
1101
        pStmt.close();
1102
      }//try
1103
      catch (SQLException ee)
1104
      {
1105 1292 tao
        MetaCatUtil.debugMessage("Error in getDocidListForDataPackage: "
1106 1217 tao
                            +ee.getMessage(), 30);
1107
      }//catch
1108
      finally
1109
      {
1110
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1111
      }//fianlly
1112
    }//finally
1113 940 tao
    return docIdList;
1114
  }//getCurrentDocidListForDataPackadge()
1115
1116
  /**
1117
   * Get all docIds list for a data packadge
1118
   * @param dataPackageDocid, the string in docId field of xml_relation table
1119
   */
1120
  private Vector getOldVersionDocidListForDataPackage(String dataPackageDocid)
1121
  {
1122 441 bojilova
1123 940 tao
    Vector docIdList=new Vector();//return value
1124
    Vector tripleList=null;
1125
    String xml=null;
1126 1292 tao
1127
     // Check the parameter
1128
    if (dataPackageDocid == null || dataPackageDocid.equals(""))
1129
    {
1130
      return docIdList;
1131
    }//if
1132
1133
    try
1134
    {
1135 1217 tao
      //initial a documentImpl object
1136
      DocumentImpl packageDocument =
1137
                  new DocumentImpl(dataPackageDocid);
1138
      //transfer to documentImpl object to string
1139
      xml=packageDocument.toString();
1140 940 tao
1141 1217 tao
      //create a tripcollection object
1142
      TripleCollection tripleForPackage = new
1143 940 tao
                                     TripleCollection(new StringReader(xml));
1144 1217 tao
      //get the vetor of triples
1145
      tripleList=tripleForPackage.getCollection();
1146 940 tao
1147 1217 tao
      for (int i= 0; i<tripleList.size(); i++)
1148 940 tao
      {
1149 1217 tao
        //put subject docid  into docIdlist without duplicate
1150
        if (!docIdList.contains(((Triple)tripleList.elementAt(i)).getSubject()))
1151
        {
1152
          //put subject docid  into docIdlist
1153
          docIdList.add(((Triple)tripleList.get(i)).getSubject());
1154
        }
1155
        //put object docid into docIdlist without duplicate
1156
        if (!docIdList.contains(((Triple)tripleList.elementAt(i)).getObject()))
1157
        {
1158
          docIdList.add(((Triple)(tripleList.get(i))).getObject());
1159
        }
1160
      }//for
1161 1292 tao
    }//try
1162
    catch (Exception e)
1163
    {
1164
      MetaCatUtil.debugMessage("Error in getOldVersionAllDocumentImpl: "
1165
                            +e.getMessage(), 30);
1166
    }//catch
1167 1217 tao
1168 1292 tao
    // return result
1169 940 tao
    return docIdList;
1170
  }//getDocidListForPackageInXMLRevisions()
1171
1172
  /**
1173
   * Check if the docId is a data packadge id. If the id is a data packadage
1174
   *id, it should be store in the docId fields in xml_relation table.
1175
   *So we can use a query to get the entries which the docId equals the given
1176
   *value. If the result is null. The docId is not a packadge id. Otherwise,
1177
   * it is.
1178
   * @param docId, the id need to be checked
1179
   */
1180
  private boolean isDataPackageId(String docId)
1181
  {
1182
    boolean result=false;
1183 1217 tao
    PreparedStatement pStmt = null;
1184 940 tao
    ResultSet rs=null;
1185
    String query="SELECT docId from xml_relation where docId = ?";
1186 1217 tao
    DBConnection dbConn = null;
1187
    int serialNumber = -1;
1188 940 tao
    try
1189
    {
1190 1217 tao
      dbConn=DBConnectionPool.
1191
                  getDBConnection("DBQuery.isDataPackageId");
1192
      serialNumber=dbConn.getCheckOutSerialNumber();
1193
      pStmt=dbConn.prepareStatement(query);
1194 940 tao
      //bind the value to query
1195
      pStmt.setString(1, docId);
1196
      //execute the query
1197
      pStmt.execute();
1198
      rs=pStmt.getResultSet();
1199
      //process the result
1200
      if (rs.next()) //There are some records for the id in docId fields
1201
      {
1202
        result=true;//It is a data packadge id
1203
      }
1204
      pStmt.close();
1205
    }//try
1206
    catch (SQLException e)
1207
    {
1208 1217 tao
      util.debugMessage("Error in isDataPackageId: "
1209 1096 tao
                            +e.getMessage(), 30);
1210 940 tao
    }
1211 1217 tao
    finally
1212
    {
1213
      try
1214
      {
1215
        pStmt.close();
1216
      }//try
1217
      catch (SQLException ee)
1218
      {
1219
        MetaCatUtil.debugMessage("Error in isDataPackageId: "
1220
                                                        + ee.getMessage(), 30);
1221
      }//catch
1222
      finally
1223
      {
1224
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1225
      }//finally
1226
    }//finally
1227 940 tao
    return result;
1228
  }//isDataPackageId()
1229
1230
  /**
1231 945 tao
   * Check if the user has the permission to export data package
1232
   * @param conn, the connection
1233
   * @param docId, the id need to be checked
1234
   * @param user, the name of user
1235
   * @param groups, the user's group
1236
   */
1237 1217 tao
   private boolean hasPermissionToExportPackage(String docId,
1238 945 tao
                                        String user, String[] groups)
1239
                   throws Exception
1240
   {
1241 1217 tao
     //DocumentImpl doc=new DocumentImpl(conn,docId);
1242
     return DocumentImpl.hasReadPermission(user, groups,docId);
1243 945 tao
   }
1244
1245
  /**
1246 940 tao
   *Get the current Rev for a docid in xml_documents table
1247
   * @param docId, the id need to get version numb
1248
   * If the return value is -5, means no value in rev field for this docid
1249
   */
1250
  private int getCurrentRevFromXMLDoumentsTable(String docId)
1251 1292 tao
                                                throws SQLException
1252 940 tao
  {
1253
    int rev=-5;
1254 1217 tao
    PreparedStatement pStmt = null;
1255 940 tao
    ResultSet rs=null;
1256
    String query="SELECT rev from xml_documents where docId = ?";
1257 1217 tao
    DBConnection dbConn=null;
1258
    int serialNumber = -1;
1259 940 tao
    try
1260
    {
1261 1217 tao
      dbConn=DBConnectionPool.
1262
                  getDBConnection("DBQuery.getCurrentRevFromXMLDocumentsTable");
1263
      serialNumber=dbConn.getCheckOutSerialNumber();
1264
      pStmt=dbConn.prepareStatement(query);
1265 940 tao
      //bind the value to query
1266
      pStmt.setString(1, docId);
1267
      //execute the query
1268
      pStmt.execute();
1269
      rs=pStmt.getResultSet();
1270
      //process the result
1271
      if (rs.next()) //There are some records for rev
1272
      {
1273
        rev=rs.getInt(1);;//It is the version for given docid
1274
      }
1275
      else
1276
      {
1277
        rev=-5;
1278
      }
1279 1292 tao
1280 940 tao
    }//try
1281
    catch (SQLException e)
1282
    {
1283 1292 tao
      MetaCatUtil.debugMessage("Error in getCurrentRevFromXMLDoumentsTable: "
1284 1096 tao
                            +e.getMessage(), 30);
1285 1292 tao
      throw e;
1286 1217 tao
    }//catch
1287
    finally
1288
    {
1289
      try
1290
      {
1291
        pStmt.close();
1292
      }//try
1293
      catch (SQLException ee)
1294
      {
1295
        MetaCatUtil.debugMessage("Error in getCurrentRevFromXMLDoumentsTable: "
1296
                                  +ee.getMessage(), 30);
1297
      }//catch
1298
      finally
1299
      {
1300
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1301
      }//finally
1302
    }//finally
1303 940 tao
    return rev;
1304
  }//getCurrentRevFromXMLDoumentsTable
1305
1306
 /**
1307
   *put a doc into a zip output stream
1308
   *@param docImpl, docmentImpl object which will be sent to zip output stream
1309
   *@param zipOut, zip output stream which the docImpl will be put
1310
   *@param packageZipEntry, the zip entry name for whole package
1311
   */
1312
  private void addDocToZipOutputStream(DocumentImpl docImpl,
1313
                                ZipOutputStream zipOut, String packageZipEntry)
1314
               throws ClassNotFoundException, IOException, SQLException,
1315
                      McdbException, Exception
1316
  {
1317
    byte[] byteString = null;
1318
    ZipEntry zEntry = null;
1319
1320
    byteString = docImpl.toString().getBytes();
1321
    //use docId as the zip entry's name
1322
    zEntry = new ZipEntry(packageZipEntry+"/metadata/"+docImpl.getDocID());
1323
    zEntry.setSize(byteString.length);
1324
    zipOut.putNextEntry(zEntry);
1325
    zipOut.write(byteString, 0, byteString.length);
1326
    zipOut.closeEntry();
1327
1328
  }//addDocToZipOutputStream()
1329
1330
1331
  /**
1332 1292 tao
   * Transfer a docid vetor to a documentImpl vector. The documentImpl vetor
1333
   * only inlcudes current version. If a DocumentImple object
1334
   * couldn't find for a docid, then the String of this docid was added to vetor
1335
   * rather than DocumentImple object.
1336
   * @param docIdList, a vetor hold a docid list for a data package. In docid,
1337
   * there is not version number in it.
1338 940 tao
   */
1339
1340
  private Vector getCurrentAllDocumentImpl( Vector docIdList)
1341
                              throws McdbException,Exception
1342
  {
1343 1217 tao
    //Connection dbConn=null;
1344 940 tao
    Vector documentImplList=new Vector();
1345
    int rev=0;
1346
1347 1292 tao
    // Check the parameter
1348
    if (docIdList.isEmpty())
1349 940 tao
    {
1350 1292 tao
      return documentImplList;
1351
    }//if
1352
1353 940 tao
    //for every docid in vector
1354
    for (int i=0;i<docIdList.size();i++)
1355
    {
1356 1292 tao
      try
1357
      {
1358
        //get newest version for this docId
1359
        rev=getCurrentRevFromXMLDoumentsTable((String)docIdList.elementAt(i));
1360
1361
        // There is no record for this docId in xml_documents table
1362
        if (rev ==-5)
1363
        {
1364
          // Rather than put DocumentImple object, put a String Object(docid)
1365
          // into the documentImplList
1366
          documentImplList.add((String)docIdList.elementAt(i));
1367
          // Skip other code
1368
          continue;
1369
        }
1370 948 tao
1371 1292 tao
        String docidPlusVersion=((String)docIdList.elementAt(i))
1372 948 tao
                        +util.getOption("accNumSeparator")+rev;
1373 1292 tao
1374
1375
        //create new documentImpl object
1376
        DocumentImpl documentImplObject =
1377 1217 tao
                                    new DocumentImpl(docidPlusVersion);
1378 1292 tao
       //add them to vector
1379
        documentImplList.add(documentImplObject);
1380
      }//try
1381
      catch (Exception e)
1382
      {
1383
        MetaCatUtil.debugMessage("Error in getCurrentAllDocumentImpl: "
1384
                            +e.getMessage(), 30);
1385
        // continue the for loop
1386
        continue;
1387
      }
1388 940 tao
    }//for
1389
    return documentImplList;
1390
  }
1391
1392
  /**
1393 1292 tao
   * Transfer a docid vetor to a documentImpl vector. If a DocumentImple object
1394
   * couldn't find for a docid, then the String of this docid was added to vetor
1395
   * rather than DocumentImple object.
1396
   * @param docIdList, a vetor hold a docid list for a data package. In docid,
1397
   *t here is version number in it.
1398 940 tao
   */
1399
  private Vector getOldVersionAllDocumentImpl( Vector docIdList)
1400
  {
1401 1217 tao
    //Connection dbConn=null;
1402 940 tao
    Vector documentImplList=new Vector();
1403
    String siteCode=null;
1404
    String uniqueId=null;
1405
    int rev=0;
1406
1407 1292 tao
    // Check the parameter
1408
    if (docIdList.isEmpty())
1409 940 tao
    {
1410 1292 tao
      return documentImplList;
1411
    }//if
1412
1413 940 tao
    //for every docid in vector
1414
    for (int i=0;i<docIdList.size();i++)
1415
    {
1416
1417 948 tao
        String docidPlusVersion=(String)(docIdList.elementAt(i));
1418 1292 tao
1419
        try
1420
        {
1421
          //create new documentImpl object
1422
          DocumentImpl documentImplObject =
1423 1217 tao
                                    new DocumentImpl(docidPlusVersion);
1424 1292 tao
          //add them to vector
1425
          documentImplList.add(documentImplObject);
1426
        }//try
1427
        catch (McdbDocNotFoundException notFoundE)
1428
        {
1429
          MetaCatUtil.debugMessage("Error in DBQuery.getOldVersionAllDocument"+
1430
                                  "Imple" + notFoundE.getMessage(), 30);
1431
          // Rather than add a DocumentImple object into vetor, a String object
1432
          // - the doicd was added to the vector
1433
          documentImplList.add(docidPlusVersion);
1434
          // Continue the for loop
1435
          continue;
1436
        }//catch
1437
        catch (Exception e)
1438
        {
1439
          MetaCatUtil.debugMessage("Error in DBQuery.getOldVersionAllDocument"+
1440
                                  "Imple" + e.getMessage(), 30);
1441
          // Continue the for loop
1442
          continue;
1443
        }//catch
1444
1445 948 tao
1446 940 tao
    }//for
1447
    return documentImplList;
1448 1292 tao
  }//getOldVersionAllDocumentImple
1449
1450 940 tao
  /**
1451
   *put a data file into a zip output stream
1452
   *@param docImpl, docmentImpl object which will be sent to zip output stream
1453
   *@param zipOut, the zip output stream which the docImpl will be put
1454
   *@param packageZipEntry, the zip entry name for whole package
1455
   */
1456
  private void addDataFileToZipOutputStream(DocumentImpl docImpl,
1457
                                ZipOutputStream zipOut, String packageZipEntry)
1458
               throws ClassNotFoundException, IOException, SQLException,
1459
                      McdbException, Exception
1460
  {
1461
    byte[] byteString = null;
1462
    ZipEntry zEntry = null;
1463
    // this is data file; add file to zip
1464
    String filePath = util.getOption("datafilepath");
1465
    if (!filePath.endsWith("/"))
1466
    {
1467
      filePath += "/";
1468
    }
1469
    String fileName = filePath + docImpl.getDocID();
1470 963 berkley
    zEntry = new ZipEntry(packageZipEntry+"/data/"+docImpl.getDocID());
1471 940 tao
    zipOut.putNextEntry(zEntry);
1472
    FileInputStream fin = null;
1473
    try
1474
    {
1475
      fin = new FileInputStream(fileName);
1476
      byte[] buf = new byte[4 * 1024]; // 4K buffer
1477
      int b = fin.read(buf);
1478
      while (b != -1)
1479
      {
1480
        zipOut.write(buf, 0, b);
1481
        b = fin.read(buf);
1482
      }//while
1483
      zipOut.closeEntry();
1484
    }//try
1485
    catch (IOException ioe)
1486
    {
1487 1096 tao
      util.debugMessage("There is an exception: "+ioe.getMessage(), 30);
1488 940 tao
    }//catch
1489
  }//addDataFileToZipOutputStream()
1490
1491
  /**
1492
   *create a html summary for data package and put it into zip output stream
1493
   *@param docImplList, the documentImpl ojbects in data package
1494
   *@param zipOut, the zip output stream which the html should be put
1495
   *@param packageZipEntry, the zip entry name for whole package
1496
   */
1497
   private void addHtmlSummaryToZipOutputStream(Vector docImplList,
1498
                                ZipOutputStream zipOut, String packageZipEntry)
1499
                                           throws Exception
1500
  {
1501
    StringBuffer htmlDoc = new StringBuffer();
1502
    ZipEntry zEntry = null;
1503
    byte[] byteString=null;
1504
    InputStream source;
1505
    DBTransform xmlToHtml;
1506 1292 tao
1507 940 tao
    //create a DBTransform ojbect
1508 1217 tao
    xmlToHtml = new DBTransform();
1509 940 tao
    //head of html
1510
    htmlDoc.append("<html><head></head><body>");
1511
    for (int i=0; i<docImplList.size(); i++)
1512
    {
1513 1292 tao
      // If this String object, this means it is missed data file
1514
      if ((((docImplList.elementAt(i)).getClass()).toString())
1515
                                             .equals("class java.lang.String"))
1516
      {
1517
1518
        htmlDoc.append("<a href=\"");
1519
        String dataFileid =(String)docImplList.elementAt(i);
1520
        htmlDoc.append("./data/").append(dataFileid).append("\">");
1521
        htmlDoc.append("Data File: ");
1522
        htmlDoc.append(dataFileid).append("</a><br>");
1523
        htmlDoc.append("<br><hr><br>");
1524
1525
      }//if
1526
      else if ((((DocumentImpl)docImplList.elementAt(i)).getDoctype()).
1527 940 tao
                                                         compareTo("BIN")!=0)
1528
      { //this is an xml file so we can transform it.
1529
        //transform each file individually then concatenate all of the
1530
        //transformations together.
1531
1532
        //for metadata xml title
1533
        htmlDoc.append("<h2>");
1534
        htmlDoc.append(((DocumentImpl)docImplList.elementAt(i)).getDocID());
1535
        //htmlDoc.append(".");
1536
        //htmlDoc.append(((DocumentImpl)docImplList.elementAt(i)).getRev());
1537
        htmlDoc.append("</h2>");
1538
        //do the actual transform
1539
        StringWriter docString = new StringWriter();
1540
        xmlToHtml.transformXMLDocument(
1541
                        ((DocumentImpl)docImplList.elementAt(i)).toString(),
1542
           "-//NCEAS//eml-generic//EN", "-//W3C//HTML//EN", "html", docString);
1543
        htmlDoc.append(docString.toString());
1544
        htmlDoc.append("<br><br><hr><br><br>");
1545
      }//if
1546
      else
1547
      { //this is a data file so we should link to it in the html
1548
        htmlDoc.append("<a href=\"");
1549
        String dataFileid =((DocumentImpl)docImplList.elementAt(i)).getDocID();
1550
        htmlDoc.append("./data/").append(dataFileid).append("\">");
1551
        htmlDoc.append("Data File: ");
1552
        htmlDoc.append(dataFileid).append("</a><br>");
1553
        htmlDoc.append("<br><hr><br>");
1554
      }//else
1555
    }//for
1556
    htmlDoc.append("</body></html>");
1557
    byteString = htmlDoc.toString().getBytes();
1558
    zEntry = new ZipEntry(packageZipEntry+"/metadata.html");
1559
    zEntry.setSize(byteString.length);
1560
    zipOut.putNextEntry(zEntry);
1561
    zipOut.write(byteString, 0, byteString.length);
1562
    zipOut.closeEntry();
1563 1217 tao
    //dbConn.close();
1564 940 tao
1565
  }//addHtmlSummaryToZipOutputStream
1566
1567 945 tao
1568
1569 940 tao
  /**
1570
   * put a data packadge into a zip output stream
1571
   * @param docId, which the user want to put into zip output stream
1572
   * @param out, a servletoutput stream which the zip output stream will be put
1573
   * @param user, the username of the user
1574
   * @param groups, the group of the user
1575
   */
1576
  public ZipOutputStream getZippedPackage(String docIdString,
1577 1292 tao
        ServletOutputStream out, String user, String[] groups, String passWord)
1578 940 tao
                    throws ClassNotFoundException, IOException, SQLException,
1579
                      McdbException, NumberFormatException, Exception
1580
  {
1581
    ZipOutputStream zOut = null;
1582
    String elementDocid=null;
1583
    DocumentImpl docImpls=null;
1584 1217 tao
    //Connection dbConn = null;
1585 940 tao
    Vector docIdList=new Vector();
1586 945 tao
    Vector documentImplList=new Vector();
1587
    Vector htmlDocumentImplList=new Vector();
1588 940 tao
    String packageId=null;
1589
    String rootName="package";//the package zip entry name
1590
1591
    String docId=null;
1592
    int version=-5;
1593 1292 tao
    // Docid without revision
1594 940 tao
    docId=MetaCatUtil.getDocIdFromString(docIdString);
1595 1292 tao
    // revision number
1596 940 tao
    version=MetaCatUtil.getVersionFromString(docIdString);
1597
1598
    //check if the reqused docId is a data package id
1599 1356 tao
    if (!isDataPackageId(docId))
1600 940 tao
    {
1601 1356 tao
1602
      /*Exception e = new Exception("The request the doc id " +docIdString+
1603 940 tao
                                    " is not a data package id");
1604 1356 tao
      throw e;*/
1605
1606
1607
      //CB 1/6/03: if the requested docid is not a datapackage, we just zip
1608
      //up the single document and return the zip file.
1609
1610
      if(!hasPermissionToExportPackage(docId, user, groups))
1611
      {
1612
1613
        Exception e = new Exception("User " + user + " does not have permission"
1614
                         +" to export the data package " + docIdString);
1615
        throw e;
1616
      }
1617
1618
      docImpls=new DocumentImpl(docId);
1619
      //checking if the user has the permission to read the documents
1620
      if (docImpls.hasReadPermission(user,groups,docImpls.getDocID()))
1621
      {
1622
        zOut = new ZipOutputStream(out);
1623
        //if the docImpls is metadata
1624
        if ((docImpls.getDoctype()).compareTo("BIN")!=0)
1625
        {
1626
          //add metadata into zip output stream
1627
          addDocToZipOutputStream(docImpls, zOut, rootName);
1628
        }//if
1629
        else
1630
        {
1631
          //it is data file
1632
          addDataFileToZipOutputStream(docImpls, zOut, rootName);
1633
          htmlDocumentImplList.add(docImpls);
1634
        }//else
1635
      }//if
1636
1637
      zOut.finish(); //terminate the zip file
1638
      return zOut;
1639 940 tao
    }
1640 1292 tao
    // Check the permission of user
1641 1217 tao
    else if(!hasPermissionToExportPackage(docId, user, groups))
1642 945 tao
    {
1643 1292 tao
1644 945 tao
      Exception e = new Exception("User " + user + " does not have permission"
1645
                       +" to export the data package " + docIdString);
1646
      throw e;
1647
    }
1648 940 tao
    else //it is a packadge id
1649
    {
1650
      //store the package id
1651
      packageId=docId;
1652 1292 tao
      //get current version in database
1653
      int currentVersion = getCurrentRevFromXMLDoumentsTable(packageId);
1654
      //If it is for current version (-1 means user didn't specify revision)
1655
      if ((version ==-1)||version==currentVersion)
1656 940 tao
      {
1657
        //get current version number
1658 1292 tao
        version=currentVersion;
1659 940 tao
        //get package zip entry name
1660
        //it should be docId.revsion.package
1661
        rootName=packageId+util.getOption("accNumSeparator")+version+
1662
                                  util.getOption("accNumSeparator")+"package";
1663
        //get the whole id list for data packadge
1664
        docIdList=getCurrentDocidListForDataPackage(packageId);
1665
        //get the whole documentImple object
1666
        documentImplList=getCurrentAllDocumentImpl(docIdList);
1667
1668
      }//if
1669 1292 tao
      else if (version > currentVersion || version < -1)
1670
      {
1671
        throw new Exception ("The user specified docid: "+docId+"."+version
1672
                                              +" doesn't exist");
1673
      }//else if
1674 940 tao
      else  //for an old version
1675
      {
1676
1677
        rootName=docIdString+util.getOption("accNumSeparator")+"package";
1678
        //get the whole id list for data packadge
1679
        docIdList=getOldVersionDocidListForDataPackage(docIdString);
1680
1681
        //get the whole documentImple object
1682
        documentImplList=getOldVersionAllDocumentImpl(docIdList);
1683
      }//else
1684
1685 1292 tao
      // Make sure documentImplist is not empty
1686
      if (documentImplList.isEmpty())
1687
      {
1688
        throw new Exception ("Couldn't find component for data package: "
1689
                                              + packageId);
1690
      }//if
1691 940 tao
1692 1292 tao
1693
       zOut = new ZipOutputStream(out);
1694 940 tao
      //put every element into zip output stream
1695
      for (int i=0; i < documentImplList.size(); i++ )
1696
      {
1697 1292 tao
        // if the object in the vetor is String, this means we couldn't find
1698
        // the document locally, we need find it remote
1699
       if ((((documentImplList.elementAt(i)).getClass()).toString())
1700
                                             .equals("class java.lang.String"))
1701
        {
1702
          // Get String object from vetor
1703
          String documentId = (String) documentImplList.elementAt(i);
1704
          MetaCatUtil.debugMessage("docid: "+documentId, 30);
1705
          // Get doicd without revision
1706
          String docidWithoutRevision =
1707
                                     MetaCatUtil.getDocIdFromString(documentId);
1708
          MetaCatUtil.debugMessage("docidWithoutRevsion: "
1709
                                                     +docidWithoutRevision, 30);
1710
          // Get revision
1711
          String revision = MetaCatUtil.getRevisionStringFromString(documentId);
1712
          MetaCatUtil.debugMessage("revsion from docIdentifier: "+revision, 30);
1713
          // Zip entry string
1714
          String zipEntryPath = rootName+"/data/";
1715
          // Create a RemoteDocument object
1716
          RemoteDocument remoteDoc =
1717
                          new RemoteDocument(docidWithoutRevision,revision,user,
1718
                                                     passWord, zipEntryPath);
1719
          // Here we only read data file from remote metacat
1720
          String docType = remoteDoc.getDocType();
1721
          if (docType!=null)
1722
          {
1723
            if (docType.equals("BIN"))
1724
            {
1725
              // Put remote document to zip output
1726
              remoteDoc.readDocumentFromRemoteServerByZip(zOut);
1727
              // Add String object to htmlDocumentImplList
1728
              String elementInHtmlList = remoteDoc.getDocIdWithoutRevsion()+
1729
               MetaCatUtil.getOption("accNumSeparator")+remoteDoc.getRevision();
1730
              htmlDocumentImplList.add(elementInHtmlList);
1731
            }//if
1732
          }//if
1733
1734
        }//if
1735
        else
1736
        {
1737
          //create a docmentImpls object (represent xml doc) base on the docId
1738
          docImpls=(DocumentImpl)documentImplList.elementAt(i);
1739
          //checking if the user has the permission to read the documents
1740
          if (docImpls.hasReadPermission(user,groups,docImpls.getDocID()))
1741
          {
1742 948 tao
            //if the docImpls is metadata
1743 1292 tao
            if ((docImpls.getDoctype()).compareTo("BIN")!=0)
1744
            {
1745 948 tao
              //add metadata into zip output stream
1746
              addDocToZipOutputStream(docImpls, zOut, rootName);
1747
              //add the documentImpl into the vetor which will be used in html
1748
              htmlDocumentImplList.add(docImpls);
1749 953 tao
1750 1292 tao
            }//if
1751
            else
1752
            {
1753
              //it is data file
1754
              addDataFileToZipOutputStream(docImpls, zOut, rootName);
1755
              htmlDocumentImplList.add(docImpls);
1756
            }//else
1757 948 tao
          }//if
1758 1292 tao
        }//else
1759 940 tao
      }//for
1760
1761
      //add html summary file
1762 945 tao
      addHtmlSummaryToZipOutputStream(htmlDocumentImplList, zOut, rootName);
1763 940 tao
      zOut.finish(); //terminate the zip file
1764 1217 tao
      //dbConn.close();
1765 940 tao
      return zOut;
1766
    }//else
1767
  }//getZippedPackage()
1768 1361 tao
1769
   private class ReturnFieldValue
1770
  {
1771
    private String docid          = null; //return field value for this docid
1772
    private String fieldValue     = null;
1773
    private String xmlFieldValue  = null; //return field value in xml format
1774
1775
1776
    public void setDocid(String myDocid)
1777
    {
1778
      docid = myDocid;
1779
    }
1780
1781
    public String getDocid()
1782
    {
1783
      return docid;
1784
    }
1785
1786
    public void setFieldValue(String myValue)
1787
    {
1788
      fieldValue = myValue;
1789
    }
1790
1791
    public String getFieldValue()
1792
    {
1793
      return fieldValue;
1794
    }
1795
1796
    public void setXMLFieldValue(String xml)
1797
    {
1798
      xmlFieldValue = xml;
1799
    }
1800
1801
    public String getXMLFieldValue()
1802
    {
1803
      return xmlFieldValue;
1804
    }
1805
1806 940 tao
1807 1361 tao
  }
1808
1809 155 jones
}