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 1029 tao
import java.io.*;
40 798 jones
import java.text.SimpleDateFormat;
41
42
import java.util.Date;
43 1432 tao
import java.util.Hashtable;
44 429 jones
import java.util.Iterator;
45 407 jones
import java.util.Stack;
46 429 jones
import java.util.TreeSet;
47 1432 tao
import java.util.Vector;
48 577 berkley
import java.util.Enumeration;
49 407 jones
50
import org.xml.sax.AttributeList;
51
import org.xml.sax.ContentHandler;
52
import org.xml.sax.DTDHandler;
53
import org.xml.sax.EntityResolver;
54
import org.xml.sax.ErrorHandler;
55
import org.xml.sax.InputSource;
56
import org.xml.sax.XMLReader;
57
import org.xml.sax.SAXException;
58
import org.xml.sax.SAXParseException;
59
import org.xml.sax.helpers.XMLReaderFactory;
60
61 561 berkley
import java.net.URL;
62
63 777 bojilova
import edu.ucsb.nceas.dbadapter.AbstractDatabase;
64 747 bojilova
65 393 jones
/**
66
 * A class that represents an XML document. It can be created with a simple
67 407 jones
 * document identifier from a database connection.  It also will write an
68
 * XML text document to a database connection using SAX.
69 393 jones
 */
70
public class DocumentImpl {
71
72 1407 tao
   /* Constants */
73 1441 tao
   public static final String SCHEMA                 = "Schema";
74
   public static final String DTD                    = "DTD";
75 1407 tao
   public static final String EML2                   = "eml2";
76 1383 tao
   public static final String EXTERNALSCHEMALOCATIONPROPERTY =
77
              "http://apache.org/xml/properties/schema/external-schemaLocation";
78 1407 tao
   /*public static final String EXTERNALSCHEMALOCATION =
79 1390 tao
     "eml://ecoinformatics.org/eml-2.0.0 http://dev.nceas.ucsb.edu/tao/schema/eml.xsd"+
80 1407 tao
      " http://www.xml-cml.org/schema/stmml http://dev.nceas.ucsb.edu/tao/schema/stmml.xsd";*/
81 1383 tao
   public static final String DECLARATIONHANDLERPROPERTY =
82
                            "http://xml.org/sax/properties/declaration-handler";
83
   public static final String LEXICALPROPERTY =
84
                             "http://xml.org/sax/properties/lexical-handler";
85
   public static final String VALIDATIONFEATURE =
86
                             "http://xml.org/sax/features/validation";
87
   public static final String SCHEMAVALIDATIONFEATURE =
88
                             "http://apache.org/xml/features/validation/schema";
89
   public static final String NAMESPACEFEATURE =
90
                              "http://xml.org/sax/features/namespaces";
91
   public static final String NAMESPACEPREFIXESFEATURE =
92
                              "http://xml.org/sax/features/namespace-prefixes";
93 1554 tao
   public static final String EMLNAMESPACE =
94 1551 tao
                                         MetaCatUtil.getOption("eml2namespace");
95
                                         // "eml://ecoinformatics.org/eml-2.0.0";
96 1383 tao
97
98 425 bojilova
  static final int ALL = 1;
99
  static final int WRITE = 2;
100
  static final int READ = 4;
101 777 bojilova
  private static final AbstractDatabase dbAdapter = MetaCatUtil.dbAdapter;
102 425 bojilova
103 1217 tao
  private DBConnection connection = null;
104 393 jones
  private String docid = null;
105 956 tao
  private String updatedVersion=null;
106 393 jones
  private String docname = null;
107
  private String doctype = null;
108 1441 tao
  private String validateType = null; //base on dtd or schema
109 691 bojilova
// DOCTITLE attr cleared from the db
110
//  private String doctitle = null;
111 465 berkley
  private String createdate = null;
112
  private String updatedate = null;
113 393 jones
  private String system_id = null;
114 561 berkley
  private String userowner = null;
115
  private String userupdated = null;
116 575 berkley
  private int rev;
117 561 berkley
  private int serverlocation;
118 1059 tao
  private String docHomeServer;
119 697 bojilova
  private String publicaccess;
120 393 jones
  private long rootnodeid;
121
  private ElementNode rootNode = null;
122 429 jones
  private TreeSet nodeRecordList = null;
123 1292 tao
  //private static
124
  //ReplicationServerList serverList = new ReplicationServerList();
125 790 bojilova
126
  /**
127 800 jones
   * Constructor used to create a document and read the document information
128
   * from the database.  If readNodes is false, then the node data is not
129
   * read at this time, but is deferred until it is needed (such as when a
130
   * call to toXml() is made).
131 790 bojilova
   *
132
   * @param conn the database connection from which to read the document
133 800 jones
   * @param docid the identifier of the document to be created
134
   * @param readNodes flag indicating whether the xmlnodes should be read
135 790 bojilova
   */
136 1217 tao
  public DocumentImpl(String docid, boolean readNodes)
137 802 bojilova
         throws McdbException
138 790 bojilova
  {
139 801 jones
    try {
140 1217 tao
      //this.conn = conn;
141 801 jones
      this.docid = docid;
142
143
      // Look up the document information
144
      getDocumentInfo(docid);
145 1217 tao
146 801 jones
      if (readNodes) {
147 800 jones
        // Download all of the document nodes using a single SQL query
148
        // The sort order of the records is determined by the NodeComparator
149
        // class, and needs to represent a depth-first traversal for the
150
        // toXml() method to work properly
151
        nodeRecordList = getNodeRecordList(rootnodeid);
152 1217 tao
153 801 jones
      }
154 800 jones
155 801 jones
    } catch (McdbException ex) {
156
      throw ex;
157
    } catch (Throwable t) {
158
      throw new McdbException("Error reading document from " +
159
                              "DocumentImpl.DocumentImpl: " + docid);
160 800 jones
    }
161 790 bojilova
  }
162 393 jones
163
  /**
164 396 jones
   * Constructor, creates document from database connection, used
165
   * for reading the document
166 393 jones
   *
167
   * @param conn the database connection from which to read the document
168
   * @param docid the identifier of the document to be created
169
   */
170 1217 tao
  public DocumentImpl(String docid) throws McdbException
171 393 jones
  {
172 1217 tao
    this(docid, true);
173 393 jones
  }
174
175 1441 tao
176 549 berkley
177 956 tao
  /**
178
   * Construct a new document instance, writing the contents to the database.
179
   * This method is called from DBSAXHandler because we need to know the
180
   * root element name for documents without a DOCTYPE before creating it.
181
   *
182
   * In this constructor, the docid is without rev. There is a string rev to
183
   * specify the revision user want to upadate. The revion is only need to be
184
   * greater than current one. It is not need to be sequent number just after
185
   * current one. So it is only used in update action
186
   * @param conn the JDBC Connection to which all information is written
187
   * @param rootnodeid - sequence id of the root node in the document
188
   * @param docname - the name of DTD, i.e. the name immediately following
189
   *        the DOCTYPE keyword ( should be the root element name ) or
190
   *        the root element name if no DOCTYPE declaration provided
191
   *        (Oracle's and IBM parsers are not aware if it is not the
192
   *        root element name)
193
   * @param doctype - Public ID of the DTD, i.e. the name immediately
194
   *                  following the PUBLIC keyword in DOCTYPE declaration or
195
   *                  the docname if no Public ID provided or
196
   *                  null if no DOCTYPE declaration provided
197
   * @param docid the docid to use for the UPDATE, no version number
198
   * @param version, need to be update
199
   * @param action the action to be performed (INSERT OR UPDATE)
200
   * @param user the user that owns the document
201
   * @param pub flag for public "read" access on document
202
   * @param serverCode the serverid from xml_replication on which this document
203
   *        resides.
204
   *
205
   */
206 1217 tao
  public DocumentImpl(DBConnection conn, long rootNodeId, String docName,
207 956 tao
                      String docType, String docId, String newRevision,
208
                      String action, String user,
209
                      String pub, String catalogId, int serverCode)
210
                      throws SQLException, Exception
211
  {
212 1217 tao
    this.connection = conn;
213 956 tao
    this.rootnodeid = rootNodeId;
214
    this.docname = docName;
215
    this.doctype = docType;
216
    this.docid = docId;
217
    this.updatedVersion = newRevision;
218
    writeDocumentToDB(action, user, pub, catalogId, serverCode);
219
  }
220
221 798 jones
  /**
222 1026 tao
   * This method will be call in handleUploadRequest in MetacatServlet class
223
   */
224
  public static void registerDocument(
225
                     String docname, String doctype, String accnum, String user)
226
                     throws SQLException, AccessionNumberException, Exception
227
  {
228 1217 tao
229 1063 tao
    try
230
    {
231 1217 tao
       // get server location for this doc
232
      int serverLocation=getServerLocationNumber(accnum);
233 1063 tao
      registerDocument(docname, doctype,accnum, user, serverLocation);
234
    }
235
    catch (Exception e)
236
    {
237
      throw e;
238
    }
239 1217 tao
240 1026 tao
241
  }
242
  /**
243 798 jones
   * Register a document that resides on the filesystem with the database.
244
   * (ie, just an entry in xml_documents, nothing in xml_nodes).
245
   * Creates a reference to a filesystem document (used for non-xml data files).
246 1055 tao
   * This class only be called in MetaCatServerlet.
247 798 jones
   * @param conn the JDBC Connection to which all information is written
248
   * @param docname - the name of DTD, i.e. the name immediately following
249
   *        the DOCTYPE keyword ( should be the root element name ) or
250
   *        the root element name if no DOCTYPE declaration provided
251
   *        (Oracle's and IBM parsers are not aware if it is not the
252
   *        root element name)
253
   * @param doctype - Public ID of the DTD, i.e. the name immediately
254
   *                  following the PUBLIC keyword in DOCTYPE declaration or
255
   *                  the docname if no Public ID provided or
256
   *                  null if no DOCTYPE declaration provided
257
   * @param accnum the accession number to use for the INSERT OR UPDATE, which
258
   *               includes a revision number for this revision of the document
259
   *               (e.g., knb.1.1)
260
   * @param user the user that owns the document
261
   * @param serverCode the serverid from xml_replication on which this document
262
   *        resides.
263
   */
264
  public static void registerDocument(
265
                     String docname, String doctype, String accnum,
266
                     String user, int serverCode)
267
                     throws SQLException, AccessionNumberException, Exception
268
  {
269 1217 tao
    DBConnection dbconn = null;
270
    int serialNumber = -1;
271
    PreparedStatement pstmt = null;
272
    //MetaCatUtil util = new MetaCatUtil();
273 965 tao
    AccessionNumber ac;
274 1755 tao
    String action = null;
275 798 jones
    try {
276 1217 tao
      //dbconn = util.openDBConnection();
277
      //check out DBConnection
278
      dbconn=DBConnectionPool.
279
                    getDBConnection("DocumentImpl.registerDocument");
280
      serialNumber=dbconn.getCheckOutSerialNumber();
281 965 tao
      String docIdWithoutRev=MetaCatUtil.getDocIdFromString(accnum);
282
      int userSpecifyRev=MetaCatUtil.getVersionFromString(accnum);
283 1217 tao
      int revInDataBase=getLatestRevisionNumber(docIdWithoutRev);
284 965 tao
      //revIndataBase=-1, there is no record in xml_documents table
285
      //the data file is a new one, inert it into table
286
      //user specified rev should be great than 0
287
      if (revInDataBase==-1 && userSpecifyRev>0 )
288
      {
289 1217 tao
        ac = new AccessionNumber(accnum, "insert");
290 1755 tao
        action = "insert";
291 965 tao
      }
292
      //rev is greater the last revsion number and revInDataBase isn't -1
293
      // it is a updated data file
294
      else if (userSpecifyRev>revInDataBase && revInDataBase>0)
295
      {
296
297
        //archive the old entry
298 1217 tao
        archiveDocRevision(docIdWithoutRev, user);
299 965 tao
        //delete the old entry in xml_documents
300 1755 tao
        //deleteXMLDocuments(docIdWithoutRev);
301 1217 tao
        ac = new AccessionNumber(accnum, "update");
302 1755 tao
        action = "update";
303 965 tao
      }
304
      //other situation
305
      else
306
      {
307
308
        throw new Exception("Revision number couldn't be "
309
                    +userSpecifyRev);
310
      }
311 798 jones
      String docid = ac.getDocid();
312
      String rev = ac.getRev();
313 1755 tao
      /*SimpleDateFormat formatter = new SimpleDateFormat ("MM/dd/yy HH:mm:ss");
314 798 jones
      Date localtime = new Date();
315
      String dateString = formatter.format(localtime);
316 1755 tao
      String sqlDateString=dbAdapter.toDate(dateString, "MM/DD/YY HH24:MI:SS");*/
317
      String  sqlDateString = dbAdapter.getDateTimeFunction();
318 798 jones
319
      StringBuffer sql = new StringBuffer();
320 1755 tao
      if (action != null && action.equals("insert"))
321
      {
322
        sql.append("insert into xml_documents (docid, docname, doctype, ");
323
        sql.append("user_owner, user_updated, server_location, rev,date_created");
324
        sql.append(", date_updated, public_access) values ('");
325
        sql.append(docid).append("','");
326
        sql.append(docname).append("','");
327
        sql.append(doctype).append("','");
328
        sql.append(user).append("','");
329
        sql.append(user).append("','");
330
        sql.append(serverCode).append("','");
331
        sql.append(rev).append("',");
332
        sql.append(sqlDateString).append(",");
333
        sql.append(sqlDateString).append(",");
334
        sql.append("'0')");
335
      }
336
      else if (action != null && action.equals("update"))
337
      {
338
        sql.append("update xml_documents set docname ='");
339
        sql.append(docname).append("', ");
340
        sql.append("user_updated='");
341
        sql.append(user).append("', ");
342
        sql.append("server_location='");
343
        sql.append(serverCode).append("',");
344
        sql.append("rev='");
345
        sql.append(rev).append("',");
346
        sql.append("date_updated=");
347
        sql.append(sqlDateString);
348
        sql.append(" where docid='");
349
        sql.append(docid).append("'");
350
      }
351 1217 tao
      pstmt = dbconn.prepareStatement(sql.toString());
352 798 jones
      pstmt.execute();
353
      pstmt.close();
354 1217 tao
      //dbconn.close();
355 1063 tao
    }
356
    finally
357
    {
358
      try
359
      {
360 1217 tao
        pstmt.close();
361 1063 tao
      }
362 1217 tao
      finally
363 1063 tao
      {
364 1217 tao
        DBConnectionPool.returnDBConnection(dbconn, serialNumber);
365 1063 tao
      }
366 798 jones
    }
367
  }
368 1029 tao
369 1055 tao
    /**
370
   * Register a document that resides on the filesystem with the database.
371
   * (ie, just an entry in xml_documents, nothing in xml_nodes).
372
   * Creates a reference to a filesystem document (used for non-xml data files)
373
   * This method will be called for register data file in xml_documents in
374
   * Replication.
375
   * This method is revised from registerDocument.
376
   *
377
   * @param conn the JDBC Connection to which all information is written
378
   * @param docname - the name of DTD, i.e. the name immediately following
379
   *        the DOCTYPE keyword ( should be the root element name ) or
380
   *        the root element name if no DOCTYPE declaration provided
381
   *        (Oracle's and IBM parsers are not aware if it is not the
382
   *        root element name)
383
   * @param doctype - Public ID of the DTD, i.e. the name immediately
384
   *                  following the PUBLIC keyword in DOCTYPE declaration or
385
   *                  the docname if no Public ID provided or
386
   *                  null if no DOCTYPE declaration provided
387
   * @param accnum the accession number to use for the INSERT OR UPDATE, which
388
   *               includes a revision number for this revision of the document
389
   *               (e.g., knb.1.1)
390
   * @param user the user that owns the document
391
   * @param serverCode the serverid from xml_replication on which this document
392
   *        resides.
393
   */
394
  public static void registerDocumentInReplication(
395
                     String docname, String doctype, String accnum,
396
                     String user, int serverCode)
397
                     throws SQLException, AccessionNumberException, Exception
398
  {
399 1217 tao
    DBConnection dbconn = null;
400
    int serialNumber = -1;
401
    //MetaCatUtil util = new MetaCatUtil();
402 1055 tao
    AccessionNumber ac;
403 1217 tao
    PreparedStatement pstmt = null;
404 1755 tao
    String action = null;
405 1055 tao
    try {
406 1217 tao
      //dbconn = util.openDBConnection();
407
       dbconn=DBConnectionPool.
408
                  getDBConnection("DocumentImpl.registerDocumentInReplication");
409
      serialNumber=dbconn.getCheckOutSerialNumber();
410 1055 tao
      String docIdWithoutRev=MetaCatUtil.getDocIdFromString(accnum);
411
      int userSpecifyRev=MetaCatUtil.getVersionFromString(accnum);
412 1217 tao
      int revInDataBase=getLatestRevisionNumber(docIdWithoutRev);
413 1055 tao
      //revIndataBase=-1, there is no record in xml_documents table
414
      //the data file is a new one, inert it into table
415
      //user specified rev should be great than 0
416
      if (revInDataBase==-1 && userSpecifyRev>0 )
417
      {
418 1063 tao
419 1217 tao
        ac = new AccessionNumber(accnum, "insert");
420 1755 tao
        action = "insert";
421 1055 tao
      }
422
      //rev is greater the last revsion number and revInDataBase isn't -1
423
      // it is a updated data file
424
      else if (userSpecifyRev>revInDataBase && revInDataBase>0)
425
      {
426
427
        //archive the old entry
428 1217 tao
        archiveDocRevision(docIdWithoutRev, user);
429 1055 tao
        //delete the old entry in xml_documents
430 1755 tao
        //deleteXMLDocuments(docIdWithoutRev);
431 1217 tao
        ac = new AccessionNumber(accnum, "update");
432 1755 tao
        action = "update";
433 1055 tao
      }
434 1292 tao
      // local server has newer version, then notify the remote server
435
      else if ( userSpecifyRev < revInDataBase && revInDataBase > 0)
436
      {
437
        throw new Exception("Local server: "+MetaCatUtil.getOption("server")+
438
                 " has newer revision of doc: "+docIdWithoutRev+"."
439
                  +revInDataBase+". Please notify it.");
440
      }
441 1055 tao
      //other situation
442
      else
443
      {
444
445
        throw new Exception("Revision number couldn't be "
446
                    +userSpecifyRev);
447
      }
448
      String docid = ac.getDocid();
449
      String rev = ac.getRev();
450 1755 tao
      /*SimpleDateFormat formatter = new SimpleDateFormat ("MM/dd/yy HH:mm:ss");
451 1055 tao
      Date localtime = new Date();
452
      String dateString = formatter.format(localtime);
453 1755 tao
      String sqlDateString=dbAdapter.toDate(dateString, "MM/DD/YY HH24:MI:SS");*/
454
      String sqlDateString = dbAdapter.getDateTimeFunction();
455
456 1055 tao
      StringBuffer sql = new StringBuffer();
457 1755 tao
      if (action != null && action.equals("insert"))
458
      {
459
        sql.append("insert into xml_documents (docid, docname, doctype, ");
460
        sql.append("user_owner, user_updated, server_location, rev,date_created");
461
        sql.append(", date_updated, public_access) values ('");
462
        sql.append(docid).append("','");
463
        sql.append(docname).append("','");
464
        sql.append(doctype).append("','");
465
        sql.append(user).append("','");
466
        sql.append(user).append("','");
467
        sql.append(serverCode).append("','");
468
        sql.append(rev).append("',");
469
        sql.append(sqlDateString).append(",");
470
        sql.append(sqlDateString).append(",");
471
        sql.append("'0')");
472
      }
473
      else if (action != null && action.equals("update"))
474
      {
475
        sql.append("update xml_documents set docname ='");
476
        sql.append(docname).append("', ");
477
        sql.append("user_updated='");
478
        sql.append(user).append("', ");
479
        sql.append("server_location='");
480
        sql.append(serverCode).append("',");
481
        sql.append("rev='");
482
        sql.append(rev).append("',");
483
        sql.append("date_updated=");
484
        sql.append(sqlDateString);
485
        sql.append(" where docid='");
486
        sql.append(docid).append("'");
487
      }
488 1292 tao
      // Set auto commit fasle
489
      dbconn.setAutoCommit(false);
490 1217 tao
      pstmt = dbconn.prepareStatement(sql.toString());
491 1757 tao
492 1055 tao
      pstmt.execute();
493 1292 tao
      // Commit the insert
494
      dbconn.commit();
495 1055 tao
      pstmt.close();
496 1217 tao
      //dbconn.close();
497 1063 tao
    }
498
    finally
499
    {
500 1292 tao
      // Set DBConnection auto commit true
501
      dbconn.setAutoCommit(true);
502 1217 tao
      pstmt.close();
503
      DBConnectionPool.returnDBConnection(dbconn, serialNumber);
504 1055 tao
    }
505
  }
506
507 1021 tao
 /**
508 1029 tao
   * This method will register a data file entry in xml_documents and save a
509 1292 tao
   * data file input Stream into file system.. It is only used in replication
510 1029 tao
   *
511
   * @param  input, the input stream which contain the file content.
512
   * @param  , the input stream which contain the file content
513
   * @param docname - the name of DTD, for data file, it is a docid number.
514
   * @param doctype - "BIN" for data file
515
   * @param accnum the accession number to use for the INSERT OR UPDATE, which
516
   *               includes a revision number for this revision of the document
517
   *               (e.g., knb.1.1)
518
   * @param user the user that owns the document
519 1292 tao
   * @param docHomeServer, the home server of the docid
520
   * @param notificationServer, the server to notify force replication info to
521
   *                            local metacat
522 1029 tao
   */
523 1292 tao
 public static void writeDataFileInReplication(InputStream input,
524
                 String filePath, String docname, String doctype, String accnum,
525
                   String user, String docHomeServer, String notificationServer)
526 1029 tao
                     throws SQLException, AccessionNumberException, Exception
527
 {
528 1292 tao
    int serverCode=-2;
529
530
531 1029 tao
    if (filePath==null||filePath.equals(""))
532
    {
533
      throw new
534
            Exception("Please specify the directory where file will be store");
535
    }
536
    if (accnum==null||accnum.equals(""))
537
    {
538
      throw new Exception("Please specify the stored file name");
539
    }
540 1063 tao
541 1292 tao
542 1063 tao
543 1292 tao
    // If server is not int the xml replication talbe, insert it into
544
    // xml_replication table
545
    //serverList.addToServerListIfItIsNot(docHomeServer);
546
    insertServerIntoReplicationTable(docHomeServer);
547
548
    // Get server code again
549
    serverCode = getServerCode(docHomeServer);
550
551
552
    //register data file into xml_documents table
553
    registerDocumentInReplication(docname, doctype, accnum, user, serverCode);
554
    //write inputstream into file system.
555
    File dataDirectory = new File(filePath);
556
    File newFile = new File(dataDirectory, accnum);
557 1029 tao
558 1292 tao
    // create a buffered byte output stream
559
    // that uses a default-sized output buffer
560
    FileOutputStream fos = new FileOutputStream(newFile);
561
    BufferedOutputStream outPut = new BufferedOutputStream(fos);
562 1029 tao
563 1292 tao
    BufferedInputStream bis = null;
564
    bis = new BufferedInputStream(input);
565
    byte[] buf = new byte[4 * 1024]; // 4K buffer
566
    int b = bis.read(buf);
567 1029 tao
568 1292 tao
    while (b != -1)
569
    {
570 1029 tao
        outPut.write(buf, 0, b);
571
        b = bis.read(buf);
572 1292 tao
    }
573
    bis.close();
574
	  outPut.close();
575
	  fos.close();
576
577
    // Force replicate data file
578
    ForceReplicationHandler forceReplication = new ForceReplicationHandler
579
                                    (accnum, false, notificationServer);
580
581 1029 tao
 }
582
583 798 jones
584 1026 tao
585
  public static boolean getDataFileLockGrant(String accnum)
586
                                                  throws Exception
587
  {
588 1217 tao
589 1063 tao
    try
590
    {
591 1217 tao
592
      int serverLocation=getServerLocationNumber(accnum);
593
594 1063 tao
      return getDataFileLockGrant(accnum,serverLocation);
595
    }
596
    catch (Exception e)
597
    {
598 1217 tao
599 1063 tao
      throw e;
600
    }
601 1026 tao
  }
602
603 393 jones
  /**
604 1026 tao
   * The method will check if metacat can get data file lock grant
605
   * If server code is 1, it get.
606
   * If server code is not 1 but call replication getlock successfully,
607
   * it get
608
   * else, it didn't get
609
   * @param accnum, the ID of the document
610
   * @param action, the action to the document
611
   * @param serverCode, the server location code
612
   */
613
  public static boolean getDataFileLockGrant(String accnum, int serverCode)
614
                                          throws Exception
615
  {
616
    boolean flag=true;
617 1217 tao
    //MetaCatUtil util = new MetaCatUtil();
618
    String docid = MetaCatUtil.getDocIdFromString(accnum);
619
    int rev = MetaCatUtil.getVersionFromString(accnum);
620 1026 tao
621
    if (serverCode == 1)
622
    {
623
      flag=true;
624
      return flag;
625
    }
626
627
    //if((serverCode != 1 && action.equals("UPDATE")) )
628
    if (serverCode != 1)
629
    { //if this document being written is not a resident of this server then
630
      //we need to try to get a lock from it's resident server.  If the
631
      //resident server will not give a lock then we send the user a message
632
      //saying that he/she needs to download a new copy of the file and
633
      //merge the differences manually.
634
635 1292 tao
      String server=MetacatReplication.getServerNameForServerCode(serverCode);
636 1026 tao
      MetacatReplication.replLog("attempting to lock " + accnum);
637 1217 tao
      URL u = new URL("https://" + server + "?server=" +
638
        MetaCatUtil.getLocalReplicationServerName()+"&action=getlock&updaterev="
639 1026 tao
           +rev + "&docid=" + docid);
640
      //System.out.println("sending message: " + u.toString());
641
      String serverResStr = MetacatReplication.getURLContent(u);
642
      String openingtag =serverResStr.substring(0, serverResStr.indexOf(">")+1);
643
      if(openingtag.equals("<lockgranted>"))
644
      {
645
        //the lock was granted go ahead with the insert
646
        //System.out.println("In lockgranted");
647
        MetacatReplication.replLog("lock granted for " + accnum + " from " +
648
                                      server);
649
        flag=true;
650
        return flag;
651
      }//if
652
653
      else if(openingtag.equals("<filelocked>"))
654
      {//the file is currently locked by another user
655
       //notify our user to wait a few minutes, check out a new copy and try
656
       //again.
657
        //System.out.println("file locked");
658
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
659
                                   server + " reason: file already locked");
660
        throw new Exception("The file specified is already locked by another " +
661
                            "user.  Please wait 30 seconds, checkout the " +
662
                            "newer document, merge your changes and try " +
663
                            "again.");
664
      }
665
      else if(openingtag.equals("<outdatedfile>"))
666
      {//our file is outdated.  notify our user to check out a new copy of the
667
       //file and merge his version with the new version.
668
        //System.out.println("outdated file");
669
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
670
                                    server + " reason: local file outdated");
671
        throw new Exception("The file you are trying to update is an outdated" +
672
                            " version.  Please checkout the newest document, " +
673
                            "merge your changes and try again.");
674
      }//else if
675
    }//if
