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 691 bojilova
// DOCTITLE attr cleared from the db
726
//  /**
727
//   * Get the document title
728
//   */
729
//  public String getTitle() {
730
//    return doctitle;
731
//  }
732 459 bojilova
733 691 bojilova
// DOCTITLE attr cleared from the db
734
//  /**
735
//   * Set the document title
736
//   *
737
//   * @param title the new title for the document
738
//   */
739
//  public void setTitle( String title ) {
740
//    this.doctitle = title;
741
//    try {
742
//      PreparedStatement pstmt;
743
//      pstmt = conn.prepareStatement(
744
//            "UPDATE xml_documents " +
745
//            " SET doctitle = ? " +
746
//            "WHERE docid = ?");
747
//
748
//      // Bind the values to the query
749
//      pstmt.setString(1, doctitle);
750
//      pstmt.setString(2, docid);
751
//
752
//      // Do the insertion
753
//      pstmt.execute();
754
//      pstmt.close();
755
//    } catch (SQLException e) {
756
//      System.out.println("Error in DocumentImpl.setTitle: " + e.getMessage());
757
//    }
758
//  }
759 465 berkley
760 459 bojilova
  /**
761 407 jones
   * Write an XML file to the database, given a filename
762 393 jones
   *
763 408 jones
   * @param conn the JDBC connection to the database
764 407 jones
   * @param filename the filename to be loaded into the database
765 680 bojilova
   * @param pub flag for public "read" access on document
766
   * @param dtdfilename the dtd to be uploaded on server's file system
767 407 jones
   * @param action the action to be performed (INSERT OR UPDATE)
768
   * @param docid the docid to use for the INSERT OR UPDATE
769 680 bojilova
   * @param user the user that owns the document
770
   * @param group the group to which user belongs
771 393 jones
   */
772 598 bojilova
  public static String write(Connection conn,String filename,
773 680 bojilova
                             String pub, String dtdfilename,
774 598 bojilova
                             String action, String docid, String user,
775
                             String group )
776 457 bojilova
                throws Exception {
777 598 bojilova
778
    Reader dtd = null;
779
    if ( dtdfilename != null ) {
780
      dtd = new FileReader(new File(dtdfilename).toString());
781
    }
782 555 bojilova
    return write ( conn, new FileReader(new File(filename).toString()),
783 695 bojilova
                   pub, dtd, action, docid, user, group, false);
784 407 jones
  }
785 598 bojilova
786 680 bojilova
  public static String write(Connection conn,Reader xml,String pub,Reader dtd,
787 598 bojilova
                             String action, String docid, String user,
788 695 bojilova
                             String group, boolean validate)
789 549 berkley
                throws Exception {
790 695 bojilova
    return write(conn,xml,pub,dtd,action,docid,user,group,1,false,validate);
791 598 bojilova
  }
792
793 680 bojilova
  public static String write(Connection conn, Reader xml, String pub,
794 598 bojilova
                             String action, String docid, String user,
795
                             String group )
796
                throws Exception {
797 571 berkley
    if(action.equals("UPDATE"))
798
    {//if the document is being updated then use the servercode from the
799
     //originally inserted document.
800
      DocumentImpl doc = new DocumentImpl(conn, docid);
801
      int servercode = doc.getServerlocation();
802 680 bojilova
      return write(conn, xml, pub, action, docid, user, group, servercode);
803 571 berkley
    }
804
    else
805
    {//if the file is being inserted then the servercode is always 1
806 680 bojilova
      return write(conn, xml, pub, action, docid, user, group, 1);
807 571 berkley
    }
808 549 berkley
  }
809
810 559 berkley
  public static String write( Connection conn, Reader xml,
811
                              String action, String docid, String user,
812
                              String group, int serverCode )
813 598 bojilova
                throws Exception
814 559 berkley
  {
815 598 bojilova
    return write(conn,xml,null,action,docid,user,group,serverCode);
816 559 berkley
  }
817
818 680 bojilova
  public static String write( Connection conn, Reader xml, String pub,
819 577 berkley
                              String action, String docid, String user,
820 598 bojilova
                              String group, int serverCode)
821
                throws Exception
822 577 berkley
  {
823 695 bojilova
    return write(conn,xml,pub,null,action,docid,user,group,
824
                 serverCode,false,false);
825 577 berkley
  }
