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