676
677
   return flag;
678
679
  }//getDataFileLockGrant
680
681
  /**
682 393 jones
   * get the document name
683
   */
684
  public String getDocname() {
685
    return docname;
686
  }
687
688
  /**
689
   * get the document type (which is the PublicID)
690
   */
691
  public String getDoctype() {
692
    return doctype;
693
  }
694
695
  /**
696
   * get the system identifier
697
   */
698
  public String getSystemID() {
699
    return system_id;
700
  }
701
702
  /**
703
   * get the root node identifier
704
   */
705
  public long getRootNodeID() {
706
    return rootnodeid;
707
  }
708 465 berkley
709
  /**
710
   * get the creation date
711
   */
712
  public String getCreateDate() {
713
    return createdate;
714
  }
715
716
  /**
717
   * get the update date
718
   */
719
  public String getUpdateDate() {
720
    return updatedate;
721
  }
722 393 jones
723 396 jones
  /**
724
   * Get the document identifier (docid)
725
   */
726
  public String getDocID() {
727
    return docid;
728
  }
729 465 berkley
730 691 bojilova
// DOCTITLE attr cleared from the db
731
//  /**
732
//   *get the document title
733
//   */
734
//  public String getDocTitle() {
735
//    return doctitle;
736
//  }
737 561 berkley
738
  public String getUserowner() {
739
    return userowner;
740
  }
741
742
  public String getUserupdated() {
743
    return userupdated;
744
  }
745
746
  public int getServerlocation() {
747
    return serverlocation;
748
  }
749
750 1059 tao
  public String getDocHomeServer() {
751
    return docHomeServer;
752 1055 tao
  }
753 1059 tao
754 1055 tao
755 1059 tao
756 697 bojilova
  public String getPublicaccess() {
757 561 berkley
    return publicaccess;
758
  }
759 575 berkley
760
  public int getRev() {
761
    return rev;
762
  }
763 956 tao
764 1441 tao
  public String getValidateType()
765
  {
766
    return validateType;
767
  }
768
769 1435 tao
  /**
770 429 jones
   * Print a string representation of the XML document
771 393 jones
   */
772 1480 tao
  public String toString(String user, String[] groups, boolean withInlinedata)
773 393 jones
  {
774 429 jones
    StringWriter docwriter = new StringWriter();
775 1435 tao
    try
776
    {
777 1480 tao
      this.toXml(docwriter, user, groups, withInlinedata);
778 1435 tao
    }
779
    catch (McdbException mcdbe)
780
    {
781 800 jones
      return null;
782
    }
783 429 jones
    String document = docwriter.toString();
784
    return document;
785
  }
786 1435 tao
787
   /**
788
   * Print a string representation of the XML document
789
   */
790
  public String toString()
791
  {
792
    StringWriter docwriter = new StringWriter();
793
    String userName = null;
794
    String[] groupNames = null;
795 1480 tao
    boolean withInlineData = false;
796 1435 tao
    try
797
    {
798 1480 tao
      this.toXml(docwriter, userName, groupNames, withInlineData);
799 1435 tao
    }
800
    catch (McdbException mcdbe)
801
    {
802
      return null;
803
    }
804
    String document = docwriter.toString();
805
    return document;
806
  }
807 429 jones
808
  /**
809
   * Get a text representation of the XML document as a string
810
   * This older algorithm uses a recursive tree of Objects to represent the
811
   * nodes of the tree.  Each object is passed the data for the document
812
   * and searches all of the document data to find its children nodes and
813
   * recursively build.  Thus, because each node reads the whole document,
814
   * this algorithm is extremely slow for larger documents, and the time
815
   * to completion is O(N^N) wrt the number of nodes.  See toXml() for a
816
   * better algorithm.
817
   */
