Project

General

Profile

1 393 jones
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that represents an XML document
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Matt Jones
7
 *    Release: @release@
8
 *
9
 *   '$Author$'
10
 *     '$Date$'
11
 * '$Revision$'
12 669 jones
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 393 jones
 */
27
28
package edu.ucsb.nceas.metacat;
29
30
import java.sql.*;
31 429 jones
import java.io.File;
32
import java.io.FileReader;
33
import java.io.IOException;
34 393 jones
import java.io.PrintWriter;
35 429 jones
import java.io.Reader;
36
import java.io.StringWriter;
37
import java.io.Writer;
38 561 berkley
import java.io.InputStreamReader;
39 393 jones
40 429 jones
import java.util.Iterator;
41 407 jones
import java.util.Stack;
42 429 jones
import java.util.TreeSet;
43 577 berkley
import java.util.Enumeration;
44 407 jones
45
import org.xml.sax.AttributeList;
46
import org.xml.sax.ContentHandler;
47
import org.xml.sax.DTDHandler;
48
import org.xml.sax.EntityResolver;
49
import org.xml.sax.ErrorHandler;
50
import org.xml.sax.InputSource;
51
import org.xml.sax.XMLReader;
52
import org.xml.sax.SAXException;
53
import org.xml.sax.SAXParseException;
54
import org.xml.sax.helpers.XMLReaderFactory;
55
56 561 berkley
import java.net.URL;
57
58 393 jones
/**
59
 * A class that represents an XML document. It can be created with a simple
60 407 jones
 * document identifier from a database connection.  It also will write an
61
 * XML text document to a database connection using SAX.
62 393 jones
 */
