Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements utility methods like:
4
 *             1/ Reding all doctypes from db connection
5
 *             2/ Reading DTD or Schema file from Metacat catalog system
6
 *             3/ Reading Lore type Data Guide from db connection
7
 *  Copyright: 2000 Regents of the University of California and the
8
 *             National Center for Ecological Analysis and Synthesis
9
 *    Authors: Jivka Bojilova
10
 *    Release: @release@
11
 * 
12
 *   '$Author: jones $'
13
 *     '$Date: 2001-10-19 14:50:57 -0700 (Fri, 19 Oct 2001) $'
14
 * '$Revision: 847 $'
15
 *
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
 */
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

    
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
import java.util.Enumeration;
46
import java.util.Vector;
47
import java.util.Stack;
48

    
49
/**
50
 * A suite of utility classes for quering DB
51
 */
52
public class DBUtil {
53

    
54
  private Connection	conn = null;
55

    
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
        System.err.println(
70
        "USAGE: java DBUtil <-dt | -ds [doctype] | -dg [doctype] | -dl user>");
71
        return;
72
     } else {
73
        try {
74
                    
75
          // Open a connection to the database
76
          MetaCatUtil   util = new MetaCatUtil();
77
          Connection dbconn = util.openDBConnection();
78

    
79
          DBUtil dbutil = new DBUtil( dbconn );
80
          
81
          if ( args[0].equals("-dt") ) {
82
            String doctypes = dbutil.readDoctypes();
83
            System.out.println(doctypes);
84
          } else if ( args[0].equals("-dg") ) {
85
            String doctype = null;
86
            if ( args.length == 2 ) { doctype = args[1]; }
87
            String dataguide = dbutil.readDataGuide(doctype);
88
            System.out.println(dataguide);
89
          } 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
          } else if ( args[0].equals("-dl") ) {
95
            String scope = "";
96
            if ( args.length == 2 ) { scope = args[1]; }
97
            String docid = dbutil.getMaxDocid(scope);
98
            System.out.println(docid);
99
          } else {
100
            System.err.println(
101
            "USAGE: java DBUtil <-dt | -ds [doctype] | -dg [doctype]>");
102
          }  
103

    
104
        } catch (Exception e) {
105
          //System.err.println("error in DBUtil.main");
106
          //System.err.println(e.getMessage());
107
          e.printStackTrace(System.err);
108
        }
109
     }
110
  }
111
  
112
  /**
113
   * Construct an instance of the utility class
114
   */
115
  public DBUtil( Connection conn ) {
116
    this.conn = conn;
117
  }
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

    
128
    try {
129

    
130
      PreparedStatement pstmt =
131
        conn.prepareStatement("SELECT public_id FROM xml_catalog " +
132
                              "WHERE entry_type = 'DTD'");
133

    
134
      pstmt.execute();
135
      ResultSet rs = pstmt.getResultSet();
136
      boolean tableHasRows = rs.next();
137
      while (tableHasRows) {
138
           doctypeList.addElement(rs.getString(1));
139
           tableHasRows = rs.next();
140
      }
141
      
142
      pstmt.close();
143

    
144
    } catch (SQLException e) {
145
      throw new SQLException("DBUtil.readDoctypes(). " + e.getMessage());
146
    }
147

    
148
    return formatToXML(doctypeList, "doctype");
149
  }
150

    
151
  /**
152
   * read DTD or Schema file from Metacat's XML catalog system
153
   */
154
  public String readDTDSchema(String doctype)
155
        throws SQLException, MalformedURLException, IOException
