Project

General

Profile

1 301 bojilova
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements utility methods like:
4
 *             1/ Reding all doctypes from db connection
5 699 bojilova
 *             2/ Reading DTD or Schema file from Metacat catalog system
6
 *             3/ Reading Lore type Data Guide from db connection
7 301 bojilova
 *  Copyright: 2000 Regents of the University of California and the
8
 *             National Center for Ecological Analysis and Synthesis
9 315 bojilova
 *    Authors: Jivka Bojilova
10 349 jones
 *    Release: @release@
11 301 bojilova
 *
12
 *   '$Author$'
13
 *     '$Date$'
14
 * '$Revision$'
15 669 jones
 *
16
 * This program is free software; you can redistribute it and/or modify
17
 * it under the terms of the GNU General Public License as published by
18
 * the Free Software Foundation; either version 2 of the License, or
19
 * (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU General Public License
27
 * along with this program; if not, write to the Free Software
28
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 301 bojilova
 */
30
31
package edu.ucsb.nceas.metacat;
32
33
import java.sql.Connection;
34
import java.sql.SQLException;
35
import java.sql.PreparedStatement;
36
import java.sql.ResultSet;
37 699 bojilova
38
import java.io.BufferedInputStream;
39
import java.io.InputStream;
40
import java.io.IOException;
41
import java.net.URL;
42
import java.net.URLConnection;
43
import java.net.MalformedURLException;
44
45 301 bojilova
import java.util.Enumeration;
46
import java.util.Vector;
47 374 bojilova
import java.util.Stack;
48 301 bojilova
49
/**
50
 * A suite of utility classes for quering DB
51
 */
52
public class DBUtil {
53
54 1217 tao
  //private Connection	conn = null;
55 301 bojilova
56
  /**
57
   * main routine used for testing.
58
   * <p>
59
   * Usage: java DBUtil <-dt|-dg>
60
   *
61
   * @param -dt for selecting all doctypes
62
   *        -dg for selecting DataGuide
63
   */
64
  static public void main(String[] args) {
65
66
     if (args.length < 1)
67
     {
68
        System.err.println("Wrong number of arguments!!!");
69 699 bojilova
        System.err.println(
70 793 bojilova
        "USAGE: java DBUtil <-dt | -ds [doctype] | -dg [doctype] | -dl user>");
71 301 bojilova
        return;
72
     } else {
73
        try {
74
75
          // Open a connection to the database
76
          MetaCatUtil   util = new MetaCatUtil();
77 1217 tao
          //Connection dbconn = util.openDBConnection();
78 301 bojilova
79 1217 tao
          DBUtil dbutil = new DBUtil();
80 301 bojilova
81
          if ( args[0].equals("-dt") ) {
82
            String doctypes = dbutil.readDoctypes();
83
            System.out.println(doctypes);
84
          } else if ( args[0].equals("-dg") ) {
85 315 bojilova
            String doctype = null;
86
            if ( args.length == 2 ) { doctype = args[1]; }
87
            String dataguide = dbutil.readDataGuide(doctype);
88 301 bojilova
            System.out.println(dataguide);
89 699 bojilova
          } else if ( args[0].equals("-ds") ) {
90
            String doctype = null;
91
            if ( args.length == 2 ) { doctype = args[1]; }
92
            String dtdschema = dbutil.readDTDSchema(doctype);
93
            System.out.println(dtdschema);
94 793 bojilova
          } else if ( args[0].equals("-dl") ) {
95 847 jones
            String scope = "";
96
            if ( args.length == 2 ) { scope = args[1]; }
97
            String docid = dbutil.getMaxDocid(scope);
98 793 bojilova
            System.out.println(docid);
99 301 bojilova
          } else {
100 699 bojilova
            System.err.println(
101
            "USAGE: java DBUtil <-dt | -ds [doctype] | -dg [doctype]>");
102 301 bojilova
          }
103
104
        } catch (Exception e) {
105 699 bojilova
          //System.err.println("error in DBUtil.main");
106
          //System.err.println(e.getMessage());
107 301 bojilova
          e.printStackTrace(System.err);
108
        }
109
     }
110
  }
111
112
  /**
113
   * Construct an instance of the utility class
114
   */
115 1217 tao
  public DBUtil() {
116
    //this.conn = conn;
117 301 bojilova
  }
118
119
  /**
120
   * read all doctypes from db connection in XML format
121
   * select all Public Id from xml_catalog table
122
   */
123
  public String readDoctypes()
124
        throws SQLException  {
125
126
    Vector doctypeList = new Vector();
127 1217 tao
    DBConnection dbConn = null;
128
    int serialNumber = -1;
129
    PreparedStatement pstmt = null;
130 301 bojilova
    try {
131
132 1217 tao
      dbConn=DBConnectionPool.
133
                  getDBConnection("DBUtil.readDoctypes");
134
      serialNumber=dbConn.getCheckOutSerialNumber();
135
      pstmt =
136
        dbConn.prepareStatement("SELECT public_id FROM xml_catalog " +
137 413 bojilova
                              "WHERE entry_type = 'DTD'");
138 301 bojilova
139
      pstmt.execute();
140
      ResultSet rs = pstmt.getResultSet();
141
      boolean tableHasRows = rs.next();
142
      while (tableHasRows) {
143
           doctypeList.addElement(rs.getString(1));
144
           tableHasRows = rs.next();
145
      }
146
147
      pstmt.close();
148
149
    } catch (SQLException e) {
150 699 bojilova
      throw new SQLException("DBUtil.readDoctypes(). " + e.getMessage());
151 301 bojilova
    }
152 1217 tao
    finally
153
    {
154
      try
155
      {
156
        pstmt.close();
157
      }//try
158
      finally
159
      {
160
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
161
      }//finally
162
    }//finally
163
164 301 bojilova
165
    return formatToXML(doctypeList, "doctype");
166
  }
167
168
  /**
169 699 bojilova
   * read DTD or Schema file from Metacat's XML catalog system
170
   */
171
  public String readDTDSchema(String doctype)
172
        throws SQLException, MalformedURLException, IOException
173
  {
174
    String systemID = null;
175 1217 tao
    PreparedStatement pstmt = null;
176 699 bojilova
    StringBuffer cbuff = new StringBuffer();
177 1217 tao
    DBConnection dbConn = null;
178
    int serialNumber = -1;
179 699 bojilova
    // get doctype's System ID from db catalog
180
    try {
181 1217 tao
182
      dbConn=DBConnectionPool.
183
                  getDBConnection("DBUtil.readDTDSchema");
184
      serialNumber=dbConn.getCheckOutSerialNumber();
185
      pstmt = dbConn.prepareStatement("SELECT system_id " +
186 699 bojilova
                                    "FROM xml_catalog " +
187
                                    "WHERE entry_type in ('DTD','Schema') " +
188
                                    "AND public_id LIKE ?");
189
      pstmt.setString(1, doctype);
190
      pstmt.execute();
191
      ResultSet rs = pstmt.getResultSet();
192
      boolean hasRow = rs.next();
193
      if (hasRow) {
194
        systemID = rs.getString(1);
195
      } else {
196
        throw new SQLException("Non-registered doctype: " + doctype);
197
      }
198
      pstmt.close();
199
200
    } catch (SQLException e) {
201
      throw new SQLException("DBUtil.readDTD(). " + e.getMessage());
202
    }
203 1217 tao
    finally
204
    {
205
      try
206
      {
207
        pstmt.close();
208
      }//try
209
      finally
210
      {
211
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
212
      }//finally
213
    }//finally
214 699 bojilova
215
    // read from URL stream as specified by the System ID.
216
    try {
217
      // open a connection to this URL and return an InputStream
218
      // for reading from that connection
219
      InputStream istream = new URL(systemID).openStream();
220
      // create a buffering character-input stream
221
      // that uses a default-sized input buffer
222
      BufferedInputStream in = new BufferedInputStream(istream);
223
224
      // read the input and write into the string buffer
225
	    int inputByte;
226
	    while ( (inputByte = in.read()) != -1 ) {
227
        cbuff.append((char)inputByte);
228
	    }
229
230
      // the input stream must be closed
231
	    in.close();
232
233
    } catch (MalformedURLException e) {
234
      throw new MalformedURLException
235
      ("DBUtil.readDTD(). " + e.getMessage());
236
    } catch (IOException e) {
237
      throw new IOException
238
      ("DBUtil.readDTD(). " + e.getMessage());
239
    } catch (SecurityException e) {
240
      throw new IOException
241
      ("DBUtil.readDTD(). " + e.getMessage());
242
    }
243
244
   return cbuff.toString();
245
  }
246
247
  /**
248 301 bojilova
   * read Data Guide for a given doctype from db connection in XML format
249
   * select all distinct absolute paths from xml_index table
250
   */
251
  public String readDataGuide( String doctype )
252
        throws SQLException  {
253
254
    Vector dataguide = new Vector();
255
    String path;
256 1217 tao
    PreparedStatement pstmt = null;
257
    DBConnection dbConn = null;
258
    int serialNumber = -1;
259 315 bojilova
260 301 bojilova
    try {
261 1217 tao
        dbConn=DBConnectionPool.
262
                  getDBConnection("DBUtil.readDataGuide");
263
        serialNumber=dbConn.getCheckOutSerialNumber();
264
265 315 bojilova
        if ( doctype != null ) {
266 1217 tao
            pstmt = dbConn.prepareStatement("SELECT distinct path, nodeid " +
267 315 bojilova
                                          "FROM xml_index " +
268
                                          "WHERE path LIKE '/%' " +
269
                                          "AND doctype LIKE ? " +
270
                                          "ORDER BY nodeid");
271
            pstmt.setString(1, doctype);
272
        } else {
273 1217 tao
            pstmt =
274
            dbConn.prepareStatement("SELECT distinct path, doctype, nodeid " +
275 315 bojilova
                                          "FROM xml_index " +
276
                                          "WHERE path LIKE '/%' " +
277 374 bojilova
                                          "ORDER BY doctype, nodeid");
278 315 bojilova
        }
279
280
        pstmt.execute();
281
        ResultSet rs = pstmt.getResultSet();
282
        boolean tableHasRows = rs.next();
283
        while (tableHasRows) {
284
            path = rs.getString(1);
285
            if ( dataguide.indexOf(path) == -1 ) {
286
                dataguide.addElement(path);
287
            }
288
            tableHasRows = rs.next();
289
        }
290 301 bojilova
291 315 bojilova
        pstmt.close();
292 301 bojilova
293
    } catch (SQLException e) {
294 699 bojilova
      throw new SQLException("DBUtil.readDataGuide(). " + e.getMessage());
295 301 bojilova
    }
296 1217 tao
    finally
297
    {
298
      try
299
      {
300
        pstmt.close();
301
      }//try
302
      finally
303
      {
304
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
305
      }//finally
306
    }//finally
307 301 bojilova
308 374 bojilova
    return formatToXML(dataguide);
309 301 bojilova
  }
310
311
  /**
312 374 bojilova
   * format the DataGuide ResultSet to XML
313
   */
314
  private String formatToXML(Vector resultset) {
315
316
    String currPath = null;
317
    String currElement = null;
318
    String prevElement = null;
319
    StringBuffer result = new StringBuffer();
320
    Enumeration rs = resultset.elements();
321
    Stack st = new Stack();
322
    int i = 0;
323
324
    result.append("<?xml version=\"1.0\"?>\n");
325
    result.append("<resultset>\n");
326
327
    while (rs.hasMoreElements()) {
328
        currPath = (String)rs.nextElement();
329
        while ( !In(prevElement, currPath) ) {
330
            currElement = (String)st.pop();
331
            result.append(pad(" ",i--) + "</" + currElement + ">\n");
332
            if ( st.empty() )
333
                prevElement = null;
334
            else
335
                prevElement = (String)st.peek();
336
        }
337
        currElement = getElementFromPath(currPath);
338
        st.push(currElement);
339
        result.append(pad(" ",++i) + "<" + currElement + ">\n");
340
        prevElement = currElement;
341
    }
342
    while ( !st.empty() ) {
343
        prevElement = (String)st.pop();
344
        result.append(pad(" ",i--) + "</" + prevElement + ">\n");
345
    }
346
    result.append("</resultset>\n");
347
348
    return result.toString();
349
  }
350
351
  /**
352
   * check if element is in path like /elem1/elem2/elemn3
353
   */
354
  private boolean In(String element, String path) {
355
356
    if ( element == null ) return true;
357
    return ( path.indexOf(element) != -1 );
358
  }
359
360
  /**
361
   * get last element from path like /elem1/elem2/elemn3
362
   */
363
  private String getElementFromPath(String path) {
364
365
    return ( path.substring(path.lastIndexOf("/")+1) );
366
  }
367
368
  /**
369
   * repeates the str n-times
370
   */
371
  private String pad(String str, int n) {
372
373
    String result = "";
374
    for ( int i = 0; i < n; i++ )
375
        result = result.concat(str);
376
377
    return result;
378
  }
379
380
  /**
381 301 bojilova
   * format the ResultSet to XML
382
   */
383
  private String formatToXML(Vector resultset, String tag) {
384
385
    String val = null;
386
    StringBuffer result = new StringBuffer();
387
    Enumeration rs = resultset.elements();
388
389
    result.append("<?xml version=\"1.0\"?>\n");
390
    result.append("<resultset>\n");
391
    while (rs.hasMoreElements()) {
392
        val = (String)rs.nextElement();
393
        result.append("   <" + tag + ">" + val + "</" + tag + ">\n");
394
    }
395
    result.append("</resultset>\n");
396
397
    return result.toString();
398
  }
399
400 793 bojilova
  /**
401 847 jones
   * get the lastest Accession Number from a particular scope
402 793 bojilova
   */
403 847 jones
  public String getMaxDocid(String scope)
404 793 bojilova
        throws SQLException  {
405 301 bojilova
406 793 bojilova
    String accnum = null;
407
    String sep = MetaCatUtil.getOption("accNumSeparator");
408 1217 tao
    PreparedStatement pstmt = null;
409
    DBConnection dbConn = null;
410
    int serialNumber = -1;
411 793 bojilova
    try {
412 1217 tao
        dbConn=DBConnectionPool.
413
                  getDBConnection("DBUtil.getMaxDocid");
414
        serialNumber=dbConn.getCheckOutSerialNumber();
415
        pstmt =
416
        dbConn.prepareStatement(
417 847 jones
            "SELECT docid, rev, acc FROM " +
418
            "( " +
419
            "SELECT docid, rev, acc FROM " +
420
                "(" +
421
                "SELECT docid, rev, " +
422
                "SUBSTR(docid, INSTR(docid, '" + sep + "', 1)+1)+0 acc " +
423
                "FROM xml_documents " +
424
                "WHERE docid LIKE ? " +
425
                "ORDER BY acc DESC " +
426
                ") " +
427
            "WHERE rownum = 1 " +
428
            "UNION " +
429
            "SELECT docid, rev, acc FROM " +
430
                "(" +
431
                "SELECT docid, rev, " +
432
                "SUBSTR(docid, INSTR(docid, '" + sep + "', 1)+1)+0 acc " +
433
                "FROM xml_revisions " +
434
                "WHERE docid LIKE ? " +
435
                "ORDER BY acc DESC " +
436
                ") " +
437
            "WHERE rownum = 1 " +
438
            ") " +
439
            "ORDER BY acc DESC"
440
            );
441
442
      pstmt.setString(1,scope + sep + "%");
443
      pstmt.setString(2,scope + sep + "%");
444 793 bojilova
      pstmt.execute();
445
      ResultSet rs = pstmt.getResultSet();
446 847 jones
      boolean tableHasRows = rs.next();
447
      // 0, 1 or 2 possible num of rows
448
      // get the first one which is the max accnum
449
      if (tableHasRows) {
450 793 bojilova
        accnum = rs.getString(1) + sep + rs.getString(2);
451 847 jones
        //tableHasRows = rs.next();
452 793 bojilova
      }
453
454
      pstmt.close();
455
456
    } catch (SQLException e) {
457 847 jones
      throw new SQLException("DBUtil.getMaxDocid(). " + e.getMessage());
458 793 bojilova
    }
459 1217 tao
    finally
460
    {
461
      try
462
      {
463
        pstmt.close();
464
      }//try
465
      finally
466
      {
467
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
468
      }//finally
469
    }//finally
470 793 bojilova
471
    return accnum;
472
  }
473 1292 tao
474
  /**
475
   * To a given docid, found a dataset docid which conatains the the given doicd
476
   * This will be done by searching xml_relation table
477
   * If couldn't find, null will be return
478
   * @param givenDocId, the docid which we want to find
479
   */
480
  public static String findDataSetDocIdForGivenDocument(String givenDocId)
481
  {
482
    // Prepared statement for sql
483
    PreparedStatement pStmt = null;
484
    // Result set
485
    ResultSet resultSet = null;
486
    // String to store the data set docid
487
    String dataSetDocId = null;
488
    // DBConnection will be checkout
489
    DBConnection dbConn = null;
490
    int serialNumber = -1;
491
    // String to store the sql command
492
    String sqlCommand = null;
493
    try
494
    {
495
      // Checkout DBConnection from pool
496
      dbConn=DBConnectionPool.
497
                  getDBConnection("DBUtil.findDataSetDocIdForGivenDocument");
498
      serialNumber=dbConn.getCheckOutSerialNumber();
499
      // Sql command to chose a docid from xm_relation table
500
      sqlCommand = "select docid from xml_relation where object like ? or "
501
                                                    + "subject like ?";
502
      // Prepared statement
503
      pStmt = dbConn.prepareStatement(sqlCommand);
504
      // Bind variable
505
      pStmt.setString(1, givenDocId);
506
      pStmt.setString(2, givenDocId);
507
      // Excute prepared statement
508
      pStmt.execute();
509
      // Get result set
510
      resultSet = pStmt.getResultSet();
511
512
      // There has record
513
      if (resultSet.next())
514
      {
515
        // Put the docid into dataSetDocid
516
        dataSetDocId = resultSet.getString(1);
517
        return dataSetDocId;
518
      }//if
519
      else
520
      {
521
        // No record in xml_relation table for given doicd, null returned
522
        return dataSetDocId;
523
      }//else
524
525
    }//try
526
    catch ( SQLException e)
527
    {
528
      // Print out excepition
529
      MetaCatUtil.debugMessage("Error in DBUil.findDataSEtDocIdForGivenDocument"
530
                                +e.getMessage(), 30);
531
      // return null
532
      return dataSetDocId;
533
534
    }//catch
535
    finally
536
    {
537
      try
538
      {
539
        // Close result set
540
        resultSet.close();
541
        // Close preparedStatement
542
        pStmt.close();
543
      }//try
544
      catch ( SQLException e)
545
      {
546
        // Print out excepition
547
        MetaCatUtil.debugMessage("Error in DBUil.findDataSetDocIdForGivenDoc"
548
                                + e.getMessage(), 30);
549
550
      }//catch
551
      finally
552
      {
553
        // Return DBConnection to the pool
554
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
555
      }//finally
556
    }//finally
557
558
  }//findDataSetDocIdForGivenDocument
559
560
  /**
561
   * Method to get current revision and doctype for a given docid
562
   * The output will look like "rev;doctype"
563
   * @param givenDocId, the docid which we want
564
   */
565
  public String getCurrentRevisionAndDocTypeForGivenDocument(String givenDocId)
566
                                                 throws SQLException
567
  {
568
    // DBConection for JDBC
569
    DBConnection dbConn = null;
570
    int serialNumber = -1;
571
    // Prepared Statement
572
    PreparedStatement pstmt = null;
573
    // String to store a docid without rev
574
    String docIdWithoutRevision = null;
575
    // SQL comand
576
    String sqlCommand = null;
577
    // Resulst set
578
    ResultSet rs = null;
579
    // String to store the revision
580
    String revision = null;
581
    // String to store the doctype
582
    String docType = null;
583
584
    // Get docid without rev
585
    docIdWithoutRevision = MetaCatUtil.getDocIdFromString(givenDocId);
586
    // SQL comand is:
587
    sqlCommand = "select rev, doctype from xml_documents where docid like ?";
588
589
    try
590
    {
591
      // Check out the connection
592
      dbConn=DBConnectionPool.
593
         getDBConnection("DBUtil.getCurrentRevisionAndDocTypeForGivenDocument");
594
      serialNumber=dbConn.getCheckOutSerialNumber();
595
596
      // Prepare the sql command
597
      pstmt = dbConn.prepareStatement(sqlCommand);
598
      // Bin vairable
599
      pstmt.setString(1, docIdWithoutRevision);
600
      // Excute the prepared statement
601
      pstmt.execute();
602
      // Get result set
603
      rs = pstmt.getResultSet();
604
      // If there is some record
605
      if (rs.next())
606
      {
607
        revision = rs.getString(1);
608
        docType = rs.getString(2);
609
      }//if
610
      else
611
      {
612
        // No record, throw a exception
613
        throw new
614
              SQLException("There is not record for given docid:"+givenDocId);
615
      }//else
616
617
    }
618
    finally
619
    {
620
      try
621
      {
622
        // Close result set
623
        rs.close();
624
        // Close preparedStatement
625
        pstmt.close();
626
      }//try
627
      catch ( SQLException e)
628
      {
629
        // Print out excepition
630
        MetaCatUtil.debugMessage("Error in DBUil.getCurrentRevisionAndDocType"
631
                                + e.getMessage(), 30);
632
633
      }//catch
634
      finally
635
      {
636
        // Return DBConnection to the pool
637
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
638
      }//finally
639
    }
640
    return revision+";"+docType;
641
  }//getCurrentRevisionAndDocTypeForGivenDocument
642
643 301 bojilova
}