63
public class DocumentImpl {
64
65 425 bojilova
  static final int ALL = 1;
66
  static final int WRITE = 2;
67
  static final int READ = 4;
68
69 393 jones
  private Connection conn = null;
70
  private String docid = null;
71
  private String docname = null;
72
  private String doctype = null;
73 691 bojilova
// DOCTITLE attr cleared from the db
74
//  private String doctitle = null;
75 465 berkley
  private String createdate = null;
76
  private String updatedate = null;
77 393 jones
  private String system_id = null;
78 561 berkley
  private String userowner = null;
79
  private String userupdated = null;
80 575 berkley
  private int rev;
81 561 berkley
  private int serverlocation;
82 697 bojilova
  private String publicaccess;
83 393 jones
  private long rootnodeid;
84
  private ElementNode rootNode = null;
85 429 jones
  private TreeSet nodeRecordList = null;
86 393 jones
87
  /**
88 396 jones
   * Constructor, creates document from database connection, used
89
   * for reading the document
90 393 jones
   *
91
   * @param conn the database connection from which to read the document
92
   * @param docid the identifier of the document to be created
93
   */
94
  public DocumentImpl(Connection conn, String docid) throws McdbException
95
  {
96 465 berkley
    try {
97 393 jones
      this.conn = conn;
98
      this.docid = docid;
99 622 berkley
100
      DocumentIdentifier id = new DocumentIdentifier(docid);
101
102 393 jones
103
      // Look up the document information
104
      getDocumentInfo(docid);
105
106
      // Download all of the document nodes using a single SQL query
107 429 jones
      // The sort order of the records is determined by the NodeComparator
108
      // class, and needs to represent a depth-first traversal for the
109
      // toXml() method to work properly
110
      nodeRecordList = getNodeRecordList(rootnodeid);
111 393 jones
112
    } catch (McdbException ex) {
113
      throw ex;
114
    } catch (Throwable t) {
115 675 berkley
      throw new McdbException("Error reading document from " +
116
                              "DocumentImpl.DocumentImpl: " + docid);
117 393 jones
    }
118
  }
119
120 396 jones
  /**
121 415 jones
   * Construct a new document instance, writing the contents to the database.
122
   * This method is called from DBSAXHandler because we need to know the
123
   * root element name for documents without a DOCTYPE before creating it.
124 396 jones
   *
125
   * @param conn the JDBC Connection to which all information is written
126
   * @param rootnodeid - sequence id of the root node in the document
127
   * @param docname - the name of DTD, i.e. the name immediately following
128
   *        the DOCTYPE keyword ( should be the root element name ) or
129
   *        the root element name if no DOCTYPE declaration provided
130
   *        (Oracle's and IBM parsers are not aware if it is not the
131
   *        root element name)
132
   * @param doctype - Public ID of the DTD, i.e. the name immediately
133
   *                  following the PUBLIC keyword in DOCTYPE declaration or
134
   *                  the docname if no Public ID provided or
135
   *                  null if no DOCTYPE declaration provided
136 680 bojilova
   * @param docid the docid to use for the INSERT OR UPDATE
137
   * @param action the action to be performed (INSERT OR UPDATE)
138
   * @param user the user that owns the document
139
   * @param pub flag for public "read" access on document
140
   * @param serverCode the serverid from xml_replication on which this document
141
   *        resides.
142 396 jones
   *
143
   */
144
  public DocumentImpl(Connection conn, long rootnodeid, String docname,
145 549 berkley
                      String doctype, String docid, String action, String user,
146 697 bojilova
                      String pub, String catalogid, int serverCode)
147 549 berkley
                      throws SQLException, Exception
148
  {
149
    this.conn = conn;
150
    this.rootnodeid = rootnodeid;
151
    this.docname = docname;
152
    this.doctype = doctype;
153
    this.docid = docid;
154 697 bojilova
    writeDocumentToDB(action, user, pub, catalogid, serverCode);
155 549 berkley
  }
156
157 680 bojilova
// NOT USED ANY MORE
158
//  public DocumentImpl(Connection conn, long rootnodeid, String docname,
159
//                      String doctype, String docid, String action, String user)
160
//                      throws SQLException, Exception
161
//  {
162
//    this.conn = conn;
163
//    this.rootnodeid = rootnodeid;
164
//    this.docname = docname;
165
//    this.doctype = doctype;
166
//    this.docid = docid;
167
//    writeDocumentToDB(action, user);
168
//  }
169 407 jones
170 393 jones
  /**
171
   * get the document name
172
   */
173
  public String getDocname() {
174
    return docname;
175
  }
176
177
  /**
178
   * get the document type (which is the PublicID)
179
   */
180
  public String getDoctype() {
181
    return doctype;
182
  }
183
184
  /**
185
   * get the system identifier
186
   */
187
  public String getSystemID() {
188
    return system_id;
189
  }
190
191
  /**
192
   * get the root node identifier
193
   */
194
  public long getRootNodeID() {
195
    return rootnodeid;
196
  }
197 465 berkley
198
  /**
199
   * get the creation date
200
   */
201
  public String getCreateDate() {
202
    return createdate;
203
  }
204
205
  /**
206
   * get the update date
207
   */
208
  public String getUpdateDate() {
209
    return updatedate;
210
  }
211 393 jones
212 396 jones
  /**
213
   * Get the document identifier (docid)
214
   */
215
  public String getDocID() {
216
    return docid;
217
  }
218 465 berkley
219 691 bojilova
// DOCTITLE attr cleared from the db
220
//  /**
221
//   *get the document title
222
//   */
223
//  public String getDocTitle() {
224
//    return doctitle;
225
//  }
226 561 berkley
227
  public String getUserowner() {
228
    return userowner;
229
  }
230
231
  public String getUserupdated() {
232
    return userupdated;
233
  }
234
235
  public int getServerlocation() {
236
    return serverlocation;
237
  }
238
239 697 bojilova
  public String getPublicaccess() {
240 561 berkley
    return publicaccess;
241
  }
242 575 berkley
243
  public int getRev() {
244
    return rev;
245
  }
246 396 jones
247 393 jones
  /**
248 429 jones
   * Print a string representation of the XML document
249 393 jones
   */
250
  public String toString()
251
  {
252 429 jones
    StringWriter docwriter = new StringWriter();
253
    this.toXml(docwriter);
254
    String document = docwriter.toString();
255
    return document;
256
  }
257
258
  /**
259
   * Get a text representation of the XML document as a string
260
   * This older algorithm uses a recursive tree of Objects to represent the
261
   * nodes of the tree.  Each object is passed the data for the document
262
   * and searches all of the document data to find its children nodes and
263
   * recursively build.  Thus, because each node reads the whole document,
264
   * this algorithm is extremely slow for larger documents, and the time
265
   * to completion is O(N^N) wrt the number of nodes.  See toXml() for a
266
   * better algorithm.
267
   */
268
  public String readUsingSlowAlgorithm()
269
  {
270 393 jones
    StringBuffer doc = new StringBuffer();
271
272 429 jones
    // Create the elements from the downloaded data in the TreeSet
273
    rootNode = new ElementNode(nodeRecordList, rootnodeid);
274
275 393 jones
    // Append the resulting document to the StringBuffer and return it
276
    doc.append("<?xml version=\"1.0\"?>\n");
277
278
    if (docname != null) {
279
      if ((doctype != null) && (system_id != null)) {
280
        doc.append("<!DOCTYPE " + docname + " PUBLIC \"" + doctype +
281
                   "\" \"" + system_id + "\">\n");
282
      } else {
283
        doc.append("<!DOCTYPE " + docname + ">\n");
284
      }
285
    }
286
    doc.append(rootNode.toString());
287
288
    return (doc.toString());
289
  }
290
291
  /**
292 429 jones
   * Print a text representation of the XML document to a Writer
293
   *
294
   * @param pw the Writer to which we print the document
295
   */
296
  public void toXml(Writer pw)
297
  {
298
    PrintWriter out = null;
299
    if (pw instanceof PrintWriter) {
300
      out = (PrintWriter)pw;
301
    } else {
302
      out = new PrintWriter(pw);
303
    }
304
305
    MetaCatUtil util = new MetaCatUtil();
306
307
    Stack openElements = new Stack();
308
    boolean atRootElement = true;
309
    boolean previousNodeWasElement = false;
310
311
    // Step through all of the node records we were given
312
    Iterator it = nodeRecordList.iterator();
313
    while (it.hasNext()) {
314
      NodeRecord currentNode = (NodeRecord)it.next();
315
      //util.debugMessage("[Got Node ID: " + currentNode.nodeid +
316
                          //" (" + currentNode.parentnodeid +
317
                          //", " + currentNode.nodeindex +
318
                          //", " + currentNode.nodetype +
319
                          //", " + currentNode.nodename +
320
                          //", " + currentNode.nodedata + ")]");
321
322
      // Print the end tag for the previous node if needed
323
      //
324
      // This is determined by inspecting the parent nodeid for the
325
      // currentNode.  If it is the same as the nodeid of the last element
326
      // that was pushed onto the stack, then we are still in that previous
327
      // parent element, and we do nothing.  However, if it differs, then we
328
      // have returned to a level above the previous parent, so we go into
329
      // a loop and pop off nodes and print out their end tags until we get
330
      // the node on the stack to match the currentNode parentnodeid
331
      //
332
      // So, this of course means that we rely on the list of elements
333
      // having been sorted in a depth first traversal of the nodes, which
334
      // is handled by the NodeComparator class used by the TreeSet
335
      if (!atRootElement) {
336
        NodeRecord currentElement = (NodeRecord)openElements.peek();
337
        if ( currentNode.parentnodeid != currentElement.nodeid ) {
338
          while ( currentNode.parentnodeid != currentElement.nodeid ) {
339
            currentElement = (NodeRecord)openElements.pop();
340
            util.debugMessage("\n POPPED: " + currentElement.nodename);
341 451 bojilova
            if (previousNodeWasElement) {
342
              out.print(">");
343
              previousNodeWasElement = false;
344
            }
345 429 jones
            out.print("</" + currentElement.nodename + ">" );
346
            currentElement = (NodeRecord)openElements.peek();
347
          }
348
        }
349
      }
350
351
      // Handle the DOCUMENT node
352
      if (currentNode.nodetype.equals("DOCUMENT")) {
353
        out.println("<?xml version=\"1.0\"?>");
354
355
        if (docname != null) {
356
          if ((doctype != null) && (system_id != null)) {
357
            out.println("<!DOCTYPE " + docname + " PUBLIC \"" + doctype +
358
                       "\" \"" + system_id + "\">");
359
          } else {
360
            out.println("<!DOCTYPE " + docname + ">");
361
          }
362
        }
363
364
      // Handle the ELEMENT nodes
365
      } else if (currentNode.nodetype.equals("ELEMENT")) {
366
        if (atRootElement) {
367
          atRootElement = false;
368
        } else {
369
          if (previousNodeWasElement) {
370
            out.print(">");
371
          }
372
        }
373
        openElements.push(currentNode);
374
        util.debugMessage("\n PUSHED: " + currentNode.nodename);
375
        previousNodeWasElement = true;
376
        out.print("<" + currentNode.nodename);
377
378
      // Handle the ATTRIBUTE nodes
379
      } else if (currentNode.nodetype.equals("ATTRIBUTE")) {
380
        out.print(" " + currentNode.nodename + "=\""
381
                 + currentNode.nodedata + "\"");
382
      } else if (currentNode.nodetype.equals("TEXT")) {
383
        if (previousNodeWasElement) {
384
          out.print(">");
385
        }
386
        out.print(currentNode.nodedata);
387
        previousNodeWasElement = false;
388
389
      // Handle the COMMENT nodes
390
      } else if (currentNode.nodetype.equals("COMMENT")) {
391
        if (previousNodeWasElement) {
392
          out.print(">");
393
        }
394
        out.print("<!--" + currentNode.nodedata + "-->");
395
        previousNodeWasElement = false;
396
397
      // Handle the PI nodes
398
      } else if (currentNode.nodetype.equals("PI")) {
399
        if (previousNodeWasElement) {
400
          out.print(">");
401
        }
402
        out.print("<?" + currentNode.nodename + " " +
403
                        currentNode.nodedata + "?>");
404
        previousNodeWasElement = false;
405
406
      // Handle any other node type (do nothing)
407
      } else {
408
        // Any other types of nodes are not handled.
409
        // Probably should throw an exception here to indicate this
410
      }
411
      out.flush();
412
    }
413
414
    // Print the final end tag for the root element
415 686 berkley
    while(!openElements.empty())
416
    {
417
      NodeRecord currentElement = (NodeRecord)openElements.pop();
418
      util.debugMessage("\n POPPED: " + currentElement.nodename);
419
      out.print("</" + currentElement.nodename + ">" );
420
    }
421 429 jones
    out.flush();
422
  }
423 622 berkley
424
  private boolean isRevisionOnly(DocumentIdentifier docid) throws Exception
425
  {
426
    //System.out.println("inRevisionOnly");
427
    PreparedStatement pstmt;
428
    String rev = docid.getRev();
429
    String newid = docid.getIdentifier();
430
    pstmt = conn.prepareStatement("select rev from xml_documents " +
431
                                  "where docid like '" + newid + "'");
432
    pstmt.execute();
433
    ResultSet rs = pstmt.getResultSet();
434
    boolean tablehasrows = rs.next();
435
    if(rev.equals("newest") || rev.equals("all"))
436
    {
437
      return false;
438
    }
439
440
    if(tablehasrows)
441
    {
442
      int r = rs.getInt(1);
443 667 berkley
      pstmt.close();
444 622 berkley
      if(new Integer(rev).intValue() == r)
445
      { //the current revision in in xml_documents
446
        //System.out.println("returning false");
447
        return false;
448
      }
449
      else if(new Integer(rev).intValue() < r)
450
      { //the current revision is in xml_revisions.
451
        //System.out.println("returning true");
452
        return true;
453
      }
454
      else if(new Integer(rev).intValue() > r)
455
      { //error, rev cannot be greater than r
456
        throw new Exception("requested revision cannot be greater than " +
457
                            "the latest revision number.");
458
      }
459
    }
460
    throw new Exception("the requested docid '" + docid.toString() +
461
                        "' does not exist");
462
  }
463 429 jones
464 622 berkley
  private void getDocumentInfo(String docid) throws McdbException,
465
                                                    AccessionNumberException
466
  {
467
    getDocumentInfo(new DocumentIdentifier(docid));
468
  }
469
470 429 jones
  /**
471 393 jones
   * Look up the document type information from the database
472
   *
473
   * @param docid the id of the document to look up
474
   */
475 622 berkley
  private void getDocumentInfo(DocumentIdentifier docid) throws McdbException
476 393 jones
  {
477
    PreparedStatement pstmt;
478 622 berkley
    String table = "xml_documents";
479
480
    try
481
    {
482
      if(isRevisionOnly(docid))
483
      { //pull the document from xml_revisions instead of from xml_documents;
484
        table = "xml_revisions";
485
      }
486
    }
487
    catch(Exception e)
488
    {
489 675 berkley
      System.out.println("error in DocumentImpl.getDocumentInfo: " +
490
                          e.getMessage());
491 622 berkley
    }
492
493
    //deal with the key words here.
494
495
    if(docid.getRev().equals("all"))
496
    {
497
498
    }
499
500 393 jones
    try {
501 622 berkley
      StringBuffer sql = new StringBuffer();
502 691 bojilova
// DOCTITLE attr cleared from the db
503
//      sql.append("SELECT docname, doctype, rootnodeid, doctitle, ");
504
      sql.append("SELECT docname, doctype, rootnodeid, ");
505 697 bojilova
      sql.append("date_created, date_updated, user_owner, user_updated, ");
506
      sql.append("server_location, public_access, rev");
507
      sql.append(" FROM ").append(table);
508 622 berkley
      sql.append(" WHERE docid LIKE '").append(docid.getIdentifier());
509
      sql.append("' and rev like '").append(docid.getRev()).append("'");
510
      //System.out.println(sql.toString());
511 393 jones
      pstmt =
512 622 berkley
        conn.prepareStatement(sql.toString());
513 393 jones
      // Bind the values to the query
514 622 berkley
      //pstmt.setString(1, docid.getIdentifier());
515
      //pstmt.setString(2, docid.getRev());
516 393 jones
517
      pstmt.execute();
518
      ResultSet rs = pstmt.getResultSet();
519
      boolean tableHasRows = rs.next();
520
      if (tableHasRows) {
521 561 berkley
        this.docname        = rs.getString(1);
522
        this.doctype        = rs.getString(2);
523
        this.rootnodeid     = rs.getLong(3);
524 691 bojilova
// DOCTITLE attr cleared from the db
525
//        this.doctitle       = rs.getString(4);
526 692 bojilova
        this.createdate     = rs.getString(4);
527
        this.updatedate     = rs.getString(5);
528
        this.userowner      = rs.getString(6);
529
        this.userupdated    = rs.getString(7);
530
        this.serverlocation = rs.getInt(8);
531 697 bojilova
        this.publicaccess   = rs.getString(9);
532
        this.rev            = rs.getInt(10);
533 393 jones
      }
534
535
      if (this.doctype != null) {
536
        pstmt =
537
          conn.prepareStatement("SELECT system_id " +
538
                                  "FROM xml_catalog " +
539 447 bojilova
                                 "WHERE public_id LIKE ?");
540 393 jones
        // Bind the values to the query
541
        pstmt.setString(1, doctype);
542
543
        pstmt.execute();
544
        rs = pstmt.getResultSet();
545
        tableHasRows = rs.next();
546
        if (tableHasRows) {
547
          this.system_id  = rs.getString(1);
548
        }
549 675 berkley
        //pstmt.close();
550 393 jones
      }
551
    } catch (SQLException e) {
552 675 berkley
      System.out.println("error in DocumentImpl.getDocumentInfo: " +
553
                          e.getMessage());
554 622 berkley
      e.printStackTrace(System.out);
555 675 berkley
      throw new McdbException("Error accessing database connection in " +
556
                              "DocumentImpl.getDocumentInfo: ", e);
557 393 jones
    }
558
559
    if (this.docname == null) {
560
      throw new McdbDocNotFoundException("Document not found: " + docid);
561
    }
562
  }
563
564
  /**
565
   * Look up the node data from the database
566
   *
567 396 jones
   * @param rootnodeid the id of the root node of the node tree to look up
568 393 jones
   */
569 396 jones
  private TreeSet getNodeRecordList(long rootnodeid) throws McdbException
570 393 jones
  {
571
    PreparedStatement pstmt;
572
    TreeSet nodeRecordList = new TreeSet(new NodeComparator());
573
    long nodeid = 0;
574
    long parentnodeid = 0;
575
    long nodeindex = 0;
576
    String nodetype = null;
577
    String nodename = null;
578
    String nodedata = null;
579
580
    try {
581
      pstmt =
582
      conn.prepareStatement("SELECT nodeid,parentnodeid,nodeindex, " +
583
           "nodetype,nodename,"+
584
           "replace(" +
585
           "replace(" +
586
           "replace(nodedata,'&','&amp;') " +
587
           ",'<','&lt;') " +
588
           ",'>','&gt;') " +
589 396 jones
           "FROM xml_nodes WHERE rootnodeid = ?");
590 393 jones
591
      // Bind the values to the query
592 396 jones
      pstmt.setLong(1, rootnodeid);
593 393 jones
594
      pstmt.execute();
595
      ResultSet rs = pstmt.getResultSet();
596
      boolean tableHasRows = rs.next();
597
      while (tableHasRows) {
598
        nodeid = rs.getLong(1);
599
        parentnodeid = rs.getLong(2);
600
        nodeindex = rs.getLong(3);
601
        nodetype = rs.getString(4);
602
        nodename = rs.getString(5);
603
        nodedata = rs.getString(6);
604
605
        // add the data to the node record list hashtable
606
        NodeRecord currentRecord = new NodeRecord(nodeid, parentnodeid,
607
                                   nodeindex, nodetype, nodename, nodedata);
608
        nodeRecordList.add(currentRecord);
609
610
        // Advance to the next node
611
        tableHasRows = rs.next();
612
      }
613
      pstmt.close();
614
615
    } catch (SQLException e) {
616 675 berkley
      throw new McdbException("Error accessing database connection from " +
617
                              "DocumentImpl.getNodeRecordList ", e);
618 393 jones
    }
619
620
    if (nodeRecordList != null) {
621
      return nodeRecordList;
622
    } else {
623
      throw new McdbException("Error getting node data: " + docid);
624
    }
625
  }
626 549 berkley
627 697 bojilova
// NOT USED ANY MORE
628
//  /** creates SQL code and inserts new document into DB connection
629
//   default serverCode of 1*/
630
//  private void writeDocumentToDB(String action, String user)
631
//               throws SQLException, Exception
632
//  {
633
//    writeDocumentToDB(action, user, null, 1);
634
//  }
635 393 jones
636 459 bojilova
 /** creates SQL code and inserts new document into DB connection */
637 680 bojilova
  private void writeDocumentToDB(String action, String user, String pub,
638 697 bojilova
                                 String catalogid, int serverCode)
639 459 bojilova
               throws SQLException, Exception {
640
    try {
641
      PreparedStatement pstmt = null;
642
643
      if (action.equals("INSERT")) {
644
        //AccessionNumber ac = new AccessionNumber();
645
        //this.docid = ac.generate(docid, "INSERT");
646
        pstmt = conn.prepareStatement(
647 697 bojilova
                "INSERT INTO xml_documents " +
648
                "(docid, rootnodeid, docname, doctype, " +
649
                "user_owner, user_updated, date_created, date_updated, " +
650
                "public_access, catalog_id, server_location) " +
651
                "VALUES (?, ?, ?, ?, ?, ?, sysdate, sysdate, ?, ?, ?)");
652 549 berkley
        //note that the server_location is set to 1.
653
        //this means that "localhost" in the xml_replication table must
654
        //always be the first entry!!!!!
655
656 459 bojilova
        // Bind the values to the query
657
        pstmt.setString(1, this.docid);
658
        pstmt.setLong(2, rootnodeid);
659
        pstmt.setString(3, docname);
660
        pstmt.setString(4, doctype);
661
        pstmt.setString(5, user);
662
        pstmt.setString(6, user);
663 680 bojilova
        if ( pub == null ) {
664
          pstmt.setString(7, null);
665 697 bojilova
        } else if ( pub.toUpperCase().equals("YES") || pub.equals("1") ) {
666 680 bojilova
          pstmt.setInt(7, 1);
667 697 bojilova
        } else if ( pub.toUpperCase().equals("NO") || pub.equals("0") ) {
668 680 bojilova
          pstmt.setInt(7, 0);
669
        }
670 697 bojilova
        pstmt.setString(8, catalogid);
671
        pstmt.setInt(9, serverCode);
672 459 bojilova
      } else if (action.equals("UPDATE")) {
673
674
        // Save the old document entry in a backup table
675
        DocumentImpl.archiveDocRevision( conn, docid, user );
676 575 berkley
        DocumentImpl thisdoc = new DocumentImpl(conn, docid);
677
        int thisrev = thisdoc.getRev();
678
        thisrev++;
679 459 bojilova
        // Delete index for the old version of docid
680
        // The new index is inserting on the next calls to DBSAXNode
681
        pstmt = conn.prepareStatement(
682
                "DELETE FROM xml_index WHERE docid='" + this.docid + "'");
683
        pstmt.execute();
684 675 berkley
        //pstmt.close();
685 459 bojilova
686
        // Update the new document to reflect the new node tree
687
        pstmt = conn.prepareStatement(
688
            "UPDATE xml_documents " +
689
            "SET rootnodeid = ?, docname = ?, doctype = ?, " +
690 549 berkley
            "user_updated = ?, date_updated = sysdate, " +
691 697 bojilova
            "server_location = ?, rev = ?, public_access = ?, catalog_id = ? " +
692 680 bojilova
            "WHERE docid LIKE ?");
693 459 bojilova
        // Bind the values to the query
694
        pstmt.setLong(1, rootnodeid);
695
        pstmt.setString(2, docname);
696
        pstmt.setString(3, doctype);
697
        pstmt.setString(4, user);
698 549 berkley
        pstmt.setInt(5, serverCode);
699 575 berkley
        pstmt.setInt(6, thisrev);
700 680 bojilova
        if ( pub == null ) {
701
          pstmt.setString(7, null);
702 697 bojilova
        } else if ( pub.toUpperCase().equals("YES") || pub.equals("1") ) {
703 680 bojilova
          pstmt .setInt(7, 1);
704 697 bojilova
        } else if ( pub.toUpperCase().equals("NO") || pub.equals("0") ) {
705 680 bojilova
          pstmt.setInt(7, 0);
706
        }
707 697 bojilova
        pstmt.setString(8, catalogid);
708
        pstmt.setString(9, this.docid);
709 575 berkley
710 459 bojilova
      } else {
711
        System.err.println("Action not supported: " + action);
712
      }
713
714
      // Do the insertion
715
      pstmt.execute();
716
      pstmt.close();
717
718
    } catch (SQLException sqle) {
719
      throw sqle;
720
    } catch (Exception e) {
721
      throw e;
722
    }
723
  }
724
725
  /**
726 407 jones
   * Write an XML file to the database, given a filename
727 393 jones
   *
728 408 jones
   * @param conn the JDBC connection to the database
729 407 jones
   * @param filename the filename to be loaded into the database
730 680 bojilova
   * @param pub flag for public "read" access on document
731
   * @param dtdfilename the dtd to be uploaded on server's file system
732 407 jones
   * @param action the action to be performed (INSERT OR UPDATE)
733
   * @param docid the docid to use for the INSERT OR UPDATE
734 680 bojilova
   * @param user the user that owns the document
735
   * @param group the group to which user belongs
736 393 jones
   */
737 598 bojilova
  public static String write(Connection conn,String filename,
738 680 bojilova
                             String pub, String dtdfilename,
739 598 bojilova
                             String action, String docid, String user,
740
                             String group )
741 457 bojilova
                throws Exception {
742 598 bojilova
743
    Reader dtd = null;
744
    if ( dtdfilename != null ) {
745
      dtd = new FileReader(new File(dtdfilename).toString());
746
    }
747 555 bojilova
    return write ( conn, new FileReader(new File(filename).toString()),
748 695 bojilova
                   pub, dtd, action, docid, user, group, false);
749 407 jones
  }
750 598 bojilova
751 680 bojilova
  public static String write(Connection conn,Reader xml,String pub,Reader dtd,
752 598 bojilova
                             String action, String docid, String user,
753 695 bojilova
                             String group, boolean validate)
754 549 berkley
                throws Exception {
755 695 bojilova
    return write(conn,xml,pub,dtd,action,docid,user,group,1,false,validate);
756 598 bojilova
  }
757
758 680 bojilova
  public static String write(Connection conn, Reader xml, String pub,
759 598 bojilova
                             String action, String docid, String user,
760
                             String group )
761
                throws Exception {
762 571 berkley
    if(action.equals("UPDATE"))
763
    {//if the document is being updated then use the servercode from the
764
     //originally inserted document.
765
      DocumentImpl doc = new DocumentImpl(conn, docid);
766
      int servercode = doc.getServerlocation();
767 680 bojilova
      return write(conn, xml, pub, action, docid, user, group, servercode);
768 571 berkley
    }
769
    else
770
    {//if the file is being inserted then the servercode is always 1
771 680 bojilova
      return write(conn, xml, pub, action, docid, user, group, 1);
772 571 berkley
    }
773 549 berkley
  }
774
775 559 berkley
  public static String write( Connection conn, Reader xml,
776
                              String action, String docid, String user,
777
                              String group, int serverCode )
778 598 bojilova
                throws Exception
779 559 berkley
  {
780 598 bojilova
    return write(conn,xml,null,action,docid,user,group,serverCode);
781 559 berkley
  }
782
783 680 bojilova
  public static String write( Connection conn, Reader xml, String pub,
784 577 berkley
                              String action, String docid, String user,
785 598 bojilova
                              String group, int serverCode)
786
                throws Exception
787 577 berkley
  {
788 695 bojilova
    return write(conn,xml,pub,null,action,docid,user,group,
789
                 serverCode,false,false);
790 577 berkley
  }
791
792 680 bojilova
  public static String write( Connection conn, Reader xml, String pub,
793 600 bojilova
                              String action, String docid, String user,
794
                              String group, int serverCode, boolean override)
795
                throws Exception
796
  {
797 695 bojilova
    return write(conn,xml,pub,null,action,docid,user,group,
798
                 serverCode,override,false);
799 600 bojilova
  }
800
801 407 jones
  /**
802
   * Write an XML file to the database, given a Reader
803
   *
804 408 jones
   * @param conn the JDBC connection to the database
805 407 jones
   * @param xml the xml stream to be loaded into the database
806 680 bojilova
   * @param pub flag for public "read" access on xml document
807
   * @param dtd the dtd to be uploaded on server's file system
808 734 bojilova
   * @param action the action to be performed (INSERT or UPDATE)
809
   * @param accnum the docid + rev# to use on INSERT or UPDATE
810 580 berkley
   * @param user the user that owns the document
811
   * @param group the group to which user belongs
812
   * @param serverCode the serverid from xml_replication on which this document
813
   *        resides.
814
   * @param override flag to stop insert replication checking.
815
   *        if override = true then a document not belonging to the local server
816
   *        will not be checked upon update for a file lock.
817
   *        if override = false then a document not from this server, upon
818
   *        update will be locked and version checked.
819 407 jones
   */
820 559 berkley
821 680 bojilova
  public static String write( Connection conn,Reader xml,String pub,Reader dtd,
822 734 bojilova
                              String action, String accnum, String user,
823 695 bojilova
                              String group, int serverCode, boolean override,
824
                              boolean validate)
825 598 bojilova
                throws Exception
826 573 berkley
  {
827 734 bojilova
    String rev = "1";
828
    String docid = null;
829
    MetaCatUtil util = new MetaCatUtil();
830
    String sep = util.getOption("accNumSeparator");
831 634 berkley
832 734 bojilova
    if ( accnum != null ) {
833
      // check the correctness of accnum;
834
      // split accnum in docid and rev in order to
835
      // preserve the current implementation of processing and storing,
836
      // but show the whole accnum to the client.
837
      DocumentIdentifier id = new DocumentIdentifier(accnum);
838
      docid = id.getIdentifier();
839
      rev = id.getRev();
840
      sep = id.getSeparator();
841
    }
842
843
    // Determine if the docid,rev are OK for INSERT or UPDATE
844
    // Generate new docid on INSERT, if one is not provided.
845 571 berkley
    AccessionNumber ac = new AccessionNumber(conn);
846 734 bojilova
    docid = ac.generate(docid, rev, action);
847 569 berkley
848 590 berkley
    MetaCatUtil.debugMessage("action: " + action + " servercode: " +
849
                             serverCode + " override: " + override);
850 580 berkley
851 577 berkley
    if((serverCode != 1 && action.equals("UPDATE")) && !override)
852 559 berkley
    { //if this document being written is not a resident of this server then
853
      //we need to try to get a lock from it's resident server.  If the
854
      //resident server will not give a lock then we send the user a message
855
      //saying that he/she needs to download a new copy of the file and
856
      //merge the differences manually.
857 567 berkley
      int istreamInt;
858 561 berkley
      char istreamChar;
859 734 bojilova
      // NOT NEEDED
860
      //DocumentImpl newdoc = new DocumentImpl(conn, docid);
861
      //updaterev = newdoc.getRev();
862
      String updaterev = rev;
863 561 berkley
      String server = MetacatReplication.getServer(serverCode);
864 734 bojilova
      MetacatReplication.replLog("attempting to lock " + accnum);
865 580 berkley
      URL u = new URL("http://" + server + "?action=getlock&updaterev=" +
866
                      updaterev + "&docid=" + docid);
867 574 berkley
      System.out.println("sending message: " + u.toString());
868 569 berkley
      String serverResStr = MetacatReplication.getURLContent(u);
869 567 berkley
      String openingtag = serverResStr.substring(0, serverResStr.indexOf(">")+1);
870 571 berkley
871 561 berkley
      if(openingtag.equals("<lockgranted>"))
872
      {//the lock was granted go ahead with the insert
873 571 berkley
        try
874
        {
875 734 bojilova
          MetacatReplication.replLog("lock granted for " + accnum + " from " +
876 584 berkley
                                      server);
877 734 bojilova
          XMLReader parser = initializeParser(conn, action, docid, validate,
878 680 bojilova
                                              user, group, pub, serverCode, dtd);
879 571 berkley
          conn.setAutoCommit(false);
880 695 bojilova
          parser.parse(new InputSource(xml));
881 571 berkley
          conn.commit();
882
          conn.setAutoCommit(true);
883
        }
884
        catch (Exception e)
885
        {
886
          conn.rollback();
887
          conn.setAutoCommit(true);
888
          throw e;
889
        }
890
891
        //after inserting the document locally, tell the document's home server
892
        //to come get a copy from here.
893 582 berkley
        ForceReplicationHandler frh = new ForceReplicationHandler(docid);
894 590 berkley
895 734 bojilova
        return (docid + sep + rev);
896 561 berkley
      }
897 734 bojilova
898 561 berkley
      else if(openingtag.equals("<filelocked>"))
899
      {//the file is currently locked by another user
900
       //notify our user to wait a few minutes, check out a new copy and try
901
       //again.
902 584 berkley
        //System.out.println("file locked");
903 734 bojilova
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
904 584 berkley
                                   server + " reason: file already locked");
905 571 berkley
        throw new Exception("The file specified is already locked by another " +
906
                            "user.  Please wait 30 seconds, checkout the " +
907
                            "newer document, merge your changes and try " +
908
                            "again.");
909 561 berkley
      }
910
      else if(openingtag.equals("<outdatedfile>"))
911
      {//our file is outdated.  notify our user to check out a new copy of the
912
       //file and merge his version with the new version.
913 584 berkley
        //System.out.println("outdated file");
914 734 bojilova
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
915 584 berkley
                                    server + " reason: local file outdated");
916 571 berkley
        throw new Exception("The file you are trying to update is an outdated" +
917
                            " version.  Please checkout the newest document, " +
918
                            "merge your changes and try again.");
919 561 berkley
      }
920 559 berkley
    }