818 800 jones
  public String readUsingSlowAlgorithm() throws McdbException
819 429 jones
  {
820 393 jones
    StringBuffer doc = new StringBuffer();
821
822 800 jones
    // First, check that we have the needed node data, and get it if not
823
    if (nodeRecordList == null) {
824
      nodeRecordList = getNodeRecordList(rootnodeid);
825
    }
826
827 429 jones
    // Create the elements from the downloaded data in the TreeSet
828
    rootNode = new ElementNode(nodeRecordList, rootnodeid);
829
830 393 jones
    // Append the resulting document to the StringBuffer and return it
831
    doc.append("<?xml version=\"1.0\"?>\n");
832
833
    if (docname != null) {
834
      if ((doctype != null) && (system_id != null)) {
835
        doc.append("<!DOCTYPE " + docname + " PUBLIC \"" + doctype +
836
                   "\" \"" + system_id + "\">\n");
837
      } else {
838
        doc.append("<!DOCTYPE " + docname + ">\n");
839
      }
840
    }
841
    doc.append(rootNode.toString());
842
843
    return (doc.toString());
844
  }
845
846
  /**
847 429 jones
   * Print a text representation of the XML document to a Writer
848
   *
849
   * @param pw the Writer to which we print the document
850
   */
851 1480 tao
  public void toXml(Writer pw, String user, String[] groups, boolean withInLineData)
852 1432 tao
                                                          throws McdbException
853 429 jones
  {
854 1458 tao
    // flag for process  eml2
855
    boolean proccessEml2 = false;
856
    if (doctype != null && doctype.equals(EMLNAMESPACE))
857
    {
858
      proccessEml2 = true;
859
    }
860
    // flag for process inline data
861
    boolean prcocessInlineData = false;
862
863 1439 tao
    TreeSet nodeRecordLists = null;
864 429 jones
    PrintWriter out = null;
865
    if (pw instanceof PrintWriter) {
866
      out = (PrintWriter)pw;
867
    } else {
868
      out = new PrintWriter(pw);
869
    }
870
871
    MetaCatUtil util = new MetaCatUtil();
872
873 1432 tao
    // Here add code to handle subtree access control
874
    PermissionController control = new PermissionController(docid);
875
    Hashtable unaccessableSubTree =control.hasUnaccessableSubTree(user, groups,
876
                                             AccessControlInterface.READSTRING);
877
878
    if (!unaccessableSubTree.isEmpty())
879
    {
880 1439 tao
881
      nodeRecordLists = getPartNodeRecordList(rootnodeid, unaccessableSubTree);
882
883 1432 tao
    }
884 1439 tao
    else
885 1432 tao
    {
886 1439 tao
      nodeRecordLists = getNodeRecordList(rootnodeid);
887 800 jones
    }
888
889 429 jones
    Stack openElements = new Stack();
890
    boolean atRootElement = true;
891
    boolean previousNodeWasElement = false;
892
893
    // Step through all of the node records we were given
894 1439 tao
895
    Iterator it = nodeRecordLists.iterator();
896
897
    while (it.hasNext())
898
    {
899
900 429 jones
      NodeRecord currentNode = (NodeRecord)it.next();
901 1439 tao
      util.debugMessage("[Got Node ID: " + currentNode.nodeid +
902
                          " (" + currentNode.parentnodeid +
903
                          ", " + currentNode.nodeindex +
904
                          ", " + currentNode.nodetype +
905
                          ", " + currentNode.nodename +
906
                          ", " + currentNode.nodedata + ")]", 50);
907 429 jones
      // Print the end tag for the previous node if needed
908
      //
909
      // This is determined by inspecting the parent nodeid for the
910
      // currentNode.  If it is the same as the nodeid of the last element
911
      // that was pushed onto the stack, then we are still in that previous
912
      // parent element, and we do nothing.  However, if it differs, then we
913
      // have returned to a level above the previous parent, so we go into
914
      // a loop and pop off nodes and print out their end tags until we get
915
      // the node on the stack to match the currentNode parentnodeid
916
      //
917
      // So, this of course means that we rely on the list of elements
918
      // having been sorted in a depth first traversal of the nodes, which
919
      // is handled by the NodeComparator class used by the TreeSet
920
      if (!atRootElement) {
921
        NodeRecord currentElement = (NodeRecord)openElements.peek();
922
        if ( currentNode.parentnodeid != currentElement.nodeid ) {
923
          while ( currentNode.parentnodeid != currentElement.nodeid ) {
924
            currentElement = (NodeRecord)openElements.pop();
925 1427 tao
            util.debugMessage("\n POPPED: " + currentElement.nodename, 50);
926 451 bojilova
            if (previousNodeWasElement) {
927
              out.print(">");
928
              previousNodeWasElement = false;
929
            }
930 826 bojilova
            if ( currentElement.nodeprefix != null ) {
931
              out.print("</" + currentElement.nodeprefix + ":" +
932
                        currentElement.nodename + ">" );
933
            } else {
934
              out.print("</" + currentElement.nodename + ">" );
935
            }
936 429 jones
            currentElement = (NodeRecord)openElements.peek();
937
          }
938
        }
939
      }
940
941
      // Handle the DOCUMENT node
942
      if (currentNode.nodetype.equals("DOCUMENT")) {
943
        out.println("<?xml version=\"1.0\"?>");
944 1441 tao
        if (docname != null && validateType != null && validateType.equals(DTD))
945
        {
946
          if ((doctype != null) && (system_id != null))
947
          {
948
949 429 jones
            out.println("<!DOCTYPE " + docname + " PUBLIC \"" + doctype +
950
                       "\" \"" + system_id + "\">");
951 1441 tao
          }
952
          else
953
          {
954
955 429 jones
            out.println("<!DOCTYPE " + docname + ">");
956
          }
957
        }
958
959
      // Handle the ELEMENT nodes
960
      } else if (currentNode.nodetype.equals("ELEMENT")) {
961
        if (atRootElement) {
962
          atRootElement = false;
963
        } else {
964
          if (previousNodeWasElement) {
965
            out.print(">");
966
          }
967
        }
968
        openElements.push(currentNode);
969 1427 tao
        util.debugMessage("\n PUSHED: " + currentNode.nodename, 50);
970 429 jones
        previousNodeWasElement = true;
971 826 bojilova
        if ( currentNode.nodeprefix != null ) {
972
          out.print("<" + currentNode.nodeprefix + ":" + currentNode.nodename);
973
        } else {
974
          out.print("<" + currentNode.nodename);
975
        }
976 1458 tao
977
        // if currentNode is inline and handle eml2, set flag proccess in
978
        if (currentNode.nodename != null &&
979
            currentNode.nodename.equals(EmlSAXHandler.INLINE) && proccessEml2)
980
        {
981
          prcocessInlineData = true;
982
        }
983 429 jones
984
      // Handle the ATTRIBUTE nodes
985
      } else if (currentNode.nodetype.equals("ATTRIBUTE")) {
986 826 bojilova
        if ( currentNode.nodeprefix != null ) {
987
          out.print(" " + currentNode.nodeprefix + ":" + currentNode.nodename +
988
                    "=\"" + currentNode.nodedata + "\"");
989
        } else {
990
          out.print(" " + currentNode.nodename + "=\"" +
991
                    currentNode.nodedata + "\"");
992
        }
993 821 bojilova
994
      // Handle the NAMESPACE nodes
995
      } else if (currentNode.nodetype.equals("NAMESPACE")) {
996
        out.print(" xmlns:" + currentNode.nodename + "=\""
997
                 + currentNode.nodedata + "\"");
998
999
      // Handle the TEXT nodes
1000 429 jones
      } else if (currentNode.nodetype.equals("TEXT")) {
1001
        if (previousNodeWasElement) {
1002
          out.print(">");
1003
        }
1004 1480 tao
        if (!prcocessInlineData || !withInLineData)
1005 1458 tao
        {
1006 1480 tao
          // if it is not inline data just out put data or it is line data
1007
          // but user don't want it, just put local id in inlinedata
1008 1458 tao
          out.print(currentNode.nodedata);
1009
        }
1010
        else
1011
        {
1012 1480 tao
          // if it is inline data and user want to see it, pull out from
1013
          // file system and output it
1014 1458 tao
          // for inline data, the data base only store the file name, so we
1015
          // can combine the file name and inline data file path, to get it
1016
          String fileName = currentNode.nodedata;
1017 1515 tao
          String content = EmlSAXHandler.readInlineDataFromFileSystem(fileName);
1018 1458 tao
          out.print(content);
1019
        }
1020
        // reset proccess inline data false
1021
        prcocessInlineData =false;
1022 429 jones
        previousNodeWasElement = false;
1023
1024
      // Handle the COMMENT nodes
1025
      } else if (currentNode.nodetype.equals("COMMENT")) {
1026
        if (previousNodeWasElement) {
1027
          out.print(">");
1028
        }
1029
        out.print("<!--" + currentNode.nodedata + "-->");
1030
        previousNodeWasElement = false;
1031
1032
      // Handle the PI nodes
1033
      } else if (currentNode.nodetype.equals("PI")) {
1034
        if (previousNodeWasElement) {
1035
          out.print(">");
1036
        }
1037
        out.print("<?" + currentNode.nodename + " " +
1038
                        currentNode.nodedata + "?>");
1039
        previousNodeWasElement = false;
1040
1041
      // Handle any other node type (do nothing)
1042
      } else {
1043
        // Any other types of nodes are not handled.
1044
        // Probably should throw an exception here to indicate this
1045
      }
1046
      out.flush();
1047
    }
1048 1439 tao
1049 429 jones
    // Print the final end tag for the root element
1050 686 berkley
    while(!openElements.empty())
1051
    {
1052
      NodeRecord currentElement = (NodeRecord)openElements.pop();
1053 1427 tao
      util.debugMessage("\n POPPED: " + currentElement.nodename, 50);
1054 826 bojilova
      if ( currentElement.nodeprefix != null ) {
1055
        out.print("</" + currentElement.nodeprefix + ":" +
1056
                  currentElement.nodename + ">" );
1057
      } else {
1058
        out.print("</" + currentElement.nodename + ">" );
1059
      }
1060 686 berkley
    }
1061 429 jones
    out.flush();
1062
  }
1063 622 berkley
1064 1515 tao
1065 1458 tao
1066 622 berkley
  private boolean isRevisionOnly(DocumentIdentifier docid) throws Exception
1067
  {
1068
    //System.out.println("inRevisionOnly");
1069 1217 tao
    DBConnection dbconn = null;
1070
    int serialNumber = -1;
1071
    PreparedStatement pstmt =null;
1072 622 berkley
    String rev = docid.getRev();
1073
    String newid = docid.getIdentifier();
1074 1217 tao
    try
1075
    {
1076
      dbconn=DBConnectionPool.
1077
                    getDBConnection("DocumentImpl.isRevisionOnly");
1078
      serialNumber=dbconn.getCheckOutSerialNumber();
1079
      pstmt = dbconn.prepareStatement("select rev from xml_documents " +
1080 622 berkley
                                  "where docid like '" + newid + "'");
1081 1217 tao
      pstmt.execute();
1082
      ResultSet rs = pstmt.getResultSet();
1083
      boolean tablehasrows = rs.next();
1084
      if(rev.equals("newest") || rev.equals("all"))
1085
      {
1086 622 berkley
        return false;
1087
      }
1088 1217 tao
1089
      if(tablehasrows)
1090
      {
1091
        int r = rs.getInt(1);
1092
        pstmt.close();
1093
        if(new Integer(rev).intValue() == r)
1094
        { //the current revision in in xml_documents
1095
          //System.out.println("returning false");
1096
          return false;
1097
        }
1098
        else if(new Integer(rev).intValue() < r)
1099
        { //the current revision is in xml_revisions.
1100
          //System.out.println("returning true");
1101
          return true;
1102
        }
1103
        else if(new Integer(rev).intValue() > r)
1104
        { //error, rev cannot be greater than r
1105
          throw new Exception("requested revision cannot be greater than " +
1106 622 berkley
                            "the latest revision number.");
1107 1217 tao
        }
1108 622 berkley
      }
1109 1292 tao
      // Get miss docid and rev, throw to McdDocNotFoundException
1110
      String missDocId = MetaCatUtil.getDocIdFromString(docid.toString());
1111
      String missRevision =
1112
                  MetaCatUtil.getRevisionStringFromString(docid.toString());
1113
      throw new McdbDocNotFoundException("the requested docid '" +
1114
                docid.toString() + "' does not exist", missDocId, missRevision);
1115 1217 tao
    }//try
1116
    finally
1117
    {
1118
      pstmt.close();
1119
      DBConnectionPool.returnDBConnection(dbconn, serialNumber);
1120
    }//finally
1121 622 berkley
  }
1122 429 jones
1123 800 jones
  private void getDocumentInfo(String docid) throws McdbException,
1124 1292 tao
                                        AccessionNumberException, Exception
1125 622 berkley
  {
1126
    getDocumentInfo(new DocumentIdentifier(docid));
1127
  }
1128
1129 429 jones
  /**
1130 393 jones
   * Look up the document type information from the database
1131
   *
1132
   * @param docid the id of the document to look up
1133
   */
1134 1292 tao
  private void getDocumentInfo(DocumentIdentifier docid) throws McdbException
1135
                                                          , Exception