826
827 680 bojilova
  public static String write( Connection conn, Reader xml, String pub,
828 600 bojilova
                              String action, String docid, String user,
829
                              String group, int serverCode, boolean override)
830
                throws Exception
831
  {
832 695 bojilova
    return write(conn,xml,pub,null,action,docid,user,group,
833
                 serverCode,override,false);
834 600 bojilova
  }
835
836 407 jones
  /**
837
   * Write an XML file to the database, given a Reader
838
   *
839 408 jones
   * @param conn the JDBC connection to the database
840 407 jones
   * @param xml the xml stream to be loaded into the database
841 680 bojilova
   * @param pub flag for public "read" access on xml document
842
   * @param dtd the dtd to be uploaded on server's file system
843 407 jones
   * @param action the action to be performed (INSERT OR UPDATE)
844
   * @param docid the docid to use for the INSERT OR UPDATE
845 580 berkley
   * @param user the user that owns the document
846
   * @param group the group to which user belongs
847
   * @param serverCode the serverid from xml_replication on which this document
848
   *        resides.
849
   * @param override flag to stop insert replication checking.
850
   *        if override = true then a document not belonging to the local server
851
   *        will not be checked upon update for a file lock.
852
   *        if override = false then a document not from this server, upon
853
   *        update will be locked and version checked.
854 407 jones
   */
855 559 berkley
856 680 bojilova
  public static String write( Connection conn,Reader xml,String pub,Reader dtd,
857 555 bojilova
                              String action, String docid, String user,
858 695 bojilova
                              String group, int serverCode, boolean override,
859
                              boolean validate)
860 598 bojilova
                throws Exception