156
  {
157
    String systemID = null;
158
    PreparedStatement pstmt;
159
    StringBuffer cbuff = new StringBuffer();
160
    
161
    // get doctype's System ID from db catalog
162
    try {
163
      pstmt = conn.prepareStatement("SELECT system_id " + 
164
                                    "FROM xml_catalog " +
165
                                    "WHERE entry_type in ('DTD','Schema') " +
166
                                    "AND public_id LIKE ?");
167
      pstmt.setString(1, doctype);
168
      pstmt.execute();
169
      ResultSet rs = pstmt.getResultSet();
170
      boolean hasRow = rs.next();
171
      if (hasRow) {
172
        systemID = rs.getString(1);
173
      } else {
174
        throw new SQLException("Non-registered doctype: " + doctype);
175
      }
176
      pstmt.close();
177

    
178
    } catch (SQLException e) {
179
      throw new SQLException("DBUtil.readDTD(). " + e.getMessage());
180
    }
181

    
182
    // read from URL stream as specified by the System ID.
183
    try {
184
      // open a connection to this URL and return an InputStream
185
      // for reading from that connection
186
      InputStream istream = new URL(systemID).openStream();
187
      // create a buffering character-input stream
188
      // that uses a default-sized input buffer
189
      BufferedInputStream in = new BufferedInputStream(istream);
190

    
191
      // read the input and write into the string buffer
192
	    int inputByte;
193
	    while ( (inputByte = in.read()) != -1 ) {
194
        cbuff.append((char)inputByte);
195
	    }
196

    
197
      // the input stream must be closed
198
	    in.close();
199
	    
200
    } catch (MalformedURLException e) {
201
      throw new MalformedURLException
202
      ("DBUtil.readDTD(). " + e.getMessage());
203
    } catch (IOException e) {
204
      throw new IOException
205
      ("DBUtil.readDTD(). " + e.getMessage());
206
    } catch (SecurityException e) {
207
      throw new IOException
208
      ("DBUtil.readDTD(). " + e.getMessage());
209
    }
210
    
211
   return cbuff.toString();
212
  }
213

    
214
  /**
215
   * read Data Guide for a given doctype from db connection in XML format
216
   * select all distinct absolute paths from xml_index table
217
   */
218
  public String readDataGuide( String doctype )
219
        throws SQLException  {
220

    
221
    Vector dataguide = new Vector();
222
    String path;
223
    PreparedStatement pstmt;
224
    
225
    try {
226

    
227
        if ( doctype != null ) {
228
            pstmt = conn.prepareStatement("SELECT distinct path, nodeid " + 
229
                                          "FROM xml_index " +
230
                                          "WHERE path LIKE '/%' " + 
231
                                          "AND doctype LIKE ? " +
232
                                          "ORDER BY nodeid");
233
            pstmt.setString(1, doctype);
234
        } else {
235
            pstmt = conn.prepareStatement("SELECT distinct path, doctype, nodeid " + 
236
                                          "FROM xml_index " +
237
                                          "WHERE path LIKE '/%' " + 
238
                                          "ORDER BY doctype, nodeid");
239
        }
240

    
241
        pstmt.execute();
242
        ResultSet rs = pstmt.getResultSet();
243
        boolean tableHasRows = rs.next();
244
        while (tableHasRows) {
245
            path = rs.getString(1);
246
            if ( dataguide.indexOf(path) == -1 ) {
247
                dataguide.addElement(path);
248
            }    
249
            tableHasRows = rs.next();
250
        }
251
      
252
        pstmt.close();
253

    
254
    } catch (SQLException e) {
255
      throw new SQLException("DBUtil.readDataGuide(). " + e.getMessage());
256
    }
257

    
258
    return formatToXML(dataguide);
259
  }
260

    
261
  /**
262
   * format the DataGuide ResultSet to XML
263
   */
264
  private String formatToXML(Vector resultset) {
265
  
266
    String currPath = null;
267
    String currElement = null;
268
    String prevElement = null;
269
    StringBuffer result = new StringBuffer();
270
    Enumeration rs = resultset.elements(); 
271
    Stack st = new Stack();
272
    int i = 0;
273

    
274
    result.append("<?xml version=\"1.0\"?>\n");
275
    result.append("<resultset>\n"); 
276
    
277
    while (rs.hasMoreElements()) {
278
        currPath = (String)rs.nextElement();
279
        while ( !In(prevElement, currPath) ) {
280
            currElement = (String)st.pop();
281
            result.append(pad(" ",i--) + "</" + currElement + ">\n");
282
            if ( st.empty() ) 
283
                prevElement = null;
284
            else    
285
                prevElement = (String)st.peek();
286
        }    
287
        currElement = getElementFromPath(currPath);
288
        st.push(currElement);
289
        result.append(pad(" ",++i) + "<" + currElement + ">\n");
290
        prevElement = currElement;
291
    }
292
    while ( !st.empty() ) {
293
        prevElement = (String)st.pop();
294
        result.append(pad(" ",i--) + "</" + prevElement + ">\n");
295
    }    
296
    result.append("</resultset>\n"); 
297

    
298
    return result.toString();
299
  }