1136 393 jones
  {
1137 1217 tao
    DBConnection dbconn = null;
1138
    int serialNumber = -1;
1139
    PreparedStatement pstmt = null;
1140 622 berkley
    String table = "xml_documents";
1141 1059 tao
1142 622 berkley
    try
1143
    {
1144
      if(isRevisionOnly(docid))
1145
      { //pull the document from xml_revisions instead of from xml_documents;
1146
        table = "xml_revisions";
1147
      }
1148
    }
1149 1292 tao
    // catch a McdbDocNotFoundException throw it
1150
    catch (McdbDocNotFoundException notFound)
1151 622 berkley
    {
1152 1292 tao
      throw notFound;
1153 622 berkley
    }
1154 1292 tao
    catch(Exception e)
1155 622 berkley
    {
1156
1157 1292 tao
      MetaCatUtil.debugMessage("error in DocumentImpl.getDocumentInfo: " +
1158
                          e.getMessage(), 30);
1159
      throw e;
1160 622 berkley
    }
1161
1162 1292 tao
1163
1164 1217 tao
    try
1165
    {
1166
      dbconn=DBConnectionPool.getDBConnection("DocumentImpl.getDocumentInfo");
1167
      serialNumber=dbconn.getCheckOutSerialNumber();
1168 622 berkley
      StringBuffer sql = new StringBuffer();
1169 691 bojilova
// DOCTITLE attr cleared from the db
1170
//      sql.append("SELECT docname, doctype, rootnodeid, doctitle, ");
1171
      sql.append("SELECT docname, doctype, rootnodeid, ");
1172 697 bojilova
      sql.append("date_created, date_updated, user_owner, user_updated, ");
1173
      sql.append("server_location, public_access, rev");
1174
      sql.append(" FROM ").append(table);
1175 622 berkley
      sql.append(" WHERE docid LIKE '").append(docid.getIdentifier());
1176
      sql.append("' and rev like '").append(docid.getRev()).append("'");
1177
      //System.out.println(sql.toString());
1178 393 jones
      pstmt =
1179 1217 tao
        dbconn.prepareStatement(sql.toString());
1180 393 jones
      // Bind the values to the query
1181 622 berkley
      //pstmt.setString(1, docid.getIdentifier());
1182
      //pstmt.setString(2, docid.getRev());
1183 393 jones
1184
      pstmt.execute();
1185
      ResultSet rs = pstmt.getResultSet();
1186
      boolean tableHasRows = rs.next();
1187
      if (tableHasRows) {
1188 561 berkley
        this.docname        = rs.getString(1);
1189
        this.doctype        = rs.getString(2);
1190
        this.rootnodeid     = rs.getLong(3);
1191 691 bojilova
// DOCTITLE attr cleared from the db
1192
//        this.doctitle       = rs.getString(4);
1193 692 bojilova
        this.createdate     = rs.getString(4);
1194
        this.updatedate     = rs.getString(5);
1195
        this.userowner      = rs.getString(6);
1196
        this.userupdated    = rs.getString(7);
1197
        this.serverlocation = rs.getInt(8);
1198 697 bojilova
        this.publicaccess   = rs.getString(9);
1199
        this.rev            = rs.getInt(10);
1200 393 jones
      }
1201 818 berkley
      pstmt.close();
1202 1059 tao
1203
      //get doc  home server name
1204
1205 1217 tao
      pstmt = dbconn.prepareStatement("select server " +
1206 1059 tao
                        "from xml_replication where serverid = ?");
1207 1217 tao
      //because connection use twise here, so we need to increase one
1208
      dbconn.increaseUsageCount(1);
1209 1059 tao
      pstmt.setInt(1, serverlocation);
1210
      pstmt.execute();
1211
      rs = pstmt.getResultSet();
1212
      tableHasRows = rs.next();
1213
      if (tableHasRows)
1214
      {
1215
1216
          String server = rs.getString(1);
1217
          //get homeserver name
1218
          if(!server.equals("localhost"))
1219
          {
1220
            this.docHomeServer=server;
1221
          }
1222
          else
1223
          {
1224
            this.docHomeServer=MetaCatUtil.getLocalReplicationServerName();
1225
          }
1226
          MetaCatUtil.debugMessage("server: "+docHomeServer, 50);
1227
1228
      }
1229
      pstmt.close();
1230 393 jones
      if (this.doctype != null) {
1231
        pstmt =
1232 1441 tao
          dbconn.prepareStatement("SELECT system_id, entry_type " +
1233 393 jones
                                  "FROM xml_catalog " +
1234 769 bojilova
                                 "WHERE public_id = ?");
1235 1217 tao
        //should increase usage count again
1236
        dbconn.increaseUsageCount(1);
1237 393 jones
        // Bind the values to the query
1238
        pstmt.setString(1, doctype);
1239
1240
        pstmt.execute();
1241
        rs = pstmt.getResultSet();
1242
        tableHasRows = rs.next();
1243
        if (tableHasRows) {
1244
          this.system_id  = rs.getString(1);
1245 1441 tao
          this.validateType = rs.getString(2);
1246
1247 393 jones
        }
1248 818 berkley
        pstmt.close();
1249 393 jones
      }
1250
    } catch (SQLException e) {
1251 675 berkley
      System.out.println("error in DocumentImpl.getDocumentInfo: " +
1252
                          e.getMessage());
1253 622 berkley
      e.printStackTrace(System.out);
1254 675 berkley
      throw new McdbException("Error accessing database connection in " +
1255
                              "DocumentImpl.getDocumentInfo: ", e);
1256 393 jones
    }
1257 1217 tao
    finally
1258
    {
1259
      try
1260
      {
1261
        pstmt.close();
1262
      }
1263
      catch (SQLException ee)
1264
      {
1265
        MetaCatUtil.debugMessage("error in DocumentImple.getDocumentInfo: "
1266
                                    +ee.getMessage(), 30);
1267
      }//catch
1268
      finally
1269
      {
1270
        DBConnectionPool.returnDBConnection(dbconn, serialNumber);
1271
      }
1272
    }
1273 393 jones
1274
    if (this.docname == null) {
1275 1292 tao
      throw new McdbDocNotFoundException("Document not found: " + docid,
1276
                                 docid.getIdentifier(), docid.getRev());
1277 393 jones
    }
1278
  }
1279 1439 tao
1280
  /**
1281
   * Look up the node data from the database, but some node would be shown
1282
   * because of access control
1283
   * @param rootnodeid the id of the root node of the node tree to look up
1284
   * @param accessControl  the hashtable has control info
1285
   */
1286
  private TreeSet getPartNodeRecordList(long rootnodeid,
1287
                                        Hashtable accessControl)
1288
                                        throws McdbException
1289
  {
1290
    PreparedStatement pstmt = null;
1291
    DBConnection dbconn = null;
1292
    int serialNumber = -1;
1293
    TreeSet nodeRecordList = new TreeSet(new NodeComparator());
1294
    long nodeid = 0;
1295
    long parentnodeid = 0;
1296
    long nodeindex = 0;
1297
    String nodetype = null;
1298
    String nodename = null;
1299
    String nodeprefix = null;
1300
    String nodedata = null;
1301
    String quotechar = dbAdapter.getStringDelimiter();
1302
    String sql = "SELECT nodeid,parentnodeid,nodeindex, " +
1303
                 "nodetype,nodename,nodeprefix,nodedata " +
1304
                  "FROM xml_nodes WHERE rootnodeid = ?";
1305
1306
    // go through the access control for some nodes
1307
     Enumeration en = accessControl.elements();
1308
     while (en.hasMoreElements())
1309
     {
1310
         SubTree tree = (SubTree)en.nextElement();
1311
         long startId = tree.getStartNodeId();
1312
         long endId  = tree.getEndNodeId();
1313
         sql = sql +" AND(nodeid < " + startId + " OR nodeid > " +endId +")";
1314
1315
     }
1316
     MetaCatUtil.debugMessage("The final query to select part node tree: " +
1317
                              sql, 25);
1318 393 jones
1319 1439 tao
    try
1320
    {
1321
      dbconn=DBConnectionPool.
1322
                    getDBConnection("DocumentImpl.getPartNodeRecordList");
1323
      serialNumber=dbconn.getCheckOutSerialNumber();
1324
      pstmt = dbconn.prepareStatement(sql);
1325
1326
      // Bind the values to the query
1327
      pstmt.setLong(1, rootnodeid);
1328
      pstmt.execute();
1329
      ResultSet rs = pstmt.getResultSet();
1330
      boolean tableHasRows = rs.next();
1331
      while (tableHasRows)
1332
      {
1333
        nodeid = rs.getLong(1);
1334
        parentnodeid = rs.getLong(2);
1335
        nodeindex = rs.getLong(3);
1336
        nodetype = rs.getString(4);
1337
        nodename = rs.getString(5);
1338
        nodeprefix = rs.getString(6);
1339
        nodedata = rs.getString(7);
1340
        nodedata = MetaCatUtil.normalize(nodedata);
1341
        // add the data to the node record list hashtable
1342
        NodeRecord currentRecord = new NodeRecord(nodeid,parentnodeid,nodeindex,
1343
                                      nodetype, nodename, nodeprefix, nodedata);
1344
        nodeRecordList.add(currentRecord);
1345
1346
        // Advance to the next node
1347
        tableHasRows = rs.next();
1348
      }
1349
      pstmt.close();
1350
1351
    }
1352
    catch (SQLException e)
1353
    {
1354
      throw new McdbException("Error in DocumentImpl.getPartNodeRecordList " +
1355
                              e.getMessage());
1356
    }
1357
    finally
1358
    {
1359
      try
1360
      {
1361
        pstmt.close();
1362
      }
1363
      catch (SQLException ee)
1364
      {
1365
        MetaCatUtil.debugMessage("error in DocumentImpl.getPartNodeRecordList: "
1366
                                    +ee.getMessage(), 30);
1367
      }
1368
      finally
1369
      {
1370
        DBConnectionPool.returnDBConnection(dbconn, serialNumber);
1371
      }
1372
    }
1373
1374
1375
    if (!nodeRecordList.isEmpty())
1376
    {
1377
1378
      return nodeRecordList;
1379
    }
1380
    else
1381
    {
1382
1383
      throw new McdbException("Error getting node data: " + docid);
1384
    }
1385
  }
1386
1387 393 jones
  /**
1388
   * Look up the node data from the database
1389
   *
1390 396 jones
   * @param rootnodeid the id of the root node of the node tree to look up
1391 393 jones
   */
1392 1217 tao
  private TreeSet getNodeRecordList(long rootnodeid) throws McdbException
1393 393 jones
  {
1394 1217 tao
    PreparedStatement pstmt = null;
1395
    DBConnection dbconn = null;
1396
    int serialNumber = -1;
1397 393 jones
    TreeSet nodeRecordList = new TreeSet(new NodeComparator());
1398
    long nodeid = 0;
1399
    long parentnodeid = 0;
1400
    long nodeindex = 0;
1401
    String nodetype = null;
1402
    String nodename = null;
1403 826 bojilova
    String nodeprefix = null;
1404 393 jones
    String nodedata = null;
1405 899 berkley
    String quotechar = dbAdapter.getStringDelimiter();
1406 393 jones
1407
    try {
1408 1217 tao
      dbconn=DBConnectionPool.
1409
                    getDBConnection("DocumentImpl.getNodeRecordList");
1410
      serialNumber=dbconn.getCheckOutSerialNumber();
1411 393 jones
      pstmt =
1412 1217 tao
      dbconn.prepareStatement("SELECT nodeid,parentnodeid,nodeindex, " +
1413 899 berkley
           "nodetype,nodename,nodeprefix,nodedata " +
1414 396 jones
           "FROM xml_nodes WHERE rootnodeid = ?");
1415 393 jones
1416
      // Bind the values to the query
1417 396 jones
      pstmt.setLong(1, rootnodeid);
1418 393 jones
1419
      pstmt.execute();
1420
      ResultSet rs = pstmt.getResultSet();
1421
      boolean tableHasRows = rs.next();
1422
      while (tableHasRows) {
1423
        nodeid = rs.getLong(1);
1424
        parentnodeid = rs.getLong(2);
1425
        nodeindex = rs.getLong(3);
1426
        nodetype = rs.getString(4);
1427
        nodename = rs.getString(5);
1428 826 bojilova
        nodeprefix = rs.getString(6);
1429
        nodedata = rs.getString(7);
1430 899 berkley
        nodedata = MetaCatUtil.normalize(nodedata);
1431 393 jones
        // add the data to the node record list hashtable
1432 826 bojilova
        NodeRecord currentRecord = new NodeRecord(nodeid,parentnodeid,nodeindex,
1433 946 tao
                                      nodetype, nodename, nodeprefix, nodedata);
1434 393 jones
        nodeRecordList.add(currentRecord);
1435
1436
        // Advance to the next node
1437
        tableHasRows = rs.next();
1438
      }
1439
      pstmt.close();
1440
1441
    } catch (SQLException e) {
1442 826 bojilova
      throw new McdbException("Error in DocumentImpl.getNodeRecordList " +
1443
                              e.getMessage());
1444 393 jones
    }
1445 1217 tao
    finally
1446
    {
1447
      try
1448
      {
1449
        pstmt.close();
1450
      }
1451
      catch (SQLException ee)
1452
      {
1453
        MetaCatUtil.debugMessage("error in DocumentImpl.getNodeRecordList: "
1454
                                    +ee.getMessage(), 30);
1455
      }
1456
      finally
1457
      {
1458
        DBConnectionPool.returnDBConnection(dbconn, serialNumber);
1459
      }
1460
    }
1461 1467 tao
1462
    return nodeRecordList;
1463
1464 393 jones
  }
1465 549 berkley
1466 697 bojilova
// NOT USED ANY MORE
1467
//  /** creates SQL code and inserts new document into DB connection
1468
//   default serverCode of 1*/
1469
//  private void writeDocumentToDB(String action, String user)
1470
//               throws SQLException, Exception
1471
//  {
1472
//    writeDocumentToDB(action, user, null, 1);
1473
//  }
1474 393 jones
1475 459 bojilova
 /** creates SQL code and inserts new document into DB connection */
1476 680 bojilova
  private void writeDocumentToDB(String action, String user, String pub,
1477 697 bojilova
                                 String catalogid, int serverCode)
1478 459 bojilova
               throws SQLException, Exception {
1479 754 bojilova
    String sysdate = dbAdapter.getDateTimeFunction();
1480 747 bojilova
1481 459 bojilova
    try {
1482
      PreparedStatement pstmt = null;
1483
1484
      if (action.equals("INSERT")) {
1485
        //AccessionNumber ac = new AccessionNumber();
1486
        //this.docid = ac.generate(docid, "INSERT");
1487 1217 tao
1488
        pstmt = connection.prepareStatement(
1489 697 bojilova
                "INSERT INTO xml_documents " +
1490
                "(docid, rootnodeid, docname, doctype, " +
1491
                "user_owner, user_updated, date_created, date_updated, " +
1492 1072 tao
                "public_access, catalog_id, server_location, rev) " +
1493 747 bojilova
                "VALUES (?, ?, ?, ?, ?, ?, " + sysdate + ", " + sysdate +
1494 1072 tao
                ", ?, ?, ?, ?)");
1495 1217 tao
        // Increase dbconnection usage count
1496
        connection.increaseUsageCount(1);
1497
1498 549 berkley
        //note that the server_location is set to 1.
1499
        //this means that "localhost" in the xml_replication table must
1500
        //always be the first entry!!!!!
1501
1502 459 bojilova
        // Bind the values to the query
1503
        pstmt.setString(1, this.docid);
1504
        pstmt.setLong(2, rootnodeid);
1505
        pstmt.setString(3, docname);
1506
        pstmt.setString(4, doctype);
1507
        pstmt.setString(5, user);
1508
        pstmt.setString(6, user);
1509 1069 tao
        //public access is usefulless, so set it to null
1510
        pstmt.setString(7, null);
1511
        /*if ( pub == null ) {
1512 680 bojilova
          pstmt.setString(7, null);
1513 697 bojilova
        } else if ( pub.toUpperCase().equals("YES") || pub.equals("1") ) {
1514 680 bojilova
          pstmt.setInt(7, 1);
1515 697 bojilova
        } else if ( pub.toUpperCase().equals("NO") || pub.equals("0") ) {
1516 680 bojilova
          pstmt.setInt(7, 0);
1517 1069 tao
        }*/
1518 697 bojilova
        pstmt.setString(8, catalogid);
1519
        pstmt.setInt(9, serverCode);
1520 1072 tao
        pstmt.setInt(10, Integer.parseInt(updatedVersion));
1521 459 bojilova
      } else if (action.equals("UPDATE")) {
1522
1523 1072 tao
        // Save the old document publicaccessentry in a backup table
1524 1217 tao
        DocumentImpl.archiveDocRevision(connection, docid, user );
1525 1292 tao
        DocumentImpl thisdoc = new DocumentImpl(docid, false);
1526 575 berkley
        int thisrev = thisdoc.getRev();
1527 956 tao
1528
        //if the updated vesion is not greater than current one,
1529
        //throw it into a exception
1530
        if (Integer.parseInt(updatedVersion)<=thisrev)
1531
        {
1532
          throw new Exception("Next revision number couldn't be less"
1533
                               +" than or equal "+ thisrev);
1534
        }
1535
        else
1536
        {
1537
          //set the user specified revision
1538
          thisrev=Integer.parseInt(updatedVersion);
1539
        }
1540
1541 459 bojilova
        // Delete index for the old version of docid
1542
        // The new index is inserting on the next calls to DBSAXNode
1543 1217 tao
        pstmt = connection.prepareStatement(
1544 459 bojilova
                "DELETE FROM xml_index WHERE docid='" + this.docid + "'");
1545 1217 tao
        // Increase dbconnection usage count
1546
        connection.increaseUsageCount(1);
1547
1548 459 bojilova
        pstmt.execute();
1549 818 berkley
        pstmt.close();
1550 459 bojilova
1551
        // Update the new document to reflect the new node tree
1552 1217 tao
        pstmt = connection.prepareStatement(
1553 459 bojilova
            "UPDATE xml_documents " +
1554
            "SET rootnodeid = ?, docname = ?, doctype = ?, " +
1555 747 bojilova
            "user_updated = ?, date_updated = " + sysdate + ", " +
1556 697 bojilova
            "server_location = ?, rev = ?, public_access = ?, catalog_id = ? " +
1557 769 bojilova
            "WHERE docid = ?");
1558 1217 tao
        // Increase dbconnection usage count
1559
        connection.increaseUsageCount(1);
1560 459 bojilova
        // Bind the values to the query
1561
        pstmt.setLong(1, rootnodeid);
1562
        pstmt.setString(2, docname);
1563
        pstmt.setString(3, doctype);
1564
        pstmt.setString(4, user);
1565 549 berkley
        pstmt.setInt(5, serverCode);
1566 575 berkley
        pstmt.setInt(6, thisrev);
1567 1069 tao
        pstmt.setString(7, null);
1568
        /*if ( pub == null ) {
1569 680 bojilova
          pstmt.setString(7, null);
1570 697 bojilova
        } else if ( pub.toUpperCase().equals("YES") || pub.equals("1") ) {
1571 680 bojilova
          pstmt .setInt(7, 1);
1572 697 bojilova
        } else if ( pub.toUpperCase().equals("NO") || pub.equals("0") ) {
1573 680 bojilova
          pstmt.setInt(7, 0);
1574 1069 tao
        }*/
1575 697 bojilova
        pstmt.setString(8, catalogid);
1576
        pstmt.setString(9, this.docid);
1577 575 berkley
1578 459 bojilova
      } else {
1579
        System.err.println("Action not supported: " + action);
1580
      }
1581
1582
      // Do the insertion
1583
      pstmt.execute();
1584 1217 tao
1585 459 bojilova
      pstmt.close();
1586
1587
    } catch (SQLException sqle) {
1588
      throw sqle;
1589
    } catch (Exception e) {
1590
      throw e;
1591
    }
1592
  }