861 573 berkley
  {
862 645 bojilova
    //MOVED DOWN IN RelationHandler obj before write of relations
863
    //if(action.equals("UPDATE"))
864
    //{
865
    //  RelationHandler.deleteRelations(docid);
866
    //}
867 634 berkley
868 628 berkley
    int updaterev;
869 573 berkley
    MetaCatUtil util = new MetaCatUtil();
870 571 berkley
        // Determine if the docid is OK for INSERT or UPDATE
871
    AccessionNumber ac = new AccessionNumber(conn);
872
    String newdocid = ac.generate(docid, action);
873 569 berkley
874 590 berkley
    MetaCatUtil.debugMessage("action: " + action + " servercode: " +
875
                             serverCode + " override: " + override);
876 580 berkley
877 577 berkley
    if((serverCode != 1 && action.equals("UPDATE")) && !override)
878 559 berkley
    { //if this document being written is not a resident of this server then
879
      //we need to try to get a lock from it's resident server.  If the
880
      //resident server will not give a lock then we send the user a message
881
      //saying that he/she needs to download a new copy of the file and
882
      //merge the differences manually.
883 567 berkley
      int istreamInt;
884 561 berkley
      char istreamChar;
885
      DocumentImpl newdoc = new DocumentImpl(conn, docid);
886 628 berkley
      updaterev = newdoc.getRev();
887 561 berkley
      String server = MetacatReplication.getServer(serverCode);
888 584 berkley
      MetacatReplication.replLog("attempting to lock " + docid);
889 580 berkley
      URL u = new URL("http://" + server + "?action=getlock&updaterev=" +
890
                      updaterev + "&docid=" + docid);
891 574 berkley
      System.out.println("sending message: " + u.toString());
892 569 berkley
      String serverResStr = MetacatReplication.getURLContent(u);
893 567 berkley
      String openingtag = serverResStr.substring(0, serverResStr.indexOf(">")+1);
894 571 berkley
895 561 berkley
      if(openingtag.equals("<lockgranted>"))
896
      {//the lock was granted go ahead with the insert
897 571 berkley
        try
898
        {
899 584 berkley
          MetacatReplication.replLog("lock granted for " + docid + " from " +
900
                                      server);
901 695 bojilova
          XMLReader parser = initializeParser(conn, action, newdocid, validate,
902 680 bojilova
                                              user, group, pub, serverCode, dtd);
903 571 berkley
          conn.setAutoCommit(false);
904 695 bojilova
          parser.parse(new InputSource(xml));
905 571 berkley
          conn.commit();
906
          conn.setAutoCommit(true);
907
        }
908
        catch (Exception e)
909
        {
910
          conn.rollback();
911
          conn.setAutoCommit(true);
912
          throw e;
913
        }
914
915
        //after inserting the document locally, tell the document's home server
916
        //to come get a copy from here.
917 582 berkley
        ForceReplicationHandler frh = new ForceReplicationHandler(docid);
918 590 berkley
919 571 berkley
        if ( (docid != null) && !(newdocid.equals(docid)) )
920
        {
921
          return new String("New document ID generated:" + newdocid);
922
        }
923
        else
924
        {
925
          return newdocid;
926
        }
927 561 berkley
      }
928
      else if(openingtag.equals("<filelocked>"))
929
      {//the file is currently locked by another user
930
       //notify our user to wait a few minutes, check out a new copy and try
931
       //again.
932 584 berkley
        //System.out.println("file locked");
933
        MetacatReplication.replLog("lock denied for " + docid + " on " +
934
                                   server + " reason: file already locked");
935 571 berkley
        throw new Exception("The file specified is already locked by another " +
936
                            "user.  Please wait 30 seconds, checkout the " +
937
                            "newer document, merge your changes and try " +
938
                            "again.");
939 561 berkley
      }
940
      else if(openingtag.equals("<outdatedfile>"))
941
      {//our file is outdated.  notify our user to check out a new copy of the
942
       //file and merge his version with the new version.
943 584 berkley
        //System.out.println("outdated file");
944
        MetacatReplication.replLog("lock denied for " + docid + " on " +
945
                                    server + " reason: local file outdated");
946 571 berkley
        throw new Exception("The file you are trying to update is an outdated" +
947
                            " version.  Please checkout the newest document, " +
948
                            "merge your changes and try again.");
949 561 berkley
      }
950 559 berkley
    }
951 571 berkley
952 425 bojilova
    if ( action.equals("UPDATE") ) {
953 441 bojilova
      // check for 'write' permission for 'user' to update this document
954 628 berkley
955 570 bojilova
      if ( !hasPermission(conn, user, group, docid) ) {
956 441 bojilova
        throw new Exception("User " + user +
957
              " does not have permission to update XML Document #" + docid);
958 425 bojilova
      }
959
    }
960
961 571 berkley
    try
962 638 bojilova
    {
963 695 bojilova
      XMLReader parser = initializeParser(conn, action, newdocid, validate,
964 680 bojilova
                                          user, group, pub, serverCode, dtd);
965 555 bojilova
      conn.setAutoCommit(false);
966
      parser.parse(new InputSource(xml));
967
      conn.commit();
968
      conn.setAutoCommit(true);
969 571 berkley
    }
970
    catch (Exception e)
971
    {
972 555 bojilova
      conn.rollback();
973
      conn.setAutoCommit(true);
974
      throw e;
975
    }
976 577 berkley
977
    //force replicate out the new document to each server in our server list.
978
    if(serverCode == 1)
979 582 berkley
    { //start the thread to replicate this new document out to the other servers
980
      ForceReplicationHandler frh = new ForceReplicationHandler(newdocid,
981
                                                                action);
982 577 berkley
    }
983 457 bojilova
984 571 berkley
    if ( (docid != null) && !(newdocid.equals(docid)) )
985
    {
986 555 bojilova
      return new String("New document ID generated:" + newdocid);
987 571 berkley
    }
988
    else
989
    {
990 555 bojilova
      return newdocid;
991
    }
992 393 jones
  }
993 396 jones
994 407 jones
  /**
995
   * Delete an XML file from the database (actually, just make it a revision
996
   * in the xml_revisions table)
997
   *
998
   * @param docid the ID of the document to be deleted from the database
999
   */
1000 425 bojilova
  public static void delete( Connection conn, String docid,
1001
                                 String user, String group )
