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
  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 699 bojilova
        System.err.println(
70
        "USAGE: java DBUtil <-dt | -ds [doctype] | -dg [doctype]>");
71 301 bojilova
        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 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 301 bojilova
          } else {
95 699 bojilova
            System.err.println(
96
            "USAGE: java DBUtil <-dt | -ds [doctype] | -dg [doctype]>");
97 301 bojilova
          }
98
99
        } catch (Exception e) {
100 699 bojilova
          //System.err.println("error in DBUtil.main");
101
          //System.err.println(e.getMessage());
102 301 bojilova
          e.printStackTrace(System.err);
103
        }
104
     }
105
  }
106
107
  /**
108
   * Construct an instance of the utility class
109
   */
110
  public DBUtil( Connection conn ) {
111
    this.conn = conn;
112
  }
113
114
  /**
115
   * read all doctypes from db connection in XML format
116
   * select all Public Id from xml_catalog table
117
   */
118
  public String readDoctypes()
119
        throws SQLException  {
120
121
    Vector doctypeList = new Vector();
122
123
    try {
124
125
      PreparedStatement pstmt =
126 413 bojilova
        conn.prepareStatement("SELECT public_id FROM xml_catalog " +
127
                              "WHERE entry_type = 'DTD'");
128 301 bojilova
129
      pstmt.execute();
130
      ResultSet rs = pstmt.getResultSet();
131
      boolean tableHasRows = rs.next();
132
      while (tableHasRows) {
133
           doctypeList.addElement(rs.getString(1));
134
           tableHasRows = rs.next();
135
      }
136
137
      pstmt.close();
138
139
    } catch (SQLException e) {
140 699 bojilova
      throw new SQLException("DBUtil.readDoctypes(). " + e.getMessage());
141 301 bojilova
    }
142
143
    return formatToXML(doctypeList, "doctype");
144
  }
145
146
  /**
147 699 bojilova
   * read DTD or Schema file from Metacat's XML catalog system
148
   */
149
  public String readDTDSchema(String doctype)
150
        throws SQLException, MalformedURLException, IOException
151
  {
152
    String systemID = null;
153
    PreparedStatement pstmt;
154
    StringBuffer cbuff = new StringBuffer();
155
156
    // get doctype's System ID from db catalog
157
    try {
158
      pstmt = conn.prepareStatement("SELECT system_id " +
159
                                    "FROM xml_catalog " +
160
                                    "WHERE entry_type in ('DTD','Schema') " +
161
                                    "AND public_id LIKE ?");
162
      pstmt.setString(1, doctype);
163
      pstmt.execute();
164
      ResultSet rs = pstmt.getResultSet();
165
      boolean hasRow = rs.next();
166
      if (hasRow) {
167
        systemID = rs.getString(1);
168
      } else {
169
        throw new SQLException("Non-registered doctype: " + doctype);
170
      }
171
      pstmt.close();
172
173
    } catch (SQLException e) {
174
      throw new SQLException("DBUtil.readDTD(). " + e.getMessage());
175
    }
176
177
    // read from URL stream as specified by the System ID.
178
    try {
179
      // open a connection to this URL and return an InputStream
180
      // for reading from that connection
181
      InputStream istream = new URL(systemID).openStream();
182
      // create a buffering character-input stream
183
      // that uses a default-sized input buffer
184
      BufferedInputStream in = new BufferedInputStream(istream);
185
186
      // read the input and write into the string buffer
187
	    int inputByte;
188
	    while ( (inputByte = in.read()) != -1 ) {
189
        cbuff.append((char)inputByte);
190
	    }
191
192
      // the input stream must be closed
193
	    in.close();
194
195
    } catch (MalformedURLException e) {
196
      throw new MalformedURLException
197
      ("DBUtil.readDTD(). " + e.getMessage());
198
    } catch (IOException e) {
199
      throw new IOException
200
      ("DBUtil.readDTD(). " + e.getMessage());
201
    } catch (SecurityException e) {
202
      throw new IOException
203
      ("DBUtil.readDTD(). " + e.getMessage());
204
    }
205
206
   return cbuff.toString();
207
  }
208
209
  /**
210 301 bojilova
   * read Data Guide for a given doctype from db connection in XML format
211
   * select all distinct absolute paths from xml_index table
212
   */
213
  public String readDataGuide( String doctype )