921 571 berkley
922 425 bojilova
    if ( action.equals("UPDATE") ) {
923 441 bojilova
      // check for 'write' permission for 'user' to update this document
924 628 berkley
925 570 bojilova
      if ( !hasPermission(conn, user, group, docid) ) {
926 441 bojilova
        throw new Exception("User " + user +
927 734 bojilova
              " does not have permission to update XML Document #" + accnum);
928 425 bojilova
      }
929
    }
930
931 571 berkley
    try
932 638 bojilova
    {
933 734 bojilova
      XMLReader parser = initializeParser(conn, action, docid, validate,
934 680 bojilova
                                          user, group, pub, serverCode, dtd);
935 555 bojilova
      conn.setAutoCommit(false);
936
      parser.parse(new InputSource(xml));
937
      conn.commit();
938
      conn.setAutoCommit(true);
939 571 berkley
    }
940
    catch (Exception e)
941
    {
942 555 bojilova
      conn.rollback();
943
      conn.setAutoCommit(true);
944
      throw e;
945
    }
946 577 berkley
947
    //force replicate out the new document to each server in our server list.
948
    if(serverCode == 1)
949 582 berkley
    { //start the thread to replicate this new document out to the other servers
950 734 bojilova
      ForceReplicationHandler frh = new ForceReplicationHandler(docid, action);
951 577 berkley
    }