1002 457 bojilova
                throws Exception {
1003 628 berkley
    DocumentIdentifier id = new DocumentIdentifier(docid);
1004
    docid = id.getSiteCode() + id.getSeparator() + id.getUniqueId();
1005
1006 441 bojilova
    // Determine if the docid is OK for DELETE
1007 459 bojilova
    AccessionNumber ac = new AccessionNumber(conn);
1008 421 bojilova
    String newdocid = ac.generate(docid, "DELETE");
1009 396 jones
1010 441 bojilova
    // check for 'write' permission for 'user' to delete this document
1011 570 bojilova
    if ( !hasPermission(conn, user, group, docid) ) {
1012 441 bojilova
      throw new Exception("User " + user +
1013
              " does not have permission to delete XML Document #" + docid);
1014 425 bojilova
    }
1015
1016 407 jones
    conn.setAutoCommit(false);
1017
    // Copy the record to the xml_revisions table
1018 425 bojilova
    DocumentImpl.archiveDocRevision( conn, docid, user );
1019 396 jones
1020 407 jones
    // Now delete it from the xml_documents table
1021 628 berkley
1022 407 jones
    Statement stmt = conn.createStatement();
1023 425 bojilova
    stmt.execute("DELETE FROM xml_index WHERE docid = '" + docid + "'");
1024
    stmt.execute("DELETE FROM xml_documents WHERE docid = '" + docid + "'");
1025 688 bojilova
    //stmt.execute("DELETE FROM xml_access WHERE docid = '" + docid + "'");
1026 645 bojilova
    stmt.execute("DELETE FROM xml_access WHERE accessfileid = '" + docid + "'");
1027
    stmt.execute("DELETE FROM xml_relation WHERE docid = '" + docid + "'");
1028 407 jones
    stmt.close();
1029
    conn.commit();
1030 457 bojilova
    conn.setAutoCommit(true);
1031 634 berkley
    //IF this is a package document:
1032
    //delete all of the relations that this document created.
1033
    //if the deleted document is a package document its relations should
1034
    //no longer be active if it has been deleted from the system.
1035 645 bojilova
1036
//    MOVED UP IN THE TRANSACTION
1037
//    RelationHandler.deleteRelations(docid);
1038 407 jones
  }
1039 638 bojilova
1040 570 bojilova
  /**
1041
    * Check for "WRITE" permission on @docid for @user and/or @group
1042
    * from DB connection
1043
    */
1044
  private static boolean hasPermission( Connection conn, String user,
1045
                                        String group, String docid)
1046
                         throws SQLException
1047
  {
1048 441 bojilova
    // b' of the command line invocation
1049
    if ( (user == null) && (group == null) ) {
1050
      return true;
1051
    }
1052
1053 570 bojilova
    // Check for WRITE permission on @docid for @user and/or @group
1054
    AccessControlList aclobj = new AccessControlList(conn);
1055
    boolean hasPermission = aclobj.hasPermission("WRITE",user,docid);
1056
    if ( !hasPermission && group != null ) {
1057
      hasPermission = aclobj.hasPermission("WRITE",group,docid);
1058 425 bojilova
    }
1059 570 bojilova
1060
    return hasPermission;
1061 425 bojilova
  }
1062
1063 396 jones
  /**
1064 407 jones
   * Set up the parser handlers for writing the document to the database
1065
   */
1066 598 bojilova
  private static XMLReader initializeParser(Connection conn, String action,
1067 695 bojilova
                                   String docid, boolean validate,
1068
                                   String user, String group, String pub,
1069
                                   int serverCode, Reader dtd)
1070 598 bojilova
                           throws Exception
1071
  {
1072 407 jones
    XMLReader parser = null;
1073
    //
1074
    // Set up the SAX document handlers for parsing
1075
    //
1076
    try {
1077 645 bojilova
      ContentHandler chandler = new DBSAXHandler(conn, action, docid,
1078 680 bojilova
                                                 user, group, pub, serverCode);
1079 645 bojilova
      EntityResolver eresolver= new DBEntityResolver(conn,
1080
                                                 (DBSAXHandler)chandler, dtd);
1081 598 bojilova
      DTDHandler dtdhandler   = new DBDTDHandler(conn);
1082 407 jones
1083
      // Get an instance of the parser
1084 408 jones
      MetaCatUtil util = new MetaCatUtil();
1085
      String parserName = util.getOption("saxparser");
1086 407 jones
      parser = XMLReaderFactory.createXMLReader(parserName);
1087
1088 660 bojilova
      // Turn on validation
1089 695 bojilova
      parser.setFeature("http://xml.org/sax/features/validation", validate);
1090 660 bojilova
      // Turn off Including all external parameter entities
1091
      // (the external DTD subset also)
1092
      // Doesn't work well, probably the feature name is not correct
1093
      // parser.setFeature(
1094
      //  "http://xml.org/sax/features/external-parameter-entities", false);
1095 407 jones
1096
      // Set Handlers in the parser
1097
      parser.setProperty("http://xml.org/sax/properties/declaration-handler",
1098
                         chandler);
1099
      parser.setProperty("http://xml.org/sax/properties/lexical-handler",
1100
                         chandler);
1101
      parser.setContentHandler((ContentHandler)chandler);
1102 598 bojilova
      parser.setEntityResolver((EntityResolver)eresolver);
1103 407 jones
      parser.setDTDHandler((DTDHandler)dtdhandler);
1104
      parser.setErrorHandler((ErrorHandler)chandler);
1105
1106
    } catch (Exception e) {
1107 457 bojilova
      throw e;
1108 407 jones
    }
1109
1110
    return parser;
1111
  }