1593
1594
  /**
1595 407 jones
   * Write an XML file to the database, given a filename
1596 393 jones
   *
1597 408 jones
   * @param conn the JDBC connection to the database
1598 407 jones
   * @param filename the filename to be loaded into the database
1599 680 bojilova
   * @param pub flag for public "read" access on document
1600
   * @param dtdfilename the dtd to be uploaded on server's file system
1601 407 jones
   * @param action the action to be performed (INSERT OR UPDATE)
1602
   * @param docid the docid to use for the INSERT OR UPDATE
1603 680 bojilova
   * @param user the user that owns the document
1604 802 bojilova
   * @param groups the groups to which user belongs
1605 393 jones
   */
1606 1383 tao
  /*public static String write(DBConnection conn,String filename,
1607 680 bojilova
                             String pub, String dtdfilename,
1608 598 bojilova
                             String action, String docid, String user,
1609 802 bojilova
                             String[] groups )
1610 457 bojilova
                throws Exception {
1611 598 bojilova
1612
    Reader dtd = null;
1613
    if ( dtdfilename != null ) {
1614
      dtd = new FileReader(new File(dtdfilename).toString());
1615
    }
1616 555 bojilova
    return write ( conn, new FileReader(new File(filename).toString()),
1617 802 bojilova
                   pub, dtd, action, docid, user, groups, false);
1618 1383 tao
  }*/
1619 598 bojilova
1620 1217 tao
  public static String write(DBConnection conn,Reader xml,String pub,Reader dtd,
1621 598 bojilova
                             String action, String docid, String user,
1622 1383 tao
                             String[] groups, String ruleBase,
1623
                             boolean needValidation)
1624 549 berkley
                throws Exception {
1625 1012 tao
    //this method will be called in handleUpdateOrInsert method
1626 1383 tao
    //in MetacatServlet class and now is wrapper into documentImple
1627 1012 tao
    // get server location for this doc
1628 1217 tao
    int serverLocation=getServerLocationNumber(docid);
1629 1012 tao
    return write(conn,xml,pub,dtd,action,docid,user,groups,serverLocation,false,
1630 1383 tao
                 ruleBase, needValidation);
1631 598 bojilova
  }
1632
1633 1383 tao
1634 549 berkley
1635 407 jones
  /**
1636
   * Write an XML file to the database, given a Reader
1637
   *
1638 408 jones
   * @param conn the JDBC connection to the database
1639 407 jones
   * @param xml the xml stream to be loaded into the database
1640 680 bojilova
   * @param pub flag for public "read" access on xml document
1641
   * @param dtd the dtd to be uploaded on server's file system
1642 734 bojilova
   * @param action the action to be performed (INSERT or UPDATE)
1643
   * @param accnum the docid + rev# to use on INSERT or UPDATE
1644 580 berkley
   * @param user the user that owns the document
1645 802 bojilova
   * @param groups the groups to which user belongs
1646 580 berkley
   * @param serverCode the serverid from xml_replication on which this document
1647
   *        resides.
1648
   * @param override flag to stop insert replication checking.
1649
   *        if override = true then a document not belonging to the local server
1650
   *        will not be checked upon update for a file lock.
1651
   *        if override = false then a document not from this server, upon
1652
   *        update will be locked and version checked.
1653 407 jones
   */
1654 559 berkley
1655 1217 tao
  public static String write(DBConnection conn, Reader xml,String pub,
1656
                         Reader dtd, String action, String accnum, String user,
1657
                         String[] groups, int serverCode, boolean override,
1658 1383 tao
                         String ruleBase, boolean needValidation)
1659 598 bojilova
                throws Exception
1660 573 berkley
  {
1661 779 bojilova
    // NEW - WHEN CLIENT ALWAYS PROVIDE ACCESSION NUMBER INCLUDING REV IN IT
1662 1217 tao
    //MetaCatUtil util = new MetaCatUtil();
1663
    MetaCatUtil.debugMessage("conn usage count before writting: "
1664
                                      +conn.getUsageCount(), 50);
1665
    AccessionNumber ac = new AccessionNumber(accnum, action);
1666 779 bojilova
    String docid = ac.getDocid();
1667
    String rev = ac.getRev();
1668 590 berkley
    MetaCatUtil.debugMessage("action: " + action + " servercode: " +
1669 1055 tao
                             serverCode + " override: " + override, 10);
1670 1383 tao
1671 577 berkley
    if((serverCode != 1 && action.equals("UPDATE")) && !override)
1672 559 berkley
    { //if this document being written is not a resident of this server then
1673
      //we need to try to get a lock from it's resident server.  If the
1674
      //resident server will not give a lock then we send the user a message
1675
      //saying that he/she needs to download a new copy of the file and
1676
      //merge the differences manually.
1677 567 berkley
      int istreamInt;
1678 561 berkley
      char istreamChar;
1679 1081 tao
1680
      // check for 'write' permission for 'user' to update this document
1681 1427 tao
      if ( !hasWritePermission(user, groups, docid) ) {
1682 1081 tao
        throw new Exception("User " + user +
1683
              " does not have permission to update XML Document #" + accnum);
1684
      }
1685
1686 779 bojilova
      DocumentIdentifier id = new DocumentIdentifier(accnum);
1687
      String updaterev = id.getRev();
1688 1292 tao
      String server=MetacatReplication.getServerNameForServerCode(serverCode);
1689 734 bojilova
      MetacatReplication.replLog("attempting to lock " + accnum);
1690 1217 tao
      URL u = new URL("https://" + server + "?server="+
1691
        MetaCatUtil.getLocalReplicationServerName()+"&action=getlock&updaterev="
1692 1012 tao
           +updaterev + "&docid=" + docid);
1693
      //System.out.println("sending message: " + u.toString());
1694 569 berkley
      String serverResStr = MetacatReplication.getURLContent(u);
1695 946 tao
      String openingtag =serverResStr.substring(0, serverResStr.indexOf(">")+1);
1696 561 berkley
      if(openingtag.equals("<lockgranted>"))
1697
      {//the lock was granted go ahead with the insert
1698 571 berkley
        try
1699
        {
1700 1012 tao
          //System.out.println("In lockgranted");
1701 734 bojilova
          MetacatReplication.replLog("lock granted for " + accnum + " from " +
1702 584 berkley
                                      server);
1703 1383 tao
          /*XMLReader parser = initializeParser(conn, action, docid, updaterev,
1704
                               validate, user, groups, pub, serverCode, dtd);*/
1705 956 tao
          XMLReader parser = initializeParser(conn, action, docid, updaterev,
1706 1383 tao
                                        user, groups, pub, serverCode,
1707
                                        dtd,ruleBase, needValidation);
1708 571 berkley
          conn.setAutoCommit(false);
1709 695 bojilova
          parser.parse(new InputSource(xml));
1710 571 berkley
          conn.commit();
1711
          conn.setAutoCommit(true);
1712
        }
1713
        catch (Exception e)
1714
        {
1715
          conn.rollback();
1716
          conn.setAutoCommit(true);
1717
          throw e;
1718
        }
1719 1591 tao
        // run write into access db base one relation table and access object
1720
        runRelationAndAccessHandler(accnum, user, groups, serverCode);
1721 590 berkley
1722 1292 tao
        // Force replication the docid
1723
        ForceReplicationHandler frh = new ForceReplicationHandler
1724
                                                          (accnum, true, null);
1725
        return(accnum);
1726
1727 561 berkley
      }
1728 734 bojilova
1729 561 berkley
      else if(openingtag.equals("<filelocked>"))
1730
      {//the file is currently locked by another user
1731
       //notify our user to wait a few minutes, check out a new copy and try
1732
       //again.
1733 584 berkley
        //System.out.println("file locked");
1734 734 bojilova
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
1735 584 berkley
                                   server + " reason: file already locked");
1736 571 berkley
        throw new Exception("The file specified is already locked by another " +
1737
                            "user.  Please wait 30 seconds, checkout the " +
1738
                            "newer document, merge your changes and try " +
1739
                            "again.");
1740 561 berkley
      }
1741
      else if(openingtag.equals("<outdatedfile>"))
1742
      {//our file is outdated.  notify our user to check out a new copy of the
1743
       //file and merge his version with the new version.
1744 584 berkley
        //System.out.println("outdated file");
1745 734 bojilova
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
1746 584 berkley
                                    server + " reason: local file outdated");
1747 571 berkley
        throw new Exception("The file you are trying to update is an outdated" +
1748
                            " version.  Please checkout the newest document, " +
1749
                            "merge your changes and try again.");
1750 561 berkley
      }
1751 559 berkley
    }
1752 571 berkley
1753 425 bojilova
    if ( action.equals("UPDATE") ) {
1754 441 bojilova
      // check for 'write' permission for 'user' to update this document
1755 628 berkley
1756 1427 tao
      if ( !hasWritePermission(user, groups, docid) ) {
1757 441 bojilova
        throw new Exception("User " + user +
1758 734 bojilova
              " does not have permission to update XML Document #" + accnum);
1759 425 bojilova
      }
1760
    }
1761
1762 571 berkley
    try
1763 638 bojilova
    {
1764 956 tao
1765 1383 tao
      XMLReader parser = initializeParser(conn, action, docid, rev,
1766
                                          user, groups, pub, serverCode,
1767
                                          dtd, ruleBase, needValidation);
1768 1217 tao
1769 555 bojilova
      conn.setAutoCommit(false);
1770
      parser.parse(new InputSource(xml));
1771
      conn.commit();
1772
      conn.setAutoCommit(true);
1773 571 berkley
    }
1774
    catch (Exception e)
1775
    {
1776 555 bojilova
      conn.rollback();
1777
      conn.setAutoCommit(true);
1778
      throw e;
1779
    }
1780 577 berkley
1781 1591 tao
    // run access db base on relation table and access object
1782
    runRelationAndAccessHandler(accnum, user, groups, serverCode);
1783 1575 tao
1784 1292 tao
    // Force replicate out the new document to each server in our server list.
1785
    // Start the thread to replicate this new document out to the other servers
1786
    // true mean it is xml document
1787
    // null is because no metacat notify the force replication.
1788
    ForceReplicationHandler frh = new ForceReplicationHandler
1789
                                                  (accnum, action, true, null);
1790 1012 tao
1791 1292 tao
1792 1217 tao
    MetaCatUtil.debugMessage("Conn Usage count after writting: "
1793
                                                      +conn.getUsageCount(),50);
1794 779 bojilova
    return(accnum);
1795 393 jones
  }
1796 396 jones
1797 407 jones
  /**
1798 1055 tao
   * Write an XML file to the database during replication
1799
   *
1800
   * @param conn the JDBC connection to the database
1801
   * @param xml the xml stream to be loaded into the database
1802
   * @param pub flag for public "read" access on xml document
1803
   * @param dtd the dtd to be uploaded on server's file system
1804
   * @param action the action to be performed (INSERT or UPDATE)
1805
   * @param accnum the docid + rev# to use on INSERT or UPDATE
1806
   * @param user the user that owns the document
1807
   * @param groups the groups to which user belongs
1808
   * @param homeServer the name of server which the document origanlly create
1809
   * @param validate, if the xml document is valid or not
1810 1292 tao
   * @param notifyServer, the server which notify local server the force
1811
   *                       replication command
1812 1055 tao
   */
1813
1814 1217 tao
  public static String writeReplication(DBConnection conn, Reader xml,
1815 1383 tao
                                        String pub, Reader dtd, String action,
1816
                                        String accnum, String user,
1817
                                        String[] groups,String homeServer,
1818
                                        String notifyServer,
1819
                                        String ruleBase, boolean needValidation)
1820
                                        throws Exception