952 457 bojilova
953 734 bojilova
    return (docid + sep + rev);
954 393 jones
  }
955 396 jones
956 407 jones
  /**
957
   * Delete an XML file from the database (actually, just make it a revision
958
   * in the xml_revisions table)
959
   *
960
   * @param docid the ID of the document to be deleted from the database
961
   */
962 734 bojilova
  public static void delete( Connection conn, String accnum,
963 425 bojilova
                                 String user, String group )
964 734 bojilova
                throws Exception
965
  {
966
    DocumentIdentifier id = new DocumentIdentifier(accnum);
967
    String docid = id.getIdentifier();
968
    String rev = id.getRev();
969 628 berkley
970 734 bojilova
    // Determine if the docid,rev are OK for DELETE
971 459 bojilova
    AccessionNumber ac = new AccessionNumber(conn);
972 734 bojilova
    docid = ac.generate(docid, rev, "DELETE");
973 396 jones
974 441 bojilova
    // check for 'write' permission for 'user' to delete this document
975 570 bojilova
    if ( !hasPermission(conn, user, group, docid) ) {
976 441 bojilova
      throw new Exception("User " + user +
977 734 bojilova
              " does not have permission to delete XML Document #" + accnum);
978 425 bojilova
    }
979
980 407 jones
    conn.setAutoCommit(false);
981
    // Copy the record to the xml_revisions table
982 425 bojilova
    DocumentImpl.archiveDocRevision( conn, docid, user );
983 396 jones
984 407 jones
    // Now delete it from the xml_documents table
985 628 berkley
986 407 jones
    Statement stmt = conn.createStatement();
987 425 bojilova
    stmt.execute("DELETE FROM xml_index WHERE docid = '" + docid + "'");
988
    stmt.execute("DELETE FROM xml_documents WHERE docid = '" + docid + "'");
989 688 bojilova
    //stmt.execute("DELETE FROM xml_access WHERE docid = '" + docid + "'");
990 645 bojilova
    stmt.execute("DELETE FROM xml_access WHERE accessfileid = '" + docid + "'");
991
    stmt.execute("DELETE FROM xml_relation WHERE docid = '" + docid + "'");
992 407 jones
    stmt.close();
993
    conn.commit();
994 457 bojilova
    conn.setAutoCommit(true);
995 634 berkley
    //IF this is a package document:
996
    //delete all of the relations that this document created.
997
    //if the deleted document is a package document its relations should
998
    //no longer be active if it has been deleted from the system.
999 645 bojilova
1000 407 jones
  }