214
        throws SQLException  {
215
216
    Vector dataguide = new Vector();
217
    String path;
218 315 bojilova
    PreparedStatement pstmt;
219
220 301 bojilova
    try {
221
222 315 bojilova
        if ( doctype != null ) {
223
            pstmt = conn.prepareStatement("SELECT distinct path, nodeid " +
224
                                          "FROM xml_index " +
225
                                          "WHERE path LIKE '/%' " +
226
                                          "AND doctype LIKE ? " +
227
                                          "ORDER BY nodeid");
228
            pstmt.setString(1, doctype);
229
        } else {
230 374 bojilova
            pstmt = conn.prepareStatement("SELECT distinct path, doctype, nodeid " +
231 315 bojilova
                                          "FROM xml_index " +
232
                                          "WHERE path LIKE '/%' " +
233 374 bojilova
                                          "ORDER BY doctype, nodeid");
234 315 bojilova
        }
235
236
        pstmt.execute();
237
        ResultSet rs = pstmt.getResultSet();
238
        boolean tableHasRows = rs.next();
239
        while (tableHasRows) {
240
            path = rs.getString(1);
241
            if ( dataguide.indexOf(path) == -1 ) {
242
                dataguide.addElement(path);
243
            }
244
            tableHasRows = rs.next();
245
        }
246 301 bojilova
247 315 bojilova
        pstmt.close();
248 301 bojilova
249
    } catch (SQLException e) {
250 699 bojilova
      throw new SQLException("DBUtil.readDataGuide(). " + e.getMessage());
251 301 bojilova
    }
252
253 374 bojilova
    return formatToXML(dataguide);
254 301 bojilova
  }
255
256
  /**
257 374 bojilova
   * format the DataGuide ResultSet to XML
258
   */
259
  private String formatToXML(Vector resultset) {
260
261
    String currPath = null;
262
    String currElement = null;
263
    String prevElement = null;
264
    StringBuffer result = new StringBuffer();
265
    Enumeration rs = resultset.elements();
266
    Stack st = new Stack();
267
    int i = 0;
268
269
    result.append("<?xml version=\"1.0\"?>\n");
270
    result.append("<resultset>\n");
271
272
    while (rs.hasMoreElements()) {
273
        currPath = (String)rs.nextElement();
274
        while ( !In(prevElement, currPath) ) {
275
            currElement = (String)st.pop();
276
            result.append(pad(" ",i--) + "</" + currElement + ">\n");
277
            if ( st.empty() )
278
                prevElement = null;
279
            else
280
                prevElement = (String)st.peek();
281
        }
282
        currElement = getElementFromPath(currPath);
283
        st.push(currElement);
284
        result.append(pad(" ",++i) + "<" + currElement + ">\n");
285
        prevElement = currElement;
286
    }
287
    while ( !st.empty() ) {
288
        prevElement = (String)st.pop();
289
        result.append(pad(" ",i--) + "</" + prevElement + ">\n");
290
    }
291
    result.append("</resultset>\n");
292
293
    return result.toString();
294
  }
295
296
  /**
297
   * check if element is in path like /elem1/elem2/elemn3
298
   */
299
  private boolean In(String element, String path) {
300
301
    if ( element == null ) return true;
302
    return ( path.indexOf(element) != -1 );
303
  }
304
305
  /**
306
   * get last element from path like /elem1/elem2/elemn3
307
   */
308
  private String getElementFromPath(String path) {
309
310
    return ( path.substring(path.lastIndexOf("/")+1) );
311
  }
312
313
  /**
314
   * repeates the str n-times
315
   */
316
  private String pad(String str, int n) {
317
318
    String result = "";
319
    for ( int i = 0; i < n; i++ )
320
        result = result.concat(str);
321
322
    return result;
323
  }
324
325
  /**
326 301 bojilova
   * format the ResultSet to XML
327
   */
328
  private String formatToXML(Vector resultset, String tag) {
329
330
    String val = null;
331
    StringBuffer result = new StringBuffer();
332
    Enumeration rs = resultset.elements();
333
334
    result.append("<?xml version=\"1.0\"?>\n");
335
    result.append("<resultset>\n");
336
    while (rs.hasMoreElements()) {
337
        val = (String)rs.nextElement();
338
        result.append("   <" + tag + ">" + val + "</" + tag + ">\n");
339
    }
340
    result.append("</resultset>\n");
341
342
    return result.toString();
343
  }
344
345
346
}