1821 1055 tao
  {
1822 1292 tao
    // Docid without revision
1823
    String docid=MetaCatUtil.getDocIdFromString(accnum);
1824
    // Revision specified by user (int)
1825
    int userSpecifyRev=MetaCatUtil.getVersionFromString(accnum);
1826
    // Revision for this docid in current database
1827
    int revInDataBase=getLatestRevisionNumber(docid);
1828
    // String to store the revision
1829
    String rev = null;
1830 1217 tao
1831 1069 tao
1832 1292 tao
    //revIndataBase=-1, there is no record in xml_documents table
1833
    //the document is a new one for local server, inert it into table
1834
    //user specified rev should be great than 0
1835
    if (revInDataBase==-1 && userSpecifyRev>0 )
1836 1069 tao
    {
1837 1292 tao
        // rev equals user specified
1838
        rev=(new Integer(userSpecifyRev)).toString();
1839
        // action should be INSERT
1840
        action = "INSERT";
1841 1069 tao
    }
1842 1292 tao
    //rev is greater the last revsion number and revInDataBase isn't -1
1843
    // it is a updated  file
1844
    else if (userSpecifyRev>revInDataBase && revInDataBase>0)
1845 1055 tao
    {
1846 1292 tao
       // rev equals user specified
1847
       rev=(new Integer(userSpecifyRev)).toString();
1848
       // action should be update
1849
       action = "UPDATE";
1850 1055 tao
    }
1851 1292 tao
    // local server has newer version, then notify the remote server
1852
    else if ( userSpecifyRev < revInDataBase && revInDataBase > 0)
1853
    {
1854
      throw new Exception("Local server: "+MetaCatUtil.getOption("server")+
1855
                " has newer revision of doc: "+docid+"."+revInDataBase
1856
                 +". Please notify it.");
1857
    }
1858
    //other situation
1859
    else
1860
    {
1861
1862
        throw new Exception("The docid"+docid+"'s revision number couldn't be "
1863
                    +userSpecifyRev);
1864
    }
1865
    // Variable to store homeserver code
1866
    int serverCode=-2;
1867
1868
     // If server is not int the xml replication talbe, insert it into
1869
    // xml_replication table
1870
    //serverList.addToServerListIfItIsNot(homeServer);
1871
    insertServerIntoReplicationTable(homeServer);
1872
    // Get server code again
1873
    serverCode = getServerCode(homeServer);
1874
1875
1876
    MetaCatUtil.debugMessage("Document "+docid+"."+rev+" "+action+ " into local"
1877
                               +" metacat with servercode: "+ serverCode, 10);
1878 1055 tao
1879 1217 tao
1880 1292 tao
    // insert into xml_nodes and xml_index table
1881 1055 tao
    try
1882
    {
1883
1884 1383 tao
      XMLReader parser = initializeParser(conn, action, docid, rev,
1885
                                          user, groups, pub, serverCode, dtd,
1886
                                          ruleBase, needValidation);
1887 1055 tao
      conn.setAutoCommit(false);
1888
      parser.parse(new InputSource(xml));
1889
      conn.commit();
1890
      conn.setAutoCommit(true);
1891
    }
1892
    catch (Exception e)
1893
    {
1894
      conn.rollback();
1895
      conn.setAutoCommit(true);
1896
      throw e;
1897
    }
1898 1292 tao
1899 1591 tao
    // run write into access db base on relation table and access rule
1900
    try
1901
    {
1902
      runRelationAndAccessHandler(accnum, user, groups, serverCode);
1903
    }
1904
    catch (Exception ee)
1905
    {
1906
      MetacatReplication.replErrorLog("Failed to " +
1907
                                       "create access " +
1908
                                       "rule for package: " + accnum +
1909
                                       " because " +ee.getMessage());
1910
      MetaCatUtil.debugMessage("Failed to  " +
1911
                                       "create access " +
1912
                                       "rule for package: "+ accnum +
1913
                                       " because " +ee.getMessage(), 30);
1914
    }
1915 1292 tao
    //Force replication to other server
1916
    ForceReplicationHandler forceReplication = new ForceReplicationHandler
1917
                                  (accnum, action, true, notifyServer);
1918
1919 1055 tao
1920
    return(accnum);
1921
  }
1922
1923 1575 tao
  /* Running write record to xml_relation and xml_access*/
1924 1591 tao
  private static void runRelationAndAccessHandler(String accnumber,
1925 1575 tao
                                                  String userName,
1926
                                                  String[]group, int servercode)
1927
                                                   throws Exception
1928
  {
1929
    DBConnection dbconn = null;
1930
    int serialNumber = -1;
1931
    PreparedStatement pstmt =null;
1932
    String documenttype = getDocTypeFromDBForCurrentDocument(accnumber);
1933
    try
1934
    {
1935
      String packagedoctype = MetaCatUtil.getOption("packagedoctype");
1936
      Vector packagedoctypes = new Vector();
1937
      packagedoctypes = MetaCatUtil.getOptionList(packagedoctype);
1938
      String docIdWithoutRev = MetaCatUtil.getDocIdFromString(accnumber);
1939
      if (documenttype != null && packagedoctypes.contains(documenttype) )
1940
      {
1941
        dbconn=DBConnectionPool.
1942 1591 tao
           getDBConnection("DocumentImpl.runRelationAndAccessHandeler");
1943 1575 tao
        serialNumber=dbconn.getCheckOutSerialNumber();
1944
        dbconn.setAutoCommit(false);
1945
        // from the relations get the access file id for that package
1946 1591 tao
        String aclid = RelationHandler.getAccessFileID(docIdWithoutRev);
1947 1575 tao
        // if there are access file, write ACL for that package
1948
        if ( aclid != null )
1949
        {
1950
          runAccessControlList(dbconn, aclid, userName, group, servercode);
1951
        }
1952
        dbconn.commit();
1953
        dbconn.setAutoCommit(true);
1954
      }
1955
        // if it is an access file
1956
      else if ( documenttype != null && MetaCatUtil.getOptionList(
1957
                 MetaCatUtil.getOption("accessdoctype")).contains(documenttype))
1958
      {
1959
        dbconn=DBConnectionPool.
1960 1591 tao
           getDBConnection("DocumentImpl.runRelationAndAccessHandeler");
1961 1575 tao
        serialNumber=dbconn.getCheckOutSerialNumber();
1962
        dbconn.setAutoCommit(false);
1963
        // write ACL for the package
1964
        runAccessControlList(dbconn, docIdWithoutRev,
1965
                             userName, group, servercode);
1966
        dbconn.commit();
1967
        dbconn.setAutoCommit(true);
1968
1969
      }
1970
1971
    }
1972
    catch (Exception e)
1973
    {
1974
      if( dbconn != null)
1975
      {
1976
        dbconn.rollback();
1977
        dbconn.setAutoCommit(true);
1978
      }
1979 1591 tao
      MetaCatUtil.debugMessage("Error in DocumentImple.runRelationAndAccessHandler " +
1980 1575 tao
                                e.getMessage(), 30);
1981
      throw e;
1982
    }
1983
    finally
1984
    {
1985
      if (dbconn != null)
1986
      {
1987
        DBConnectionPool.returnDBConnection(dbconn, serialNumber);
1988
      }
1989
    }//
1990
  }
1991
1992
  // It runs in xmlIndex thread. It writes ACL for a package.
1993
  private static void runAccessControlList (DBConnection conn, String aclid,
1994
                                    String users, String[]group, int servercode)
1995
                                                throws Exception
1996
  {
1997
    // read the access file from xml_nodes
1998
    // parse the access file and store the access info into xml_access
1999
    AccessControlList aclobj =
2000
    new AccessControlList(conn, aclid, users, group, servercode);
2001
2002
  }
2003
2004
  /* Method get document type from db*/
2005
  private static String getDocTypeFromDBForCurrentDocument(String accnumber)
2006
                                                  throws SQLException
2007
  {
2008
    String docoumentType = null;
2009
    String docid = null;
2010
    PreparedStatement pstate = null;
2011
    ResultSet rs = null;
2012
    String sql = "SELECT doctype FROM xml_documents where docid = ?";
2013
    DBConnection dbConnection = null;
2014
    int serialNumber = -1;
2015
    try
2016
    {
2017
      //get rid of revision number
2018
      docid = MetaCatUtil.getDocIdFromString(accnumber);
2019
      dbConnection=DBConnectionPool.
2020
           getDBConnection("DocumentImpl.getDocTypeFromDBForCurrentDoc");
2021
      serialNumber=dbConnection.getCheckOutSerialNumber();
2022
      pstate = dbConnection.prepareStatement(sql);
2023
      //bind variable
2024
      pstate.setString(1, docid);
2025
      //excute query
2026
      pstate.execute();
2027
      //handle resultset
2028
      rs = pstate.getResultSet();
2029
      if (rs.next())
2030
      {
2031
        docoumentType = rs.getString(1);
2032
      }
2033
      rs.close();
2034
      pstate.close();
2035
    }//try
2036
    catch (SQLException e)
2037
    {
2038
      MetaCatUtil.debugMessage("error in DocumentImpl."+
2039
                      "getDocTypeFromDBForCurrentDocument "+e.getMessage(), 30);
2040
      throw e;
2041
    }//catch
2042
    finally
2043
    {
2044
      pstate.close();
2045
      DBConnectionPool.returnDBConnection(dbConnection, serialNumber);
2046
    }//
2047
    MetaCatUtil.debugMessage("The current doctype from db is: "+
2048
                              docoumentType, 35);
2049
    return docoumentType;
2050
  }
2051 1055 tao
  /**
2052 407 jones
   * Delete an XML file from the database (actually, just make it a revision
2053
   * in the xml_revisions table)
2054
   *
2055
   * @param docid the ID of the document to be deleted from the database
2056
   */
2057 1217 tao
  public static void delete(String accnum,
2058 802 bojilova
                                 String user, String[] groups )
2059 734 bojilova
                throws Exception
2060
  {
2061 779 bojilova
    // OLD
2062
    //DocumentIdentifier id = new DocumentIdentifier(accnum);
2063
    //String docid = id.getIdentifier();
2064
    //String rev = id.getRev();
2065 628 berkley
2066 779 bojilova
    // OLD
2067 734 bojilova
    // Determine if the docid,rev are OK for DELETE
2068 779 bojilova
    //AccessionNumber ac = new AccessionNumber(conn);
2069
    //docid = ac.generate(docid, rev, "DELETE");
2070 1217 tao
    DBConnection conn = null;
2071
    int serialNumber = -1;
2072
    PreparedStatement pstmt =null;
2073
    try
2074
    {
2075
      //check out DBConnection
2076
      conn=DBConnectionPool.
2077
                    getDBConnection("DocumentImpl.delete");
2078
      serialNumber=conn.getCheckOutSerialNumber();
2079 396 jones
2080 1217 tao
      // NEW - WHEN CLIENT ALWAYS PROVIDE ACCESSION NUMBER INCLUDING REV IN IT
2081
      AccessionNumber ac = new AccessionNumber(accnum, "DELETE");
2082
      String docid = ac.getDocid();
2083
      String rev = ac.getRev();
2084 779 bojilova
2085 1621 tao
      MetaCatUtil.debugMessage("Start deleting doc "+docid+ "...", 20);
2086 441 bojilova
    // check for 'write' permission for 'user' to delete this document
2087 1427 tao
      if ( !hasWritePermission(user, groups, docid) ) {
2088 1217 tao
        throw new Exception("User " + user +
2089 734 bojilova
              " does not have permission to delete XML Document #" + accnum);
2090 1217 tao
      }
2091 425 bojilova
2092 1217 tao
      conn.setAutoCommit(false);
2093
      // Copy the record to the xml_revisions table
2094
      DocumentImpl.archiveDocRevision(conn, docid, user );
2095 396 jones
2096 1217 tao
      // Now delete it from the xml_index table
2097
      pstmt = conn.prepareStatement("DELETE FROM xml_index WHERE docid = ?");
2098
      pstmt.setString(1,docid);
2099
      pstmt.execute();
2100
      pstmt.close();
2101
      conn.increaseUsageCount(1);
2102
2103
      //stmt.execute("DELETE FROM xml_access WHERE docid = '" + docid + "'");
2104
      // Now delete it from xml_access table
2105
      pstmt = conn.
2106
              prepareStatement("DELETE FROM xml_access WHERE accessfileid = ?");
2107
      pstmt.setString(1, docid);
2108
      pstmt.execute();
2109
      pstmt.close();
2110
      conn.increaseUsageCount(1);
2111
2112
      // Delete it from relation table
2113
      pstmt = conn.
2114
               prepareStatement("DELETE FROM xml_relation WHERE docid = ?");
2115
      //increase usage count
2116
      conn.increaseUsageCount(1);
2117
      pstmt.setString(1, docid);
2118
      pstmt.execute();
2119
      pstmt.close();
2120
2121 1618 tao
      // Delete it from xml_accesssubtree table
2122
      pstmt = conn.
2123
               prepareStatement("DELETE FROM xml_accesssubtree WHERE docid = ?");
2124
      //increase usage count
2125
      conn.increaseUsageCount(1);
2126
      pstmt.setString(1, docid);
2127
      pstmt.execute();
2128
      pstmt.close();
2129
2130 1217 tao
      // Delete it from xml_doucments table
2131
      pstmt =conn.prepareStatement("DELETE FROM xml_documents WHERE docid = ?");
2132
      pstmt.setString(1, docid);
2133
      pstmt.execute();
2134
      pstmt.close();
2135
      //Usaga count increase 1
2136
      conn.increaseUsageCount(1);
2137
2138
      conn.commit();
2139
      conn.setAutoCommit(true);
2140
    }//try
2141 1621 tao
    catch (Exception e)
2142
    {
2143
      MetaCatUtil.debugMessage("error in DocumentImpl.delete: " +
2144
                                e.getMessage(), 30);
2145
      throw e;
2146
    }
2147 1217 tao
    finally
2148
    {
2149
2150
      try
2151
      {
2152
        // close preparedStatement
2153
        pstmt.close();
2154
      }//try
2155
      finally
2156
      {
2157
        //check in DBonnection
2158
        DBConnectionPool.returnDBConnection(conn, serialNumber);
2159
      }//finally
2160
    }//finally
2161 634 berkley
    //IF this is a package document:
2162
    //delete all of the relations that this document created.
2163
    //if the deleted document is a package document its relations should
2164
    //no longer be active if it has been deleted from the system.
2165 645 bojilova
2166 407 jones
  }
2167 638 bojilova
2168 570 bojilova
  /**
2169 802 bojilova
    * Check for "WRITE" permission on @docid for @user and/or @groups
2170 570 bojilova
    * from DB connection
2171
    */
2172 1427 tao
  private static boolean hasWritePermission (String user,
2173 802 bojilova
                                  String[] groups, String docid )
2174 958 tao
                  throws SQLException, Exception
2175 570 bojilova
  {
2176 802 bojilova
    // Check for WRITE permission on @docid for @user and/or @groups
2177 1427 tao
    PermissionController controller = new PermissionController(docid);
2178
    return controller.hasPermission(user,groups,
2179
                                    AccessControlInterface.WRITESTRING);
2180 425 bojilova
  }
2181
2182 946 tao
  /**
2183
    * Check for "READ" permission base on docid, user and group
2184
    *@docid, the document
2185
    *@user, user name
2186
    *@group, user's group
2187
    *
2188
    */
2189 1217 tao
  public static boolean hasReadPermission (String user,
2190 946 tao
                                  String[] groups, String docId )
2191 958 tao
                  throws SQLException, Exception
2192 946 tao
  {
2193
    // Check for READ permission on @docid for @user and/or @groups
2194 1427 tao
    PermissionController controller =
2195
                        new PermissionController(docId);
2196
    return controller.hasPermission(user,groups,
2197
                                            AccessControlInterface.READSTRING);
2198 946 tao
  }
2199
2200 1383 tao
2201
   /**
2202
   * Set up the parser handlers for writing the document to the database
2203
   */
2204
  private static XMLReader initializeParser(DBConnection dbconn, String action,
2205
                                            String docid, String rev,
2206
                                            String user,
2207
                                            String[] groups, String pub,
2208
                                            int serverCode, Reader dtd,
2209
                                            String ruleBase,
2210
                                            boolean needValidation)
2211
                                            throws Exception