1001 638 bojilova
1002 570 bojilova
  /**
1003
    * Check for "WRITE" permission on @docid for @user and/or @group
1004
    * from DB connection
1005
    */
1006
  private static boolean hasPermission( Connection conn, String user,
1007
                                        String group, String docid)
1008
                         throws SQLException
1009
  {
1010 441 bojilova
    // b' of the command line invocation
1011
    if ( (user == null) && (group == null) ) {
1012
      return true;
1013
    }
1014
1015 570 bojilova
    // Check for WRITE permission on @docid for @user and/or @group
1016
    AccessControlList aclobj = new AccessControlList(conn);
1017
    boolean hasPermission = aclobj.hasPermission("WRITE",user,docid);
1018
    if ( !hasPermission && group != null ) {
1019
      hasPermission = aclobj.hasPermission("WRITE",group,docid);
1020 425 bojilova
    }
1021 570 bojilova
1022
    return hasPermission;
1023 425 bojilova
  }
1024
1025 396 jones
  /**
1026 407 jones
   * Set up the parser handlers for writing the document to the database
1027
   */
1028 598 bojilova
  private static XMLReader initializeParser(Connection conn, String action,
1029 695 bojilova
                                   String docid, boolean validate,
1030
                                   String user, String group, String pub,
1031
                                   int serverCode, Reader dtd)
