Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that reads in an XML text document and
4
 *             write its contents to a database connection using SAX
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Matt Jones
8
 *
9
 *   '$Author: jones $'
10
 *     '$Date: 2000-06-26 21:31:07 -0700 (Mon, 26 Jun 2000) $'
11
 * '$Revision: 204 $'
12
 */
13

    
14
package edu.ucsb.nceas.metacat;
15

    
16
import java.io.*;
17
import java.sql.*;
18
import java.util.Stack;
19

    
20
import org.xml.sax.AttributeList;
21
import org.xml.sax.ContentHandler;
22
import org.xml.sax.DTDHandler;
23
import org.xml.sax.EntityResolver;
24
import org.xml.sax.ErrorHandler;
25
import org.xml.sax.InputSource;
26
import org.xml.sax.XMLReader;
27
import org.xml.sax.SAXException;
28
import org.xml.sax.SAXParseException;
29
import org.xml.sax.helpers.XMLReaderFactory;
30

    
31
/**
32
 * A Class that reads in an XML text document and
33
 * write its contents to a database connection using SAX
34
 */
35
public class DBWriter {
36

    
37
  private Connection	conn = null;
38
  private String parserName = null;
39

    
40
  /**
41
   * the main routine used to test the DBWriter utility.
42
   * <p>
43
   * Usage: java DBWriter <-f filename -a action -d docid>
44
   *
45
   * @param filename the filename to be loaded into the database
46
   */
47
  static public void main(String[] args) {
48
     
49
    try {
50
      String filename = null;
51
      String action   = null;
52
      String docid    = null;
53

    
54
      for ( int i=0 ; i < args.length; ++i ) {
55
        if ( args[i].equals( "-f" ) ) {
56
          filename =  args[++i];
57
        } else if ( args[i].equals( "-a" ) ) {
58
          action =  args[++i];
59
        } else if ( args[i].equals( "-d" ) ) {
60
          docid =  args[++i];
61
        } else {
62
          System.err.println
63
            ( "   args[" +i+ "] '" +args[i]+ "' ignored." );
64
        }
65
      }
66
      
67
      boolean argsAreValid = false;
68
      if (action != null) {
69
        if (action.equals("INSERT")) {
70
          if (filename != null) {
71
            argsAreValid = true;
72
          } 
73
        } else if (action.equals("UPDATE")) {
74
          if ((filename != null) && (docid != null)) {
75
            argsAreValid = true;
76
          } 
77
        } else if (action.equals("DELETE")) {
78
          if (docid != null) {
79
            argsAreValid = true;
80
          } 
81
        } 
82
      } 
83

    
84
      if (!argsAreValid) {
85
        System.err.println("Wrong number of arguments!!!");
86
        System.err.println(
87
              "USAGE: java DBWriter <-f filename -a action -d docid>");
88
        return;
89
      }
90
 
91
      // Open a connection to the database
92
      MetaCatUtil   util = new MetaCatUtil();
93
      Connection dbconn = util.openDBConnection();
94

    
95
      DBWriter dbw = new DBWriter(dbconn, util.getOption("saxparser"));
96
      if (action.equals("DELETE")) {
97
        dbw.delete(docid);
98
        System.out.println("Document deleted: " + docid);
99
      } else {
100
        String newdocid = dbw.write(filename, action, docid);
101
        if ((docid != null) && (!docid.equals(newdocid))) {
102
          if (action.equals("INSERT")) {
103
            System.out.println("New document ID generated!!! ");
104
          } else if (action.equals("UPDATE")) {
105
            System.out.println("ERROR: Couldn't update document!!! ");
106
          }
107
        } else if ((docid == null) && (action.equals("UPDATE"))) {
108
            System.out.println("ERROR: Couldn't update document!!! ");
109
        }
110
        System.out.println("Document processing finished for: " + filename
111
              + " (" + newdocid + ")");
112
      }
113

    
114
    } catch (AccessionNumberException ane) {
115
      System.out.println("ERROR: Couldn't delete document!!! ");
116
      System.out.println(ane.getMessage());
117
    } catch (Exception e) {
118
      System.err.println("EXCEPTION HANDLING REQUIRED");
119
      System.err.println(e.getMessage());
120
      e.printStackTrace(System.err);
121
    }
122
  }
123
  
124
  /**
125
   * construct a new instance of the class to write an XML file to the database
126
   *
127
   * @param conn the database connection to which to write the XML file
128
   * @param parserName the name of a SAX2 compliant parser class
129
   */
130
  public DBWriter(Connection conn, String parserName) {
131
    this.conn = conn;
132
    this.parserName = parserName;
133
  }
134

    
135
  /**
136
   * Insert XML stream to the database
137
   *
138
   * @param xml the xml stream to be loaded into the database
139
   */
140
  public String write( Reader xml, String action, String docid )
141
                throws Exception, IOException, SQLException, 
142
                       ClassNotFoundException, SAXException, SAXParseException {
143
    try {
144
        XMLReader parser = initializeParser(action, docid);
145
        conn.setAutoCommit(false);
146
        parser.parse(new InputSource(xml));
147
        conn.commit();
148
        conn.setAutoCommit(true);
149
        return docid;
150
      } catch (SAXParseException e) {
151
        conn.rollback();
152
        throw e;
153
      } catch (SAXException e) {
154

    
155
        // If its a problem with the accession number its ok, just the 
156
        // accession number was regenerated
157
        AccessionNumberGeneratedException ang = null;
158
        try {
159
          Exception embedded = e.getException();
160
          if ((embedded != null) && 
161
              (embedded instanceof AccessionNumberGeneratedException)) {
162
            ang = (AccessionNumberGeneratedException)e.getException();
163
          }
164
        } catch (ClassCastException cce) {
165
          // Do nothing and just fall through to the ang != null test
166
        }
167
        if (ang != null) {
168
          conn.commit();
169
          conn.setAutoCommit(true);
170
          return (ang.getMessage());
171
        } else {
172
          conn.rollback();
173
          throw e;
174
        }
175
      } catch (Exception e) {
176
        conn.rollback();
177
        throw e;
178
      }
179
  }
180

    
181
  /**
182
   * Insert an XML file to the database
183
   *
184
   * @param filename the filename to be loaded into the database
185
   */
186
  public String write( String filename, String action, String docid )
187
                throws Exception, IOException, SQLException, 
188
                       ClassNotFoundException, SAXException, SAXParseException {
189
     return write(new FileReader(new File(filename).toString()), action, docid);
190
  }
191
  
192
  private XMLReader initializeParser(String action, String docid) {
193
    XMLReader parser = null;
194
    //
195
    // Set up the SAX document handlers for parsing
196
    //
197
    try {
198
      ContentHandler chandler   = new DBSAXHandler(conn, action, docid);
199
      EntityResolver dbresolver = new DBEntityResolver(conn, 
200
                                      (DBSAXHandler)chandler);
201
      DTDHandler dtdhandler     = new DBDTDHandler(conn);
202

    
203
      // Get an instance of the parser
204
      parser = XMLReaderFactory.createXMLReader(parserName);
205

    
206
      // Turn off validation
207
      parser.setFeature("http://xml.org/sax/features/validation", false);
208
      
209
      // Set Handlers in the parser
210
      parser.setProperty("http://xml.org/sax/properties/declaration-handler",
211
                         chandler);
212
      parser.setProperty("http://xml.org/sax/properties/lexical-handler",
213
                         chandler);
214
      parser.setContentHandler(chandler);
215
      parser.setEntityResolver(dbresolver);
216
      parser.setDTDHandler(dtdhandler);
217
      parser.setErrorHandler((ErrorHandler)chandler);
218

    
219
    } catch (Exception e) {
220
       System.err.println(e.toString());
221
    }
222

    
223
    return parser;
224
  }
225

    
226
  /**
227
   * Delete an XML file from the database (actually, just make it a revision
228
   * in the xml_revisions table)
229
   *
230
   * @param docid the ID of the document to be deleted from the database
231
   */
232
  public void delete( String docid )
233
                  throws IOException, SQLException, 
234
                         ClassNotFoundException, AccessionNumberException {
235

    
236
    String newdocid = AccessionNumber.generate(docid, "DELETE");
237

    
238
    conn.setAutoCommit(false);
239
    // Copy the record to the xml_revisions table
240
    DBSAXDocument document = new DBSAXDocument(conn);
241
    document.saveDocument( docid );
242

    
243
    // Now delete it from the xml_documents table
244
    Statement stmt = conn.createStatement();
245
    stmt.execute("DELETE FROM xml_documents WHERE docid LIKE '" + docid + "'");
246
    stmt.close();
247
    conn.commit();
248
  }
249
}
250

    
251
/**
252
 * '$Log$
253
 * 'Revision 1.21  2000/06/26 10:35:05  jones
254
 * 'Merged in substantial changes to DBWriter and associated classes and to
255
 * 'the MetaCatServlet in order to accomodate the new UPDATE and DELETE
256
 * 'functions.  The command line tools and the parameters for the
257
 * 'servlet have changed substantially.
258
 * '
259
 * 'Revision 1.20.2.7  2000/06/26 10:18:06  jones
260
 * 'Partial fix for MetaCatServlet INSERT?UPDATE bug.  Only will work on
261
 * 'the first call to the servlet.  Subsequent calls fail.  Seems to be
262
 * 'related to exception handling.  Multiple successive DELETE actions
263
 * 'work fine.
264
 * '
265
 * 'Revision 1.20.2.6  2000/06/26 08:38:02  jones
266
 * 'Added DELETE feature to DBWriter.  Now takes an action "DELETE" and a
267
 * 'docid and will move the record from the xml_documents table to the
268
 * 'xml_revisions table.
269
 * 'Modified option parsing to support option symbols on command line.
270
 * '
271
 * 'Revision 1.20.2.5  2000/06/26 02:02:20  jones
272
 * 'Continued fixing problems with exception handling that deals
273
 * 'with INSERT and UPDATE actions and the docid passed to DBWriter
274
 * '
275
 * 'Revision 1.20.2.4  2000/06/26 00:51:06  jones
276
 * 'If docid passed to DBWriter.write() is not unique, classes now generate
277
 * 'an AccessionNumberException containing the new docid generated as a
278
 * 'replacement.  The docid is then extracted from the exception and
279
 * 'returned to the calling application for user feedback or client processing.
280
 * '
281
 * 'Revision 1.20.2.3  2000/06/25 23:38:16  jones
282
 * 'Added RCSfile keyword
283
 * '
284
 * 'Revision 1.20.2.2  2000/06/25 23:34:18  jones
285
 * 'Changed documentation formatting, added log entries at bottom of source files
286
 * ''
287
 */
(15-15/20)