300

    
301
  /**
302
   * check if element is in path like /elem1/elem2/elemn3
303
   */
304
  private boolean In(String element, String path) {
305
    
306
    if ( element == null ) return true;
307
    return ( path.indexOf(element) != -1 );
308
  }
309

    
310
  /**
311
   * get last element from path like /elem1/elem2/elemn3
312
   */
313
  private String getElementFromPath(String path) {
314
    
315
    return ( path.substring(path.lastIndexOf("/")+1) );
316
  }
317

    
318
  /**
319
   * repeates the str n-times
320
   */
321
  private String pad(String str, int n) {
322
    
323
    String result = "";
324
    for ( int i = 0; i < n; i++ )
325
        result = result.concat(str);
326
        
327
    return result;    
328
  }
329

    
330
  /**
331
   * format the ResultSet to XML
332
   */
333
  private String formatToXML(Vector resultset, String tag) {
334
  
335
    String val = null;
336
    StringBuffer result = new StringBuffer();
337
    Enumeration rs = resultset.elements(); 
338

    
339
    result.append("<?xml version=\"1.0\"?>\n");
340
    result.append("<resultset>\n"); 
341
    while (rs.hasMoreElements()) {
342
        val = (String)rs.nextElement();
343
        result.append("   <" + tag + ">" + val + "</" + tag + ">\n");
344
    }
345
    result.append("</resultset>\n"); 
346
    
347
    return result.toString();
348
  }
349

    
350
  /**
351
   * get the lastest Accession Number from a particular scope
352
   */
353
  public String getMaxDocid(String scope)
354
        throws SQLException  {
355

    
356
    String accnum = null;
357
    String sep = MetaCatUtil.getOption("accNumSeparator");
358

    
359
    try {
360

    
361
      PreparedStatement pstmt =
362
        conn.prepareStatement(
363
            "SELECT docid, rev, acc FROM " +
364
            "( " +
365
            "SELECT docid, rev, acc FROM " +
366
                "(" +
367
                "SELECT docid, rev, " + 
368
                "SUBSTR(docid, INSTR(docid, '" + sep + "', 1)+1)+0 acc " +
369
                "FROM xml_documents " +
370
                "WHERE docid LIKE ? " +
371
                "ORDER BY acc DESC " +
372
                ") " +
373
            "WHERE rownum = 1 " +
374
            "UNION " + 
375
            "SELECT docid, rev, acc FROM " +
376
                "(" +
377
                "SELECT docid, rev, " + 
378
                "SUBSTR(docid, INSTR(docid, '" + sep + "', 1)+1)+0 acc " +
379
                "FROM xml_revisions " +
380
                "WHERE docid LIKE ? " +
381
                "ORDER BY acc DESC " +
382
                ") " +
383
            "WHERE rownum = 1 " +
384
            ") " +
385
            "ORDER BY acc DESC"
386
            );
387

    
388
      pstmt.setString(1,scope + sep + "%");
389
      pstmt.setString(2,scope + sep + "%");
390
      pstmt.execute();
391
      ResultSet rs = pstmt.getResultSet();
392
      boolean tableHasRows = rs.next(); 
393
      // 0, 1 or 2 possible num of rows
394
      // get the first one which is the max accnum
395
      if (tableHasRows) {
396
        accnum = rs.getString(1) + sep + rs.getString(2);
397
        //tableHasRows = rs.next();
398
      }
399
      
400
      pstmt.close();
401

    
402
    } catch (SQLException e) {
403
      throw new SQLException("DBUtil.getMaxDocid(). " + e.getMessage());
404
    }
405

    
406
    return accnum;
407
  }
408

    
409
}
(19-19/40)