1032 598 bojilova
                           throws Exception
1033
  {
1034 407 jones
    XMLReader parser = null;
1035
    //
1036
    // Set up the SAX document handlers for parsing
1037
    //
1038
    try {
1039 645 bojilova
      ContentHandler chandler = new DBSAXHandler(conn, action, docid,
1040 680 bojilova
                                                 user, group, pub, serverCode);
1041 645 bojilova
      EntityResolver eresolver= new DBEntityResolver(conn,
1042
                                                 (DBSAXHandler)chandler, dtd);
1043 598 bojilova
      DTDHandler dtdhandler   = new DBDTDHandler(conn);
1044 407 jones
1045
      // Get an instance of the parser
1046 408 jones
      MetaCatUtil util = new MetaCatUtil();
1047
      String parserName = util.getOption("saxparser");
1048 407 jones
      parser = XMLReaderFactory.createXMLReader(parserName);
1049
1050 660 bojilova
      // Turn on validation
1051 695 bojilova
      parser.setFeature("http://xml.org/sax/features/validation", validate);
1052 660 bojilova
      // Turn off Including all external parameter entities
1053
      // (the external DTD subset also)
1054
      // Doesn't work well, probably the feature name is not correct
1055
      // parser.setFeature(
1056
      //  "http://xml.org/sax/features/external-parameter-entities", false);
1057 407 jones
1058
      // Set Handlers in the parser
1059
      parser.setProperty("http://xml.org/sax/properties/declaration-handler",
1060
                         chandler);
1061
      parser.setProperty("http://xml.org/sax/properties/lexical-handler",
1062
                         chandler);
1063
      parser.setContentHandler((ContentHandler)chandler);
1064 598 bojilova
      parser.setEntityResolver((EntityResolver)eresolver);
1065 407 jones
      parser.setDTDHandler((DTDHandler)dtdhandler);
1066
      parser.setErrorHandler((ErrorHandler)chandler);
1067
1068
    } catch (Exception e) {
1069 457 bojilova
      throw e;
1070 407 jones
    }
1071
1072
    return parser;
1073
  }