1112
1113 459 bojilova
  /** Save a document entry in the xml_revisions table */
1114
  private static void archiveDocRevision(Connection conn, String docid,
1115 552 berkley
                                         String user)
1116
                                         throws SQLException {
1117 459 bojilova
    // create a record in xml_revisions table
1118
    // for that document as selected from xml_documents
1119
    PreparedStatement pstmt = conn.prepareStatement(
1120
      "INSERT INTO xml_revisions " +
1121 691 bojilova
        "(revisionid, docid, rootnodeid, docname, doctype, " +
1122 697 bojilova
        "user_owner, user_updated, date_created, date_updated, " +
1123
        "server_location, rev, public_access, catalog_id) " +
1124 691 bojilova
      "SELECT null, ?, rootnodeid, docname, doctype, " +
1125 697 bojilova
        "user_owner, ?, sysdate, sysdate, server_location, rev, " +
1126
        "public_access, catalog_id " +
1127 459 bojilova
      "FROM xml_documents " +
1128
      "WHERE docid = ?");
1129
    // Bind the values to the query and execute it
1130
    pstmt.setString(1, docid);
1131
    pstmt.setString(2, user);
1132
    pstmt.setString(3, docid);
1133
    pstmt.execute();
1134
    pstmt.close();
1135
1136
  }
1137
1138 407 jones
  /**
1139
   * the main routine used to test the DBWriter utility.
1140
   * <p>
1141
   * Usage: java DocumentImpl <-f filename -a action -d docid>
1142
   *
1143
   * @param filename the filename to be loaded into the database
1144
   * @param action the action to perform (READ, INSERT, UPDATE, DELETE)
1145
   * @param docid the id of the document to process
1146
   */