2212
  {
2213
    XMLReader parser = null;
2214
    try
2215
    {
2216 1407 tao
      // handler
2217
      ContentHandler chandler;
2218 1383 tao
      EntityResolver eresolver;
2219
      DTDHandler dtdhandler;
2220
      // Get an instance of the parser
2221
      String parserName = MetaCatUtil.getOption("saxparser");
2222
      parser = XMLReaderFactory.createXMLReader(parserName);
2223 1407 tao
      if (ruleBase != null && ruleBase.equals(EML2))
2224 1383 tao
      {
2225 1407 tao
        MetaCatUtil.debugMessage("eml 2 parser", 20);
2226
        chandler = new EmlSAXHandler(dbconn, action,
2227
                                    docid, rev, user, groups, pub, serverCode);
2228
        parser.setContentHandler((ContentHandler)chandler);
2229
        parser.setErrorHandler((ErrorHandler)chandler);
2230
        parser.setProperty(DECLARATIONHANDLERPROPERTY, chandler);
2231
        parser.setProperty(LEXICALPROPERTY, chandler);
2232 1383 tao
        // turn on schema validation feature
2233
        parser.setFeature(VALIDATIONFEATURE, true);
2234
        parser.setFeature(NAMESPACEFEATURE, true);
2235 1431 tao
        //parser.setFeature(NAMESPACEPREFIXESFEATURE, true);
2236 1383 tao
        parser.setFeature(SCHEMAVALIDATIONFEATURE, true);
2237 1396 tao
        // From DB to find the register external schema location
2238
        String externalSchemaLocation = null;
2239
        SchemaLocationResolver resolver = new SchemaLocationResolver();
2240
        externalSchemaLocation = resolver.getNameSpaceAndLocationString();
2241
        // Set external schemalocation.
2242
        if (externalSchemaLocation != null &&
2243
            !(externalSchemaLocation.trim()).equals(""))
2244
        {
2245 1407 tao
            parser.setProperty(EXTERNALSCHEMALOCATIONPROPERTY,
2246 1396 tao
                             externalSchemaLocation);
2247
        }
2248 1383 tao
      }
2249
      else
2250
      {
2251 1407 tao
        //create a DBSAXHandler object which has the revision specification
2252
        chandler = new DBSAXHandler(dbconn, action,
2253
                                    docid, rev, user, groups, pub, serverCode);
2254
        parser.setContentHandler((ContentHandler)chandler);
2255
        parser.setErrorHandler((ErrorHandler)chandler);
2256
        parser.setProperty(DECLARATIONHANDLERPROPERTY, chandler);
2257
        parser.setProperty(LEXICALPROPERTY, chandler);
2258
2259
        if (ruleBase != null && ruleBase.equals(SCHEMA) && needValidation)
2260
        {
2261
          MetaCatUtil.debugMessage("General schema parser", 20);
2262
          // turn on schema validation feature
2263
          parser.setFeature(VALIDATIONFEATURE, true);
2264
          parser.setFeature(NAMESPACEFEATURE, true);
2265 1431 tao
          //parser.setFeature(NAMESPACEPREFIXESFEATURE, true);
2266 1407 tao
          parser.setFeature(SCHEMAVALIDATIONFEATURE, true);
2267
          // From DB to find the register external schema location
2268
          String externalSchemaLocation = null;
2269
          SchemaLocationResolver resolver = new SchemaLocationResolver();
2270
          externalSchemaLocation = resolver.getNameSpaceAndLocationString();
2271
          // Set external schemalocation.
2272
          if (externalSchemaLocation != null &&
2273
            !(externalSchemaLocation.trim()).equals(""))
2274
          {
2275
            parser.setProperty(EXTERNALSCHEMALOCATIONPROPERTY,
2276
                             externalSchemaLocation);
2277
          }
2278
2279
        }
2280
        else if (ruleBase != null && ruleBase.equals(DTD) && needValidation)
2281
        {
2282
          MetaCatUtil.debugMessage("dtd parser", 20);
2283
          // turn on dtd validaton feature
2284
          parser.setFeature(VALIDATIONFEATURE, true);
2285
          eresolver= new DBEntityResolver(dbconn, (DBSAXHandler)chandler, dtd);
2286
          dtdhandler = new DBDTDHandler(dbconn);
2287
          parser.setEntityResolver((EntityResolver)eresolver);
2288
          parser.setDTDHandler((DTDHandler)dtdhandler);
2289
        }
2290
        else
2291
        {
2292
          MetaCatUtil.debugMessage("other parser", 20);
2293
          // non validation
2294
          parser.setFeature(VALIDATIONFEATURE, false);
2295
          eresolver= new DBEntityResolver(dbconn, (DBSAXHandler)chandler, dtd);
2296
          dtdhandler = new DBDTDHandler(dbconn);
2297
          parser.setEntityResolver((EntityResolver)eresolver);
2298
          parser.setDTDHandler((DTDHandler)dtdhandler);
2299
        }
2300
      }//else
2301 1383 tao
    }
2302
    catch (Exception e)
2303
    {
2304
      throw e;
2305
    }
2306
    return parser;
2307
  }
2308
2309
2310 396 jones
  /**
2311 407 jones
   * Set up the parser handlers for writing the document to the database
2312
   */
2313 1383 tao
  /*private static XMLReader initializeParser(DBConnection dbconn, String action,
2314 956 tao
                               String docid, String rev, boolean validate,
2315 802 bojilova
                                   String user, String[] groups, String pub,
2316 695 bojilova
                                   int serverCode, Reader dtd)
2317 598 bojilova
                           throws Exception
2318
  {
2319 407 jones
    XMLReader parser = null;
2320 1217 tao
    //DBConnection conn = null;
2321
    //int serialNumber = -1;
2322 407 jones
    //
2323
    // Set up the SAX document handlers for parsing
2324
    //
2325
    try {
2326 1217 tao
       //check out DBConnection
2327 1383 tao
2328 956 tao
      //create a DBSAXHandler object which has the revision specification
2329 1217 tao
      ContentHandler chandler = new DBSAXHandler(dbconn, action,
2330
                                    docid, rev, user, groups, pub, serverCode);
2331
      EntityResolver eresolver= new DBEntityResolver(dbconn,
2332 645 bojilova
                                                 (DBSAXHandler)chandler, dtd);
2333 1217 tao
      DTDHandler dtdhandler   = new DBDTDHandler(dbconn);
2334 407 jones
2335
      // Get an instance of the parser
2336 802 bojilova
      String parserName = MetaCatUtil.getOption("saxparser");
2337 407 jones
      parser = XMLReaderFactory.createXMLReader(parserName);
2338
2339 660 bojilova
      // Turn on validation
2340 695 bojilova
      parser.setFeature("http://xml.org/sax/features/validation", validate);
2341 660 bojilova
      // Turn off Including all external parameter entities
2342
      // (the external DTD subset also)
2343
      // Doesn't work well, probably the feature name is not correct
2344
      // parser.setFeature(
2345
      //  "http://xml.org/sax/features/external-parameter-entities", false);
2346 407 jones
2347
      // Set Handlers in the parser
2348
      parser.setProperty("http://xml.org/sax/properties/declaration-handler",
2349
                         chandler);
2350
      parser.setProperty("http://xml.org/sax/properties/lexical-handler",
2351
                         chandler);
2352
      parser.setContentHandler((ContentHandler)chandler);
2353 598 bojilova
      parser.setEntityResolver((EntityResolver)eresolver);
2354 407 jones
      parser.setDTDHandler((DTDHandler)dtdhandler);
2355
      parser.setErrorHandler((ErrorHandler)chandler);
2356
2357
    } catch (Exception e) {
2358 457 bojilova
      throw e;
2359 407 jones
    }
2360 1217 tao
    //finally
2361
    //{
2362
      //DBConnectionPool.returnDBConnection(conn, serialNumber);
2363
    //}
2364 407 jones
2365
    return parser;
2366 1383 tao
  }*/
2367 407 jones
2368 1217 tao
  /**
2369
   * Save a document entry in the xml_revisions table
2370
   * Connection use as a paramter is in order to rollback feature
2371
   */
2372
  private static void archiveDocRevision(DBConnection dbconn, String docid,
2373
                                                    String user)
2374
 {
2375
    String sysdate = dbAdapter.getDateTimeFunction();
2376
    //DBConnection conn = null;
2377
    //int serialNumber = -1;
2378
    PreparedStatement pstmt = null;
2379
2380
    // create a record in xml_revisions table
2381
    // for that document as selected from xml_documents
2382
2383
   try
2384
   {
2385
     //check out DBConnection
2386
     /*conn=DBConnectionPool.
2387
                    getDBConnection("DocumentImpl.archiveDocRevision");
2388
     serialNumber=conn.getCheckOutSerialNumber();*/
2389
     pstmt = dbconn.prepareStatement(
2390
      "INSERT INTO xml_revisions " +
2391
        "(docid, rootnodeid, docname, doctype, " +
2392
        "user_owner, user_updated, date_created, date_updated, " +
2393
        "server_location, rev, public_access, catalog_id) " +
2394
      "SELECT ?, rootnodeid, docname, doctype, " +
2395
        "user_owner, ?, " + sysdate + ", " + sysdate + ", "+
2396
        "server_location, rev, public_access, catalog_id " +
2397
      "FROM xml_documents " +
2398
      "WHERE docid = ?");
2399
      // Increase dbconnection usage count
2400
      dbconn.increaseUsageCount(1);
2401
      // Bind the values to the query and execute it
2402
      pstmt.setString(1, docid);
2403
      pstmt.setString(2, user);
2404
      pstmt.setString(3, docid);
2405
      pstmt.execute();
2406
      pstmt.close();
2407
   }//try
2408
   catch (SQLException e)
2409
   {
2410
     MetaCatUtil.debugMessage("Error in DocumentImpl.archiveDocRevision : "+
2411
                                e.getMessage(), 30);
2412
   }//catch
2413
   finally
2414
   {
2415
     try
2416
     {
2417
       pstmt.close();
2418
     }//try
2419
     catch (SQLException ee)
2420
     {
2421
       MetaCatUtil.debugMessage("Error in DocumnetImpl.archiveDocRevision: "+
2422
                                  ee.getMessage(), 50);
2423
     }//catch
2424
     //finally
2425
     //{
2426
2427
       //check in DBConnection
2428
       //DBConnectionPool.returnDBConnection(conn, serialNumber);
2429
     //}//finally
2430
   }//finnally
2431
2432
2433
  }//achiveDocRevision
2434
2435 459 bojilova
  /** Save a document entry in the xml_revisions table */
2436 1217 tao
  private static void archiveDocRevision(String docid, String user)
2437 1063 tao
 {
2438 754 bojilova
    String sysdate = dbAdapter.getDateTimeFunction();
2439 1217 tao
    DBConnection conn = null;
2440
    int serialNumber = -1;
2441
    PreparedStatement pstmt = null;
2442
2443 459 bojilova
    // create a record in xml_revisions table
2444
    // for that document as selected from xml_documents
2445 1063 tao
2446
   try
2447
   {
2448 1217 tao
     //check out DBConnection
2449
     conn=DBConnectionPool.
2450
                    getDBConnection("DocumentImpl.archiveDocRevision");
2451
     serialNumber=conn.getCheckOutSerialNumber();
2452
     pstmt = conn.prepareStatement(
2453 459 bojilova
      "INSERT INTO xml_revisions " +
2454 771 bojilova
        "(docid, rootnodeid, docname, doctype, " +
2455 697 bojilova
        "user_owner, user_updated, date_created, date_updated, " +
2456
        "server_location, rev, public_access, catalog_id) " +
2457 771 bojilova
      "SELECT ?, rootnodeid, docname, doctype, " +
2458 747 bojilova
        "user_owner, ?, " + sysdate + ", " + sysdate + ", "+
2459
        "server_location, rev, public_access, catalog_id " +
2460 459 bojilova
      "FROM xml_documents " +
2461
      "WHERE docid = ?");
2462 1063 tao
      // Bind the values to the query and execute it
2463
      pstmt.setString(1, docid);
2464
      pstmt.setString(2, user);
2465
      pstmt.setString(3, docid);
2466
      pstmt.execute();
2467
      pstmt.close();
2468 1217 tao
   }//try
2469 1063 tao
   catch (SQLException e)
2470
   {
2471 1217 tao
     MetaCatUtil.debugMessage("Error in DocumentImpl.archiveDocRevision : "+
2472
                                e.getMessage(), 30);
2473
   }//catch
2474
   finally
2475
   {
2476
     try
2477
     {
2478
       pstmt.close();
2479
     }//try
2480
     catch (SQLException ee)
2481
     {
2482
       MetaCatUtil.debugMessage("Error in DocumnetImpl.archiveDocRevision: "+
2483
                                  ee.getMessage(), 50);
2484
     }//catch
2485
     finally
2486
     {
2487
       //check in DBConnection
2488
       DBConnectionPool.returnDBConnection(conn, serialNumber);
2489
     }//finally
2490
   }//finnally
2491
2492 459 bojilova
2493 1217 tao
  }//achiveDocRevision
2494 965 tao
2495
  /**
2496
    * delete a entry in xml_table for given docid
2497
    * @param docId, the id of the document need to be delete
2498
    */
2499 1217 tao
  private static void deleteXMLDocuments(String docId)
2500 965 tao
                                         throws SQLException
2501
  {
2502 1217 tao
    DBConnection conn = null;
2503
    int serialNumber = -1;
2504
    PreparedStatement pStmt = null;
2505
    try
2506
    {
2507
      //check out DBConnection
2508
      conn=DBConnectionPool.
2509
                    getDBConnection("DocumentImpl.deleteXMLDocuments");
2510
      serialNumber=conn.getCheckOutSerialNumber();
2511
      //delete a record
2512
      pStmt =
2513 965 tao
             conn.prepareStatement("DELETE FROM xml_documents WHERE docid = '"
2514
                                              + docId + "'");
2515
    pStmt.execute();
2516 1217 tao
    }//try
2517
    finally
2518
    {
2519
      try
2520
      {
2521
        pStmt.close();
2522
      }//try
2523
      catch (SQLException e)
2524
      {
2525
        MetaCatUtil.debugMessage("error in DocumentImpl.deleteXMLDocuments: "+
2526
                                  e.getMessage(), 50);
2527
      }//catch
2528
      finally
2529
      {
2530
        //return back DBconnection
2531
        DBConnectionPool.returnDBConnection(conn, serialNumber);
2532
      }//finally
2533
    }//finally
2534
2535 459 bojilova
2536 965 tao
  }//deleteXMLDocuments
2537
2538 407 jones
  /**
2539 965 tao
    * Get last revision number from database for a docid
2540
    * If couldn't find an entry,  -1 will return
2541
    * The return value is integer because we want compare it to there new one
2542
    * @param docid <sitecode>.<uniqueid> part of Accession Number
2543
    */
2544 1582 tao
  public static int getLatestRevisionNumber(String docId)
2545 965 tao
                                      throws SQLException
2546
  {
2547
    int rev = 1;
2548 1217 tao
    PreparedStatement pStmt = null;
2549
    DBConnection dbConn = null;
2550
    int serialNumber = -1;
2551 1582 tao
    // get rid of rev
2552
    docId = MetaCatUtil.getDocIdFromString(docId);
2553 1217 tao
    try
2554
    {
2555
      //check out DBConnection
2556
      dbConn=DBConnectionPool.
2557
                    getDBConnection("DocumentImpl.getLatestRevisionNumber");
2558
      serialNumber=dbConn.getCheckOutSerialNumber();
2559 965 tao
2560 1217 tao
      pStmt = dbConn.prepareStatement
2561 965 tao
              ("SELECT rev FROM xml_documents WHERE docid='" + docId + "'");
2562 1217 tao
      pStmt.execute();
2563 965 tao
2564 1217 tao
      ResultSet rs = pStmt.getResultSet();
2565
      boolean hasRow = rs.next();
2566
      if (hasRow)
2567
      {
2568
        rev = rs.getInt(1);
2569
        pStmt.close();
2570
      }
2571
      else
2572
      {
2573
        rev=-1;
2574
        pStmt.close();
2575
      }
2576
    }//try
2577
    finally
2578 965 tao
    {
2579 1217 tao
      try
2580
      {
2581
        pStmt.close();
2582
      }
2583
      catch (Exception ee)
2584
      {
2585
        MetaCatUtil.debugMessage("Error in DocumentImpl."+
2586
                        "getLatestRevisionNumber: "+ee.getMessage(), 50);
2587
      }
2588
      finally
2589
      {
2590
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2591
      }
2592
    }//finally
2593 965 tao
2594
    return rev;
2595
  }//getLatestRevisionNumber