1074
1075 459 bojilova
  /** Save a document entry in the xml_revisions table */
1076
  private static void archiveDocRevision(Connection conn, String docid,
1077 552 berkley
                                         String user)
1078
                                         throws SQLException {
1079 459 bojilova
    // create a record in xml_revisions table
1080
    // for that document as selected from xml_documents
1081
    PreparedStatement pstmt = conn.prepareStatement(
1082
      "INSERT INTO xml_revisions " +
1083 691 bojilova
        "(revisionid, docid, rootnodeid, docname, doctype, " +
1084 697 bojilova
        "user_owner, user_updated, date_created, date_updated, " +
1085
        "server_location, rev, public_access, catalog_id) " +
1086 691 bojilova
      "SELECT null, ?, rootnodeid, docname, doctype, " +
1087 697 bojilova
        "user_owner, ?, sysdate, sysdate, server_location, rev, " +
1088
        "public_access, catalog_id " +
1089 459 bojilova
      "FROM xml_documents " +
1090
      "WHERE docid = ?");
1091
    // Bind the values to the query and execute it
1092
    pstmt.setString(1, docid);
1093
    pstmt.setString(2, user);
1094
    pstmt.setString(3, docid);
1095
    pstmt.execute();
1096
    pstmt.close();
1097
1098
  }