1147
  static public void main(String[] args) {
1148
1149
    try {
1150 555 bojilova
      String filename    = null;
1151 598 bojilova
      String dtdfilename = null;
1152 555 bojilova
      String action      = null;
1153
      String docid       = null;
1154 429 jones
      boolean showRuntime = false;
1155
      boolean useOldReadAlgorithm = false;
1156 407 jones
1157 408 jones
      // Parse the command line arguments
1158 407 jones
      for ( int i=0 ; i < args.length; ++i ) {
1159
        if ( args[i].equals( "-f" ) ) {
1160
          filename =  args[++i];
1161 598 bojilova
        } else if ( args[i].equals( "-r" ) ) {
1162
          dtdfilename =  args[++i];
1163 407 jones
        } else if ( args[i].equals( "-a" ) ) {
1164
          action =  args[++i];
1165
        } else if ( args[i].equals( "-d" ) ) {
1166
          docid =  args[++i];
1167 429 jones
        } else if ( args[i].equals( "-t" ) ) {
1168
          showRuntime = true;
1169
        } else if ( args[i].equals( "-old" ) ) {
1170
          useOldReadAlgorithm = true;
1171 407 jones
        } else {
1172
          System.err.println
1173
            ( "   args[" +i+ "] '" +args[i]+ "' ignored." );
1174
        }
1175
      }
1176
1177 408 jones
      // Check if the required arguments are provided
1178 407 jones
      boolean argsAreValid = false;
1179
      if (action != null) {
1180
        if (action.equals("INSERT")) {
1181
          if (filename != null) {
1182
            argsAreValid = true;
1183
          }
1184
        } else if (action.equals("UPDATE")) {
1185
          if ((filename != null) && (docid != null)) {
1186
            argsAreValid = true;
1187
          }
1188
        } else if (action.equals("DELETE")) {
1189
          if (docid != null) {
1190
            argsAreValid = true;
1191
          }
1192
        } else if (action.equals("READ")) {
1193
          if (docid != null) {
1194
            argsAreValid = true;
1195
          }
1196
        }
1197
      }
1198
1199 408 jones
      // Print usage message if the arguments are not valid
1200 407 jones
      if (!argsAreValid) {
1201
        System.err.println("Wrong number of arguments!!!");
1202
        System.err.println(
1203 598 bojilova
          "USAGE: java DocumentImpl [-t] <-a INSERT> [-d docid] <-f filename> "+
1204 680 bojilova
          "[-r dtdfilename]");
1205 407 jones
        System.err.println(
1206 598 bojilova
          "   OR: java DocumentImpl [-t] <-a UPDATE -d docid -f filename> " +
1207 680 bojilova
          "[-r dtdfilename]");
1208 407 jones
        System.err.println(
1209 429 jones
          "   OR: java DocumentImpl [-t] <-a DELETE -d docid>");
1210 407 jones
        System.err.println(
1211 429 jones
          "   OR: java DocumentImpl [-t] [-old] <-a READ -d docid>");
1212 407 jones
        return;
1213
      }
1214 429 jones
1215
      // Time the request if asked for
1216
      double startTime = System.currentTimeMillis();
1217
1218 407 jones
      // Open a connection to the database
1219
      MetaCatUtil util = new MetaCatUtil();
1220
      Connection dbconn = util.openDBConnection();
1221
1222 463 berkley
      double connTime = System.currentTimeMillis();
1223 408 jones
      // Execute the action requested (READ, INSERT, UPDATE, DELETE)
1224 407 jones
      if (action.equals("READ")) {
1225
          DocumentImpl xmldoc = new DocumentImpl( dbconn, docid );
1226 429 jones
          if (useOldReadAlgorithm) {
1227
            System.out.println(xmldoc.readUsingSlowAlgorithm());
1228
          } else {
1229
            xmldoc.toXml(new PrintWriter(System.out));
1230
          }
1231 408 jones
      } else if (action.equals("DELETE")) {
1232 425 bojilova
        DocumentImpl.delete(dbconn, docid, null, null);
1233 408 jones
        System.out.println("Document deleted: " + docid);
1234 407 jones
      } else {
1235 680 bojilova
        String newdocid = DocumentImpl.write(dbconn, filename, null,
1236 598 bojilova
                                             dtdfilename, action, docid,
1237
                                             null, null);
1238 408 jones
        if ((docid != null) && (!docid.equals(newdocid))) {
1239
          if (action.equals("INSERT")) {
1240
            System.out.println("New document ID generated!!! ");
1241
          } else if (action.equals("UPDATE")) {
1242
            System.out.println("ERROR: Couldn't update document!!! ");
1243 407 jones
          }
1244 408 jones
        } else if ((docid == null) && (action.equals("UPDATE"))) {
1245
          System.out.println("ERROR: Couldn't update document!!! ");
1246 407 jones
        }
1247 408 jones
        System.out.println("Document processing finished for: " + filename
1248
              + " (" + newdocid + ")");
1249 407 jones
      }
1250
1251 429 jones
      double stopTime = System.currentTimeMillis();
1252 463 berkley
      double dbOpenTime = (connTime - startTime)/1000;
1253
      double insertTime = (stopTime - connTime)/1000;
1254 429 jones
      double executionTime = (stopTime - startTime)/1000;
1255
      if (showRuntime) {
1256 463 berkley
        System.out.println("\n\nTotal Execution time was: " +
1257
                           executionTime + " seconds.");
1258
        System.out.println("Time to open DB connection was: " + dbOpenTime +
1259
                           " seconds.");
1260
        System.out.println("Time to insert document was: " + insertTime +
1261
                           " seconds.");
1262 429 jones
      }
1263 463 berkley
      dbconn.close();
1264 407 jones
    } catch (McdbException me) {
1265
      me.toXml(new PrintWriter(System.err));
1266
    } catch (AccessionNumberException ane) {
1267
      System.out.println("ERROR: Couldn't delete document!!! ");
1268
      System.out.println(ane.getMessage());
1269
    } catch (Exception e) {
1270
      System.err.println("EXCEPTION HANDLING REQUIRED");
1271
      System.err.println(e.getMessage());
1272
      e.printStackTrace(System.err);
1273
    }
1274
  }
1275 393 jones
}