2596
2597
  /**
2598 1012 tao
   * Get server location form database for a accNum
2599
   *
2600
   * @param accum <sitecode>.<uniqueid>.<rev>
2601
   */
2602 1217 tao
  private static int getServerLocationNumber(String accNum)
2603 1012 tao
                                            throws SQLException
2604
  {
2605
    //get rid of revNum part
2606
    String docId=MetaCatUtil.getDocIdFromString(accNum);
2607 1217 tao
    PreparedStatement pStmt = null;
2608
    int serverLocation = 1;
2609
    DBConnection conn = null;
2610
    int serialNumber = -1;
2611
2612
    try
2613
    {
2614
      //check out DBConnection
2615
      conn=DBConnectionPool.
2616
                    getDBConnection("DocumentImpl.getServerLocationNumber");
2617
      serialNumber=conn.getCheckOutSerialNumber();
2618 1012 tao
2619 1217 tao
      pStmt = conn.prepareStatement
2620 1012 tao
      ("SELECT server_location FROM xml_documents WHERE docid='" + docId + "'");
2621 1217 tao
      pStmt.execute();
2622 1012 tao
2623 1217 tao
      ResultSet rs = pStmt.getResultSet();
2624
      boolean hasRow = rs.next();
2625
      //if there is entry in xml_documents, get the serverlocation
2626
      if (hasRow)
2627
      {
2628
        serverLocation = rs.getInt(1);
2629
        pStmt.close();
2630
      }
2631
      else
2632
      {
2633
        //if htere is no entry in xml_documents, we consider it is new document
2634
        //the server location is local host and value is 1
2635
        serverLocation=1;
2636
        pStmt.close();
2637
      }
2638
    }//try
2639
    finally
2640 1012 tao
    {
2641 1217 tao
      try
2642
      {
2643
        pStmt.close();
2644
      }//try
2645
      catch (Exception ee)
2646
      {
2647
        MetaCatUtil.debugMessage("Error in DocumentImpl.getServerLocationNu(): "
2648
                                    +ee.getMessage(), 50);
2649
      }//catch
2650
      finally
2651
      {
2652
        DBConnectionPool.returnDBConnection(conn, serialNumber);
2653
      }//finally
2654
    }//finally
2655 1012 tao
2656
    return serverLocation;
2657
  }
2658 1055 tao
2659 1012 tao
  /**
2660 1055 tao
   * Given a server name, return its servercode in xml_replication table.
2661
   * If no server is found, -1 will return
2662
   * @param serverName,
2663
   */
2664
  private static int getServerCode(String serverName)
2665
  {
2666
    PreparedStatement pStmt=null;
2667
    int serverLocation=-2;
2668 1217 tao
    DBConnection dbConn = null;
2669
    int serialNumber = -1;
2670
    //MetaCatUtil util = new MetaCatUtil();
2671 1055 tao
2672
2673
    //we should consider about local host too
2674 1217 tao
    if (serverName.equals(MetaCatUtil.getLocalReplicationServerName()))
2675 1055 tao
    {
2676
      serverLocation=1;
2677
      return serverLocation;
2678
    }
2679
2680
2681
    try
2682
    {
2683
      //check xml_replication table
2684 1217 tao
      //dbConn=util.openDBConnection();
2685
      //check out DBConnection
2686
      dbConn=DBConnectionPool.getDBConnection("DocumentImpl.getServerCode");
2687
      serialNumber=dbConn.getCheckOutSerialNumber();
2688 1055 tao
      pStmt = dbConn.prepareStatement
2689
      ("SELECT serverid FROM xml_replication WHERE server='" + serverName +"'");
2690
      pStmt.execute();
2691
2692
      ResultSet rs = pStmt.getResultSet();
2693
      boolean hasRow = rs.next();
2694
      //if there is entry in xml_replication, get the serverid
2695
      if (hasRow)
2696
      {
2697
        serverLocation = rs.getInt(1);
2698
        pStmt.close();
2699
      }
2700
      else
2701
      {
2702
        // if htere is no entry in xml_replication, -1 will return
2703
        serverLocation=-1;
2704
        pStmt.close();
2705
      }
2706
    }
2707
    catch (Exception e)
2708
    {
2709 1217 tao
      MetaCatUtil.debugMessage("Error in DocumentImpl.getServerCode(): "
2710 1055 tao
                                    +e.getMessage(), 30);
2711
    }
2712
    finally
2713
    {
2714
      try
2715
      {
2716 1217 tao
        pStmt.close();
2717 1055 tao
      }
2718
      catch (Exception ee)
2719 1217 tao
      {
2720
        MetaCatUtil.debugMessage("Error in DocumentImpl.getServerCode(): "
2721
                                    +ee.getMessage(), 50);
2722
      }
2723
      finally
2724
      {
2725
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2726
      }
2727 1055 tao
    }
2728
2729
2730
    return serverLocation;
2731
  }
2732
2733
  /**
2734
   * Insert a server into xml_replcation table
2735
   * @param server, the name of server
2736
   */
2737 1292 tao
  private static synchronized void
2738
                                insertServerIntoReplicationTable(String server)
2739 1055 tao
  {
2740
    PreparedStatement pStmt=null;
2741 1217 tao
    DBConnection dbConn = null;
2742
    int serialNumber = -1;
2743 1292 tao
2744
    // Initial value for the server
2745
    int replicate = 0;
2746
    int dataReplicate = 0;
2747
    int hub = 0;
2748
2749 1055 tao
    try
2750
    {
2751 1292 tao
       // Get DBConnection
2752 1217 tao
       dbConn=DBConnectionPool.
2753
                getDBConnection("DocumentImpl.insertServIntoReplicationTable");
2754
       serialNumber=dbConn.getCheckOutSerialNumber();
2755 1292 tao
2756
      // Compare the server to dabase
2757
      pStmt = dbConn.prepareStatement
2758
      ("SELECT serverid FROM xml_replication WHERE server='" + server +"'");
2759
      pStmt.execute();
2760
      ResultSet rs = pStmt.getResultSet();
2761
      boolean hasRow = rs.next();
2762
      // Close preparedstatement and result set
2763
      pStmt.close();
2764
      rs.close();
2765
2766
      // If the server is not in the table, and server is not local host,
2767
      // insert it
2768
      if ( !hasRow
2769
         && !server.equals(MetaCatUtil.getLocalReplicationServerName()))
2770
      {
2771
        // Set auto commit false
2772
        dbConn.setAutoCommit(false);
2773 1751 tao
        /*pStmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
2774 1292 tao
                      "(server, last_checked, replicate, datareplicate, hub) " +
2775
                       "VALUES ('" + server + "', to_date(" +
2776
                       "'01/01/00', 'MM/DD/YY'), '" +
2777 1751 tao
                       replicate +"', '"+dataReplicate+"','"+ hub + "')");*/
2778
        pStmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
2779
                      "(server, last_checked, replicate, datareplicate, hub) " +
2780
                       "VALUES ('" + server + "', " +
2781 1758 tao
                       dbAdapter.toDate("01/01/1980", "MM/DD/YYYY") + ", '" +
2782 1292 tao
                       replicate +"', '"+dataReplicate+"','"+ hub + "')");
2783 1757 tao
2784 1751 tao
2785 1055 tao
        pStmt.execute();
2786 1292 tao
        dbConn.commit();
2787
        // Increase usage number
2788
        dbConn.increaseUsageCount(1);
2789 1055 tao
        pStmt.close();
2790 1292 tao
2791
      }
2792 1217 tao
    }//try
2793 1055 tao
    catch (Exception e)
2794
    {
2795 1217 tao
      MetaCatUtil.debugMessage("Error in DocumentImpl.insertServerIntoRepli(): "
2796 1055 tao
                                    +e.getMessage(), 30);
2797 1217 tao
    }//catch
2798 1055 tao
    finally
2799
    {
2800 1217 tao
2801 1055 tao
      try
2802
      {
2803 1292 tao
        // Set auto commit true
2804
        dbConn.setAutoCommit(true);
2805 1055 tao
        pStmt.close();
2806 1292 tao
2807 1217 tao
      }//try
2808
      catch (Exception ee)
2809
      {
2810
        MetaCatUtil.debugMessage("Error in DocumentImpl.insetServerIntoRepl(): "
2811
                                    +ee.getMessage(), 50);
2812
      }//catch
2813
      finally
2814
      {
2815
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2816 1055 tao
      }
2817 1217 tao
2818
    }//finally
2819 1055 tao
2820
  }
2821
2822
2823
  /**
2824 407 jones
   * the main routine used to test the DBWriter utility.
2825
   * <p>
2826
   * Usage: java DocumentImpl <-f filename -a action -d docid>
2827
   *
2828
   * @param filename the filename to be loaded into the database
2829
   * @param action the action to perform (READ, INSERT, UPDATE, DELETE)
2830
   * @param docid the id of the document to process
2831
   */
2832
  static public void main(String[] args) {
2833 1217 tao
    DBConnection dbconn = null;
2834
    int serialNumber = -1;
2835 407 jones
    try {
2836 555 bojilova
      String filename    = null;
2837 598 bojilova
      String dtdfilename = null;
2838 555 bojilova
      String action      = null;
2839
      String docid       = null;
2840 429 jones
      boolean showRuntime = false;
2841
      boolean useOldReadAlgorithm = false;
2842 407 jones
2843 408 jones
      // Parse the command line arguments
2844 407 jones
      for ( int i=0 ; i < args.length; ++i ) {
2845
        if ( args[i].equals( "-f" ) ) {
2846
          filename =  args[++i];
2847 598 bojilova
        } else if ( args[i].equals( "-r" ) ) {
2848
          dtdfilename =  args[++i];
2849 407 jones
        } else if ( args[i].equals( "-a" ) ) {
2850
          action =  args[++i];
2851
        } else if ( args[i].equals( "-d" ) ) {
2852
          docid =  args[++i];
2853 429 jones
        } else if ( args[i].equals( "-t" ) ) {
2854
          showRuntime = true;
2855
        } else if ( args[i].equals( "-old" ) ) {
2856
          useOldReadAlgorithm = true;
2857 407 jones
        } else {
2858
          System.err.println
2859
            ( "   args[" +i+ "] '" +args[i]+ "' ignored." );
2860
        }
2861
      }
2862
2863 408 jones
      // Check if the required arguments are provided
2864 407 jones
      boolean argsAreValid = false;
2865
      if (action != null) {
2866
        if (action.equals("INSERT")) {
2867
          if (filename != null) {
2868
            argsAreValid = true;
2869
          }
2870
        } else if (action.equals("UPDATE")) {
2871
          if ((filename != null) && (docid != null)) {
2872
            argsAreValid = true;
2873
          }
2874
        } else if (action.equals("DELETE")) {
2875
          if (docid != null) {
2876
            argsAreValid = true;
2877
          }
2878
        } else if (action.equals("READ")) {
2879
          if (docid != null) {
2880
            argsAreValid = true;
2881
          }
2882
        }
2883
      }
2884
2885 408 jones
      // Print usage message if the arguments are not valid
2886 407 jones
      if (!argsAreValid) {
2887
        System.err.println("Wrong number of arguments!!!");
2888
        System.err.println(
2889 598 bojilova
          "USAGE: java DocumentImpl [-t] <-a INSERT> [-d docid] <-f filename> "+
2890 680 bojilova
          "[-r dtdfilename]");
2891 407 jones
        System.err.println(
2892 598 bojilova
          "   OR: java DocumentImpl [-t] <-a UPDATE -d docid -f filename> " +
2893 680 bojilova
          "[-r dtdfilename]");
2894 407 jones
        System.err.println(
2895 429 jones
          "   OR: java DocumentImpl [-t] <-a DELETE -d docid>");
2896 407 jones
        System.err.println(
2897 429 jones
          "   OR: java DocumentImpl [-t] [-old] <-a READ -d docid>");
2898 407 jones
        return;
2899
      }
2900 429 jones
2901
      // Time the request if asked for
2902
      double startTime = System.currentTimeMillis();
2903
2904 407 jones
      // Open a connection to the database
2905
      MetaCatUtil util = new MetaCatUtil();
2906 1217 tao
2907
      dbconn=DBConnectionPool.getDBConnection("DocumentImpl.main");
2908
      serialNumber=dbconn.getCheckOutSerialNumber();
2909 407 jones
2910 463 berkley
      double connTime = System.currentTimeMillis();
2911 408 jones
      // Execute the action requested (READ, INSERT, UPDATE, DELETE)
2912 407 jones
      if (action.equals("READ")) {
2913 1217 tao
          DocumentImpl xmldoc = new DocumentImpl(docid );
2914 429 jones
          if (useOldReadAlgorithm) {
2915
            System.out.println(xmldoc.readUsingSlowAlgorithm());
2916
          } else {
2917 1480 tao
            xmldoc.toXml(new PrintWriter(System.out), null, null, true);
2918 429 jones
          }
2919 408 jones
      } else if (action.equals("DELETE")) {
2920 1217 tao
        DocumentImpl.delete(docid, null, null);
2921 408 jones
        System.out.println("Document deleted: " + docid);
2922 407 jones
      } else {
2923 1383 tao
        /*String newdocid = DocumentImpl.write(dbconn, filename, null,
2924 598 bojilova
                                             dtdfilename, action, docid,
2925
                                             null, null);
2926 408 jones
        if ((docid != null) && (!docid.equals(newdocid))) {
2927
          if (action.equals("INSERT")) {
2928
            System.out.println("New document ID generated!!! ");
2929
          } else if (action.equals("UPDATE")) {
2930
            System.out.println("ERROR: Couldn't update document!!! ");
2931 407 jones
          }
2932 408 jones
        } else if ((docid == null) && (action.equals("UPDATE"))) {
2933
          System.out.println("ERROR: Couldn't update document!!! ");
2934 407 jones
        }
2935 408 jones
        System.out.println("Document processing finished for: " + filename
2936 1383 tao
              + " (" + newdocid + ")");*/
2937 407 jones
      }
2938
2939 429 jones
      double stopTime = System.currentTimeMillis();
2940 463 berkley
      double dbOpenTime = (connTime - startTime)/1000;
2941
      double insertTime = (stopTime - connTime)/1000;
2942 429 jones
      double executionTime = (stopTime - startTime)/1000;
2943
      if (showRuntime) {
2944 463 berkley
        System.out.println("\n\nTotal Execution time was: " +
2945
                           executionTime + " seconds.");
2946
        System.out.println("Time to open DB connection was: " + dbOpenTime +
2947
                           " seconds.");
2948
        System.out.println("Time to insert document was: " + insertTime +
2949
                           " seconds.");
2950 429 jones
      }
2951 463 berkley
      dbconn.close();
2952 407 jones
    } catch (McdbException me) {
2953
      me.toXml(new PrintWriter(System.err));
2954
    } catch (AccessionNumberException ane) {
2955
      System.out.println(ane.getMessage());
2956
    } catch (Exception e) {
2957
      System.err.println("EXCEPTION HANDLING REQUIRED");
2958
      System.err.println(e.getMessage());
2959
      e.printStackTrace(System.err);
2960
    }
2961 1217 tao
    finally
2962
    {
2963
      // Return db connection
2964
      DBConnectionPool.returnDBConnection(dbconn, serialNumber);
2965
    }
2966 407 jones
  }
2967 393 jones
}