1099
1100 407 jones
  /**
1101
   * the main routine used to test the DBWriter utility.
1102
   * <p>
1103
   * Usage: java DocumentImpl <-f filename -a action -d docid>
1104
   *
1105
   * @param filename the filename to be loaded into the database
1106
   * @param action the action to perform (READ, INSERT, UPDATE, DELETE)
1107
   * @param docid the id of the document to process
1108
   */
1109
  static public void main(String[] args) {
1110
1111
    try {
1112 555 bojilova
      String filename    = null;
1113 598 bojilova
      String dtdfilename = null;
1114 555 bojilova
      String action      = null;
1115
      String docid       = null;
1116 429 jones
      boolean showRuntime = false;
1117
      boolean useOldReadAlgorithm = false;
1118 407 jones
1119 408 jones
      // Parse the command line arguments
1120 407 jones
      for ( int i=0 ; i < args.length; ++i ) {
1121
        if ( args[i].equals( "-f" ) ) {
1122
          filename =  args[++i];
1123 598 bojilova
        } else if ( args[i].equals( "-r" ) ) {
1124
          dtdfilename =  args[++i];
1125 407 jones
        } else if ( args[i].equals( "-a" ) ) {
1126
          action =  args[++i];
1127
        } else if ( args[i].equals( "-d" ) ) {
1128
          docid =  args[++i];
1129 429 jones
        } else if ( args[i].equals( "-t" ) ) {
1130
          showRuntime = true;
1131
        } else if ( args[i].equals( "-old" ) ) {
1132
          useOldReadAlgorithm = true;
1133 407 jones
        } else {
1134
          System.err.println
1135
            ( "   args[" +i+ "] '" +args[i]+ "' ignored." );
1136
        }
1137
      }
1138
1139 408 jones
      // Check if the required arguments are provided
1140 407 jones
      boolean argsAreValid = false;
1141
      if (action != null) {
1142
        if (action.equals("INSERT")) {
1143
          if (filename != null) {
1144
            argsAreValid = true;
1145
          }
1146
        } else if (action.equals("UPDATE")) {
1147
          if ((filename != null) && (docid != null)) {
1148
            argsAreValid = true;
1149
          }
1150
        } else if (action.equals("DELETE")) {
1151
          if (docid != null) {
1152
            argsAreValid = true;
1153
          }
1154
        } else if (action.equals("READ")) {
1155
          if (docid != null) {
1156
            argsAreValid = true;
1157
          }
1158
        }
1159
      }
1160
1161 408 jones
      // Print usage message if the arguments are not valid
1162 407 jones
      if (!argsAreValid) {
1163
        System.err.println("Wrong number of arguments!!!");
1164
        System.err.println(
1165 598 bojilova
          "USAGE: java DocumentImpl [-t] <-a INSERT> [-d docid] <-f filename> "+
1166 680 bojilova
          "[-r dtdfilename]");
1167 407 jones
        System.err.println(
1168 598 bojilova
          "   OR: java DocumentImpl [-t] <-a UPDATE -d docid -f filename> " +
1169 680 bojilova
          "[-r dtdfilename]");
1170 407 jones
        System.err.println(
1171 429 jones
          "   OR: java DocumentImpl [-t] <-a DELETE -d docid>");
1172 407 jones
        System.err.println(
1173 429 jones
          "   OR: java DocumentImpl [-t] [-old] <-a READ -d docid>");
1174 407 jones
        return;
1175
      }
1176 429 jones
1177
      // Time the request if asked for
1178
      double startTime = System.currentTimeMillis();
1179
1180 407 jones
      // Open a connection to the database
1181
      MetaCatUtil util = new MetaCatUtil();
1182
      Connection dbconn = util.openDBConnection();
1183
1184 463 berkley
      double connTime = System.currentTimeMillis();
1185 408 jones
      // Execute the action requested (READ, INSERT, UPDATE, DELETE)
1186 407 jones
      if (action.equals("READ")) {
1187
          DocumentImpl xmldoc = new DocumentImpl( dbconn, docid );
1188 429 jones
          if (useOldReadAlgorithm) {
1189
            System.out.println(xmldoc.readUsingSlowAlgorithm());
1190
          } else {
1191
            xmldoc.toXml(new PrintWriter(System.out));
1192
          }
1193 408 jones
      } else if (action.equals("DELETE")) {
1194 425 bojilova
        DocumentImpl.delete(dbconn, docid, null, null);
1195 408 jones
        System.out.println("Document deleted: " + docid);
1196 407 jones
      } else {
1197 680 bojilova
        String newdocid = DocumentImpl.write(dbconn, filename, null,
1198 598 bojilova
                                             dtdfilename, action, docid,
1199
                                             null, null);
1200 408 jones
        if ((docid != null) && (!docid.equals(newdocid))) {
1201
          if (action.equals("INSERT")) {
1202
            System.out.println("New document ID generated!!! ");
1203
          } else if (action.equals("UPDATE")) {
1204
            System.out.println("ERROR: Couldn't update document!!! ");
1205 407 jones
          }
1206 408 jones
        } else if ((docid == null) && (action.equals("UPDATE"))) {
1207
          System.out.println("ERROR: Couldn't update document!!! ");
1208 407 jones
        }
1209 408 jones
        System.out.println("Document processing finished for: " + filename
1210
              + " (" + newdocid + ")");
1211 407 jones
      }
1212
1213 429 jones
      double stopTime = System.currentTimeMillis();
1214 463 berkley
      double dbOpenTime = (connTime - startTime)/1000;
1215
      double insertTime = (stopTime - connTime)/1000;
1216 429 jones
      double executionTime = (stopTime - startTime)/1000;
1217
      if (showRuntime) {
1218 463 berkley
        System.out.println("\n\nTotal Execution time was: " +
1219
                           executionTime + " seconds.");
1220
        System.out.println("Time to open DB connection was: " + dbOpenTime +
1221
                           " seconds.");
1222
        System.out.println("Time to insert document was: " + insertTime +
1223
                           " seconds.");
1224 429 jones
      }
1225 463 berkley
      dbconn.close();
1226 407 jones
    } catch (McdbException me) {
1227
      me.toXml(new PrintWriter(System.err));
1228
    } catch (AccessionNumberException ane) {
1229
      System.out.println("ERROR: Couldn't delete document!!! ");
1230
      System.out.println(ane.getMessage());
1231
    } catch (Exception e) {
1232
      System.err.println("EXCEPTION HANDLING REQUIRED");
1233
      System.err.println(e.getMessage());
1234
      e.printStackTrace(System.err);
1235
    }
1236
  }
1237 393 jones
}