Project

General

Profile

1
/**
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: tao $'
10
 *     '$Date: 2003-02-27 18:23:18 -0800 (Thu, 27 Feb 2003) $'
11
 * '$Revision: 1432 $'
12
 *
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
 */
27

    
28
package edu.ucsb.nceas.metacat;
29

    
30
import java.sql.*;
31
import java.io.File;
32
import java.io.FileReader;
33
import java.io.IOException;
34
import java.io.PrintWriter;
35
import java.io.Reader;
36
import java.io.StringWriter;
37
import java.io.Writer;
38
import java.io.InputStreamReader;
39
import java.io.*;
40
import java.text.SimpleDateFormat;
41

    
42
import java.util.Date;
43
import java.util.Hashtable;
44
import java.util.Iterator;
45
import java.util.Stack;
46
import java.util.TreeSet;
47
import java.util.Vector;
48
import java.util.Enumeration;
49

    
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
import java.net.URL;
62

    
63
import edu.ucsb.nceas.dbadapter.AbstractDatabase;
64

    
65
/**
66
 * A class that represents an XML document. It can be created with a simple
67
 * document identifier from a database connection.  It also will write an
68
 * XML text document to a database connection using SAX.
69
 */
70
public class DocumentImpl {
71

    
72
   /* Constants */
73
   public static final String SCHEMA                 = "schema";
74
   public static final String DTD                    = "dtd";
75
   public static final String EML2                   = "eml2";
76
   public static final String EXTERNALSCHEMALOCATIONPROPERTY = 
77
              "http://apache.org/xml/properties/schema/external-schemaLocation";
78
   /*public static final String EXTERNALSCHEMALOCATION = 
79
     "eml://ecoinformatics.org/eml-2.0.0 http://dev.nceas.ucsb.edu/tao/schema/eml.xsd"+
80
      " http://www.xml-cml.org/schema/stmml http://dev.nceas.ucsb.edu/tao/schema/stmml.xsd";*/
81
   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
  
94
  
95
  static final int ALL = 1;
96
  static final int WRITE = 2;
97
  static final int READ = 4;
98
  private static final AbstractDatabase dbAdapter = MetaCatUtil.dbAdapter;
99

    
100
  private DBConnection connection = null;
101
  private String docid = null;
102
  private String updatedVersion=null;
103
  private String docname = null;
104
  private String doctype = null;
105
// DOCTITLE attr cleared from the db
106
//  private String doctitle = null;
107
  private String createdate = null;
108
  private String updatedate = null;
109
  private String system_id = null;
110
  private String userowner = null;
111
  private String userupdated = null;
112
  private int rev;
113
  private int serverlocation;
114
  private String docHomeServer;
115
  private String publicaccess; 
116
  private long rootnodeid;
117
  private ElementNode rootNode = null;
118
  private TreeSet nodeRecordList = null;
119
  //private static 
120
  //ReplicationServerList serverList = new ReplicationServerList();
121
  
122
  /**
123
   * Constructor used to create a document and read the document information
124
   * from the database.  If readNodes is false, then the node data is not 
125
   * read at this time, but is deferred until it is needed (such as when a 
126
   * call to toXml() is made).  
127
   *
128
   * @param conn the database connection from which to read the document
129
   * @param docid the identifier of the document to be created
130
   * @param readNodes flag indicating whether the xmlnodes should be read
131
   */
132
  public DocumentImpl(String docid, boolean readNodes) 
133
         throws McdbException 
134
  {
135
    try {
136
      //this.conn = conn;
137
      this.docid = docid;
138
      
139
      // Look up the document information
140
      getDocumentInfo(docid);
141
      
142
      if (readNodes) {
143
        // Download all of the document nodes using a single SQL query
144
        // The sort order of the records is determined by the NodeComparator
145
        // class, and needs to represent a depth-first traversal for the
146
        // toXml() method to work properly
147
        nodeRecordList = getNodeRecordList(rootnodeid);
148
        
149
      }
150
    
151
    } catch (McdbException ex) {
152
      throw ex;
153
    } catch (Throwable t) {
154
      throw new McdbException("Error reading document from " +
155
                              "DocumentImpl.DocumentImpl: " + docid);
156
    }
157
  }
158

    
159
  /**
160
   * Constructor, creates document from database connection, used 
161
   * for reading the document
162
   *
163
   * @param conn the database connection from which to read the document
164
   * @param docid the identifier of the document to be created
165
   */
166
  public DocumentImpl(String docid) throws McdbException 
167
  {
168
    this(docid, true);
169
  }
170

    
171
  /** 
172
   * Construct a new document instance, writing the contents to the database.
173
   * This method is called from DBSAXHandler because we need to know the
174
   * root element name for documents without a DOCTYPE before creating it.
175
   *
176
   * @param conn the JDBC Connection to which all information is written
177
   * @param rootnodeid - sequence id of the root node in the document
178
   * @param docname - the name of DTD, i.e. the name immediately following 
179
   *        the DOCTYPE keyword ( should be the root element name ) or
180
   *        the root element name if no DOCTYPE declaration provided
181
   *        (Oracle's and IBM parsers are not aware if it is not the 
182
   *        root element name)
183
   * @param doctype - Public ID of the DTD, i.e. the name immediately 
184
   *                  following the PUBLIC keyword in DOCTYPE declaration or
185
   *                  the docname if no Public ID provided or
186
   *                  null if no DOCTYPE declaration provided
187
   * @param docid the docid to use for the INSERT OR UPDATE
188
   * @param action the action to be performed (INSERT OR UPDATE)
189
   * @param user the user that owns the document
190
   * @param pub flag for public "read" access on document
191
   * @param serverCode the serverid from xml_replication on which this document
192
   *        resides.
193
   *
194
   */
195
  /*public DocumentImpl(Connection conn, long rootnodeid, String docname, 
196
                      String doctype, String docid, String action, String user,
197
                      String pub, String catalogid, int serverCode)
198
                      throws SQLException, Exception
199
  {
200
    this.conn = conn;
201
    this.rootnodeid = rootnodeid;
202
    this.docname = docname;
203
    this.doctype = doctype;
204
    this.docid = docid;
205
    writeDocumentToDB(action, user, pub, catalogid, serverCode);
206
  }*/
207
  
208
  /** 
209
   * Construct a new document instance, writing the contents to the database.
210
   * This method is called from DBSAXHandler because we need to know the
211
   * root element name for documents without a DOCTYPE before creating it.
212
   *
213
   * In this constructor, the docid is without rev. There is a string rev to 
214
   * specify the revision user want to upadate. The revion is only need to be
215
   * greater than current one. It is not need to be sequent number just after
216
   * current one. So it is only used in update action
217
   * @param conn the JDBC Connection to which all information is written
218
   * @param rootnodeid - sequence id of the root node in the document
219
   * @param docname - the name of DTD, i.e. the name immediately following 
220
   *        the DOCTYPE keyword ( should be the root element name ) or
221
   *        the root element name if no DOCTYPE declaration provided
222
   *        (Oracle's and IBM parsers are not aware if it is not the 
223
   *        root element name)
224
   * @param doctype - Public ID of the DTD, i.e. the name immediately 
225
   *                  following the PUBLIC keyword in DOCTYPE declaration or
226
   *                  the docname if no Public ID provided or
227
   *                  null if no DOCTYPE declaration provided
228
   * @param docid the docid to use for the UPDATE, no version number
229
   * @param version, need to be update
230
   * @param action the action to be performed (INSERT OR UPDATE)
231
   * @param user the user that owns the document
232
   * @param pub flag for public "read" access on document
233
   * @param serverCode the serverid from xml_replication on which this document
234
   *        resides.
235
   *
236
   */
237
  public DocumentImpl(DBConnection conn, long rootNodeId, String docName, 
238
                      String docType, String docId, String newRevision, 
239
                      String action, String user,
240
                      String pub, String catalogId, int serverCode)
241
                      throws SQLException, Exception
242
  {
243
    this.connection = conn;
244
    this.rootnodeid = rootNodeId;
245
    this.docname = docName;
246
    this.doctype = docType;
247
    this.docid = docId;
248
    this.updatedVersion = newRevision;
249
    writeDocumentToDB(action, user, pub, catalogId, serverCode);
250
  }
251
  
252
  /**
253
   * This method will be call in handleUploadRequest in MetacatServlet class
254
   */
255
  public static void registerDocument(
256
                     String docname, String doctype, String accnum, String user)
257
                     throws SQLException, AccessionNumberException, Exception
258
  {
259
    
260
    try
261
    {
262
       // get server location for this doc
263
      int serverLocation=getServerLocationNumber(accnum);
264
      registerDocument(docname, doctype,accnum, user, serverLocation);
265
    }
266
    catch (Exception e)
267
    {
268
      throw e;
269
    }
270
   
271
    
272
  }
273
  /**
274
   * Register a document that resides on the filesystem with the database.
275
   * (ie, just an entry in xml_documents, nothing in xml_nodes).
276
   * Creates a reference to a filesystem document (used for non-xml data files).
277
   * This class only be called in MetaCatServerlet.
278
   * @param conn the JDBC Connection to which all information is written
279
   * @param docname - the name of DTD, i.e. the name immediately following 
280
   *        the DOCTYPE keyword ( should be the root element name ) or
281
   *        the root element name if no DOCTYPE declaration provided
282
   *        (Oracle's and IBM parsers are not aware if it is not the 
283
   *        root element name)
284
   * @param doctype - Public ID of the DTD, i.e. the name immediately 
285
   *                  following the PUBLIC keyword in DOCTYPE declaration or
286
   *                  the docname if no Public ID provided or
287
   *                  null if no DOCTYPE declaration provided
288
   * @param accnum the accession number to use for the INSERT OR UPDATE, which 
289
   *               includes a revision number for this revision of the document 
290
   *               (e.g., knb.1.1)
291
   * @param user the user that owns the document
292
   * @param serverCode the serverid from xml_replication on which this document
293
   *        resides.
294
   */
295
  public static void registerDocument(
296
                     String docname, String doctype, String accnum, 
297
                     String user, int serverCode)
298
                     throws SQLException, AccessionNumberException, Exception
299
  {
300
    DBConnection dbconn = null;
301
    int serialNumber = -1;
302
    PreparedStatement pstmt = null;
303
    //MetaCatUtil util = new MetaCatUtil();
304
    AccessionNumber ac;
305
    try {
306
      //dbconn = util.openDBConnection();
307
      //check out DBConnection
308
      dbconn=DBConnectionPool.
309
                    getDBConnection("DocumentImpl.registerDocument");
310
      serialNumber=dbconn.getCheckOutSerialNumber();
311
      String docIdWithoutRev=MetaCatUtil.getDocIdFromString(accnum);
312
      int userSpecifyRev=MetaCatUtil.getVersionFromString(accnum);
313
      int revInDataBase=getLatestRevisionNumber(docIdWithoutRev);
314
      //revIndataBase=-1, there is no record in xml_documents table
315
      //the data file is a new one, inert it into table
316
      //user specified rev should be great than 0
317
      if (revInDataBase==-1 && userSpecifyRev>0 )
318
      {
319
        ac = new AccessionNumber(accnum, "insert");
320
      }
321
      //rev is greater the last revsion number and revInDataBase isn't -1
322
      // it is a updated data file
323
      else if (userSpecifyRev>revInDataBase && revInDataBase>0)
324
      {
325
        
326
        //archive the old entry 
327
        archiveDocRevision(docIdWithoutRev, user);
328
        //delete the old entry in xml_documents
329
        deleteXMLDocuments(docIdWithoutRev);
330
        ac = new AccessionNumber(accnum, "update");
331
      }
332
      //other situation
333
      else
334
      {
335
        
336
        throw new Exception("Revision number couldn't be "
337
                    +userSpecifyRev);
338
      }
339
      String docid = ac.getDocid();
340
      String rev = ac.getRev();
341
      SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
342
      Date localtime = new Date();
343
      String dateString = formatter.format(localtime);
344
  
345
      String sqlDateString = "to_date('" + dateString + 
346
                                          "', 'YY-MM-DD HH24:MI:SS')";
347
  
348
      StringBuffer sql = new StringBuffer();
349
      sql.append("insert into xml_documents (docid, docname, doctype, ");
350
      sql.append("user_owner, user_updated, server_location, rev,date_created");
351
      sql.append(", date_updated, public_access) values ('");
352
      sql.append(docid).append("','");
353
      sql.append(docname).append("','");
354
      sql.append(doctype).append("','");
355
      sql.append(user).append("','");
356
      sql.append(user).append("','");
357
      sql.append(serverCode).append("','");
358
      sql.append(rev).append("',");
359
      sql.append(sqlDateString).append(",");
360
      sql.append(sqlDateString).append(",");
361
      sql.append("'0')");
362
      pstmt = dbconn.prepareStatement(sql.toString());
363
      pstmt.execute();
364
      pstmt.close();
365
      //dbconn.close();
366
    } 
367
    finally 
368
    {
369
      try
370
      {
371
        pstmt.close();
372
      }
373
      finally
374
      {
375
        DBConnectionPool.returnDBConnection(dbconn, serialNumber);
376
      }
377
    }    
378
  }
379
  
380
    /**
381
   * Register a document that resides on the filesystem with the database.
382
   * (ie, just an entry in xml_documents, nothing in xml_nodes).
383
   * Creates a reference to a filesystem document (used for non-xml data files)
384
   * This method will be called for register data file in xml_documents in 
385
   * Replication.
386
   * This method is revised from registerDocument.
387
   *
388
   * @param conn the JDBC Connection to which all information is written
389
   * @param docname - the name of DTD, i.e. the name immediately following 
390
   *        the DOCTYPE keyword ( should be the root element name ) or
391
   *        the root element name if no DOCTYPE declaration provided
392
   *        (Oracle's and IBM parsers are not aware if it is not the 
393
   *        root element name)
394
   * @param doctype - Public ID of the DTD, i.e. the name immediately 
395
   *                  following the PUBLIC keyword in DOCTYPE declaration or
396
   *                  the docname if no Public ID provided or
397
   *                  null if no DOCTYPE declaration provided
398
   * @param accnum the accession number to use for the INSERT OR UPDATE, which 
399
   *               includes a revision number for this revision of the document 
400
   *               (e.g., knb.1.1)
401
   * @param user the user that owns the document
402
   * @param serverCode the serverid from xml_replication on which this document
403
   *        resides.
404
   */
405
  public static void registerDocumentInReplication(
406
                     String docname, String doctype, String accnum, 
407
                     String user, int serverCode)
408
                     throws SQLException, AccessionNumberException, Exception
409
  {
410
    DBConnection dbconn = null;
411
    int serialNumber = -1;
412
    //MetaCatUtil util = new MetaCatUtil();
413
    AccessionNumber ac;
414
    PreparedStatement pstmt = null;
415
    try {
416
      //dbconn = util.openDBConnection();
417
       dbconn=DBConnectionPool.
418
                  getDBConnection("DocumentImpl.registerDocumentInReplication");
419
      serialNumber=dbconn.getCheckOutSerialNumber();
420
      String docIdWithoutRev=MetaCatUtil.getDocIdFromString(accnum);
421
      int userSpecifyRev=MetaCatUtil.getVersionFromString(accnum);
422
      int revInDataBase=getLatestRevisionNumber(docIdWithoutRev);
423
      //revIndataBase=-1, there is no record in xml_documents table
424
      //the data file is a new one, inert it into table
425
      //user specified rev should be great than 0
426
      if (revInDataBase==-1 && userSpecifyRev>0 )
427
      {
428
       
429
        ac = new AccessionNumber(accnum, "insert");
430
      }
431
      //rev is greater the last revsion number and revInDataBase isn't -1
432
      // it is a updated data file
433
      else if (userSpecifyRev>revInDataBase && revInDataBase>0)
434
      {
435
        
436
        //archive the old entry 
437
        archiveDocRevision(docIdWithoutRev, user);
438
        //delete the old entry in xml_documents
439
        deleteXMLDocuments(docIdWithoutRev);
440
        ac = new AccessionNumber(accnum, "update");
441
      }
442
      // local server has newer version, then notify the remote server
443
      else if ( userSpecifyRev < revInDataBase && revInDataBase > 0)
444
      {
445
        throw new Exception("Local server: "+MetaCatUtil.getOption("server")+
446
                 " has newer revision of doc: "+docIdWithoutRev+"."
447
                  +revInDataBase+". Please notify it.");
448
      }
449
      //other situation
450
      else
451
      {
452
        
453
        throw new Exception("Revision number couldn't be "
454
                    +userSpecifyRev);
455
      }
456
      String docid = ac.getDocid();
457
      String rev = ac.getRev();
458
      SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
459
      Date localtime = new Date();
460
      String dateString = formatter.format(localtime);
461
  
462
      String sqlDateString = "to_date('" + dateString + 
463
                                          "', 'YY-MM-DD HH24:MI:SS')";
464
  
465
      StringBuffer sql = new StringBuffer();
466
      sql.append("insert into xml_documents (docid, docname, doctype, ");
467
      sql.append("user_owner, user_updated, server_location, rev,date_created");
468
      sql.append(", date_updated, public_access) values ('");
469
      sql.append(docid).append("','");
470
      sql.append(docname).append("','");
471
      sql.append(doctype).append("','");
472
      sql.append(user).append("','");
473
      sql.append(user).append("','");
474
      sql.append(serverCode).append("','");
475
      sql.append(rev).append("',");
476
      sql.append(sqlDateString).append(",");
477
      sql.append(sqlDateString).append(",");
478
      sql.append("'0')");
479
      // Set auto commit fasle
480
      dbconn.setAutoCommit(false);
481
      pstmt = dbconn.prepareStatement(sql.toString());
482
      pstmt.execute();
483
      // Commit the insert
484
      dbconn.commit();
485
      pstmt.close();
486
      //dbconn.close();
487
    } 
488
    finally 
489
    {
490
      // Set DBConnection auto commit true
491
      dbconn.setAutoCommit(true);
492
      pstmt.close();
493
      DBConnectionPool.returnDBConnection(dbconn, serialNumber);
494
    }    
495
  }
496
  
497
 /**
498
   * This method will register a data file entry in xml_documents and save a
499
   * data file input Stream into file system.. It is only used in replication
500
   *
501
   * @param  input, the input stream which contain the file content.
502
   * @param  , the input stream which contain the file content
503
   * @param docname - the name of DTD, for data file, it is a docid number.
504
   * @param doctype - "BIN" for data file
505
   * @param accnum the accession number to use for the INSERT OR UPDATE, which 
506
   *               includes a revision number for this revision of the document 
507
   *               (e.g., knb.1.1)
508
   * @param user the user that owns the document
509
   * @param docHomeServer, the home server of the docid
510
   * @param notificationServer, the server to notify force replication info to 
511
   *                            local metacat
512
   */
513
 public static void writeDataFileInReplication(InputStream input, 
514
                 String filePath, String docname, String doctype, String accnum, 
515
                   String user, String docHomeServer, String notificationServer)
516
                     throws SQLException, AccessionNumberException, Exception
517
 {
518
    int serverCode=-2;
519
   
520
    
521
    if (filePath==null||filePath.equals(""))
522
    {
523
      throw new 
524
            Exception("Please specify the directory where file will be store");
525
    }
526
    if (accnum==null||accnum.equals(""))
527
    {
528
      throw new Exception("Please specify the stored file name");
529
    }
530
    
531
   
532
    
533
    // If server is not int the xml replication talbe, insert it into 
534
    // xml_replication table
535
    //serverList.addToServerListIfItIsNot(docHomeServer);
536
    insertServerIntoReplicationTable(docHomeServer);
537
    
538
    // Get server code again
539
    serverCode = getServerCode(docHomeServer);
540
    
541
    
542
    //register data file into xml_documents table
543
    registerDocumentInReplication(docname, doctype, accnum, user, serverCode);
544
    //write inputstream into file system.
545
    File dataDirectory = new File(filePath);
546
    File newFile = new File(dataDirectory, accnum); 
547
       
548
    // create a buffered byte output stream
549
    // that uses a default-sized output buffer
550
    FileOutputStream fos = new FileOutputStream(newFile);
551
    BufferedOutputStream outPut = new BufferedOutputStream(fos);
552

    
553
    BufferedInputStream bis = null;
554
    bis = new BufferedInputStream(input);
555
    byte[] buf = new byte[4 * 1024]; // 4K buffer
556
    int b = bis.read(buf);
557
       
558
    while (b != -1) 
559
    {
560
        outPut.write(buf, 0, b);
561
        b = bis.read(buf);
562
    }
563
    bis.close();
564
	  outPut.close();
565
	  fos.close();
566
      
567
    // Force replicate data file
568
    ForceReplicationHandler forceReplication = new ForceReplicationHandler
569
                                    (accnum, false, notificationServer);
570
  
571
 }
572
  
573

    
574
  
575
  public static boolean getDataFileLockGrant(String accnum) 
576
                                                  throws Exception
577
  { 
578
    
579
    try
580
    {
581
      
582
      int serverLocation=getServerLocationNumber(accnum);
583
    
584
      return getDataFileLockGrant(accnum,serverLocation);
585
    }
586
    catch (Exception e)
587
    {
588
     
589
      throw e;
590
    }
591
  }
592
    
593
  /**
594
   * The method will check if metacat can get data file lock grant
595
   * If server code is 1, it get.
596
   * If server code is not 1 but call replication getlock successfully,
597
   * it get
598
   * else, it didn't get
599
   * @param accnum, the ID of the document 
600
   * @param action, the action to the document
601
   * @param serverCode, the server location code
602
   */
603
  public static boolean getDataFileLockGrant(String accnum, int serverCode)
604
                                          throws Exception 
605
  {
606
    boolean flag=true;
607
    //MetaCatUtil util = new MetaCatUtil();
608
    String docid = MetaCatUtil.getDocIdFromString(accnum);
609
    int rev = MetaCatUtil.getVersionFromString(accnum);
610
    
611
    if (serverCode == 1)
612
    {
613
      flag=true;
614
      return flag;
615
    }
616
    
617
    //if((serverCode != 1 && action.equals("UPDATE")) )
618
    if (serverCode != 1)
619
    { //if this document being written is not a resident of this server then
620
      //we need to try to get a lock from it's resident server.  If the
621
      //resident server will not give a lock then we send the user a message
622
      //saying that he/she needs to download a new copy of the file and
623
      //merge the differences manually.
624
      
625
      String server=MetacatReplication.getServerNameForServerCode(serverCode);
626
      MetacatReplication.replLog("attempting to lock " + accnum);
627
      URL u = new URL("https://" + server + "?server=" +
628
        MetaCatUtil.getLocalReplicationServerName()+"&action=getlock&updaterev=" 
629
           +rev + "&docid=" + docid);
630
      //System.out.println("sending message: " + u.toString());
631
      String serverResStr = MetacatReplication.getURLContent(u);
632
      String openingtag =serverResStr.substring(0, serverResStr.indexOf(">")+1);
633
      if(openingtag.equals("<lockgranted>"))
634
      {
635
        //the lock was granted go ahead with the insert
636
        //System.out.println("In lockgranted");
637
        MetacatReplication.replLog("lock granted for " + accnum + " from " +
638
                                      server);
639
        flag=true;  
640
        return flag;
641
      }//if
642

    
643
      else if(openingtag.equals("<filelocked>"))
644
      {//the file is currently locked by another user
645
       //notify our user to wait a few minutes, check out a new copy and try
646
       //again.
647
        //System.out.println("file locked");
648
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
649
                                   server + " reason: file already locked");
650
        throw new Exception("The file specified is already locked by another " +
651
                            "user.  Please wait 30 seconds, checkout the " +
652
                            "newer document, merge your changes and try " +
653
                            "again.");
654
      }
655
      else if(openingtag.equals("<outdatedfile>"))
656
      {//our file is outdated.  notify our user to check out a new copy of the
657
       //file and merge his version with the new version.
658
        //System.out.println("outdated file");
659
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
660
                                    server + " reason: local file outdated");
661
        throw new Exception("The file you are trying to update is an outdated" +
662
                            " version.  Please checkout the newest document, " +
663
                            "merge your changes and try again.");
664
      }//else if
665
    }//if
666
    
667
   return flag;
668
   
669
  }//getDataFileLockGrant
670
  
671
  /**
672
   * get the document name
673
   */
674
  public String getDocname() {
675
    return docname;
676
  }
677

    
678
  /**
679
   * get the document type (which is the PublicID)
680
   */
681
  public String getDoctype() {
682
    return doctype;
683
  }
684

    
685
  /**
686
   * get the system identifier
687
   */
688
  public String getSystemID() {
689
    return system_id;
690
  }
691

    
692
  /**
693
   * get the root node identifier
694
   */
695
  public long getRootNodeID() {
696
    return rootnodeid;
697
  }
698
  
699
  /**
700
   * get the creation date
701
   */
702
  public String getCreateDate() {
703
    return createdate;
704
  }
705
  
706
  /**
707
   * get the update date
708
   */
709
  public String getUpdateDate() {
710
    return updatedate;
711
  }
712

    
713
  /** 
714
   * Get the document identifier (docid)
715
   */
716
  public String getDocID() {
717
    return docid;
718
  }
719
  
720
// DOCTITLE attr cleared from the db
721
//  /**
722
//   *get the document title
723
//   */
724
//  public String getDocTitle() {
725
//    return doctitle;
726
//  }
727
  
728
  public String getUserowner() {
729
    return userowner;
730
  }
731
  
732
  public String getUserupdated() {
733
    return userupdated;
734
  }
735
  
736
  public int getServerlocation() {
737
    return serverlocation;
738
  }
739
  
740
  public String getDocHomeServer() {
741
    return docHomeServer;
742
  }
743
  
744
 
745
 
746
  public String getPublicaccess() {
747
    return publicaccess;
748
  }
749
  
750
  public int getRev() {
751
    return rev;
752
  }
753
  
754
   /**
755
   * Print a string representation of the XML document
756
   */
757
  public String toString(String user, String[] groups)
758
  {
759
    StringWriter docwriter = new StringWriter();
760
    try {
761
      this.toXml(docwriter, user, groups);
762
    } catch (McdbException mcdbe) {
763
      return null;
764
    }
765
    String document = docwriter.toString();
766
    return document;
767
  }
768

    
769
  /**
770
   * Get a text representation of the XML document as a string
771
   * This older algorithm uses a recursive tree of Objects to represent the
772
   * nodes of the tree.  Each object is passed the data for the document 
773
   * and searches all of the document data to find its children nodes and
774
   * recursively build.  Thus, because each node reads the whole document,
775
   * this algorithm is extremely slow for larger documents, and the time
776
   * to completion is O(N^N) wrt the number of nodes.  See toXml() for a
777
   * better algorithm.
778
   */
779
  public String readUsingSlowAlgorithm() throws McdbException
780
  {
781
    StringBuffer doc = new StringBuffer();
782

    
783
    // First, check that we have the needed node data, and get it if not
784
    if (nodeRecordList == null) {
785
      nodeRecordList = getNodeRecordList(rootnodeid);
786
    }
787

    
788
    // Create the elements from the downloaded data in the TreeSet
789
    rootNode = new ElementNode(nodeRecordList, rootnodeid);
790

    
791
    // Append the resulting document to the StringBuffer and return it
792
    doc.append("<?xml version=\"1.0\"?>\n");
793
      
794
    if (docname != null) {
795
      if ((doctype != null) && (system_id != null)) {
796
        doc.append("<!DOCTYPE " + docname + " PUBLIC \"" + doctype + 
797
                   "\" \"" + system_id + "\">\n");
798
      } else {
799
        doc.append("<!DOCTYPE " + docname + ">\n");
800
      }
801
    }
802
    doc.append(rootNode.toString());
803
  
804
    return (doc.toString());
805
  }
806

    
807
  /**
808
   * Print a text representation of the XML document to a Writer
809
   *
810
   * @param pw the Writer to which we print the document
811
   */
812
  public void toXml(Writer pw, String user, String[] groups) 
813
                                                          throws McdbException
814
  {
815
    PrintWriter out = null;
816
    if (pw instanceof PrintWriter) {
817
      out = (PrintWriter)pw;
818
    } else {
819
      out = new PrintWriter(pw);
820
    }
821

    
822
    MetaCatUtil util = new MetaCatUtil();
823
    
824
    // Here add code to handle subtree access control
825
    PermissionController control = new PermissionController(docid);
826
    Hashtable unaccessableSubTree =control.hasUnaccessableSubTree(user, groups, 
827
                                             AccessControlInterface.READSTRING);
828
    
829
    if (!unaccessableSubTree.isEmpty())
830
    {
831
       Enumeration en = unaccessableSubTree.elements();
832
       while (en.hasMoreElements())
833
       {
834
         SubTree tree = (SubTree)en.nextElement();
835
         //System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
836
         //System.out.println("subtree id pull out: "+tree.getSubTreeId());
837
         //System.out.println("start node id: "+tree.getStartNodeId());
838
         //System.out.println("end node id: "+tree.getEndNodeId());
839
       }
840
    }
841
    
842
    // First, check that we have the needed node data, and get it if not
843
    if (nodeRecordList == null) 
844
    {
845
      nodeRecordList = getNodeRecordList(rootnodeid);
846
    }
847

    
848
    Stack openElements = new Stack();
849
    boolean atRootElement = true;
850
    boolean previousNodeWasElement = false;
851

    
852
    // Step through all of the node records we were given
853
    Iterator it = nodeRecordList.iterator();
854
    while (it.hasNext()) {
855
      NodeRecord currentNode = (NodeRecord)it.next();
856
      //util.debugMessage("[Got Node ID: " + currentNode.nodeid +
857
                          //" (" + currentNode.parentnodeid +
858
                          //", " + currentNode.nodeindex + 
859
                          //", " + currentNode.nodetype + 
860
                          //", " + currentNode.nodename + 
861
                          //", " + currentNode.nodedata + ")]");
862
      // Print the end tag for the previous node if needed
863
      //
864
      // This is determined by inspecting the parent nodeid for the
865
      // currentNode.  If it is the same as the nodeid of the last element
866
      // that was pushed onto the stack, then we are still in that previous
867
      // parent element, and we do nothing.  However, if it differs, then we
868
      // have returned to a level above the previous parent, so we go into
869
      // a loop and pop off nodes and print out their end tags until we get
870
      // the node on the stack to match the currentNode parentnodeid
871
      //
872
      // So, this of course means that we rely on the list of elements
873
      // having been sorted in a depth first traversal of the nodes, which
874
      // is handled by the NodeComparator class used by the TreeSet
875
      if (!atRootElement) {
876
        NodeRecord currentElement = (NodeRecord)openElements.peek();
877
        if ( currentNode.parentnodeid != currentElement.nodeid ) {
878
          while ( currentNode.parentnodeid != currentElement.nodeid ) {
879
            currentElement = (NodeRecord)openElements.pop();
880
            util.debugMessage("\n POPPED: " + currentElement.nodename, 50);
881
            if (previousNodeWasElement) {
882
              out.print(">");
883
              previousNodeWasElement = false;
884
            }  
885
            if ( currentElement.nodeprefix != null ) {
886
              out.print("</" + currentElement.nodeprefix + ":" + 
887
                        currentElement.nodename + ">" );
888
            } else {
889
              out.print("</" + currentElement.nodename + ">" );
890
            }
891
            currentElement = (NodeRecord)openElements.peek();
892
          }
893
        }
894
      }
895

    
896
      // Handle the DOCUMENT node
897
      if (currentNode.nodetype.equals("DOCUMENT")) {
898
        out.println("<?xml version=\"1.0\"?>");
899
      
900
        if (docname != null) {
901
          if ((doctype != null) && (system_id != null)) {
902
            out.println("<!DOCTYPE " + docname + " PUBLIC \"" + doctype + 
903
                       "\" \"" + system_id + "\">");
904
          } else {
905
            out.println("<!DOCTYPE " + docname + ">");
906
          }
907
        }
908

    
909
      // Handle the ELEMENT nodes
910
      } else if (currentNode.nodetype.equals("ELEMENT")) {
911
        if (atRootElement) {
912
          atRootElement = false;
913
        } else {
914
          if (previousNodeWasElement) {
915
            out.print(">");
916
          }
917
        }
918
        openElements.push(currentNode);
919
        util.debugMessage("\n PUSHED: " + currentNode.nodename, 50);
920
        previousNodeWasElement = true;
921
        if ( currentNode.nodeprefix != null ) {
922
          out.print("<" + currentNode.nodeprefix + ":" + currentNode.nodename);
923
        } else {
924
          out.print("<" + currentNode.nodename);
925
        }
926

    
927
      // Handle the ATTRIBUTE nodes
928
      } else if (currentNode.nodetype.equals("ATTRIBUTE")) {
929
        if ( currentNode.nodeprefix != null ) {
930
          out.print(" " + currentNode.nodeprefix + ":" + currentNode.nodename +
931
                    "=\"" + currentNode.nodedata + "\"");
932
        } else {
933
          out.print(" " + currentNode.nodename + "=\"" +
934
                    currentNode.nodedata + "\"");
935
        }
936

    
937
      // Handle the NAMESPACE nodes
938
      } else if (currentNode.nodetype.equals("NAMESPACE")) {
939
        out.print(" xmlns:" + currentNode.nodename + "=\""
940
                 + currentNode.nodedata + "\"");
941

    
942
      // Handle the TEXT nodes
943
      } else if (currentNode.nodetype.equals("TEXT")) {
944
        if (previousNodeWasElement) {
945
          out.print(">");
946
        }
947
        out.print(currentNode.nodedata);
948
        previousNodeWasElement = false;
949

    
950
      // Handle the COMMENT nodes
951
      } else if (currentNode.nodetype.equals("COMMENT")) {
952
        if (previousNodeWasElement) {
953
          out.print(">");
954
        }
955
        out.print("<!--" + currentNode.nodedata + "-->");
956
        previousNodeWasElement = false;
957

    
958
      // Handle the PI nodes
959
      } else if (currentNode.nodetype.equals("PI")) {
960
        if (previousNodeWasElement) {
961
          out.print(">");
962
        }
963
        out.print("<?" + currentNode.nodename + " " +
964
                        currentNode.nodedata + "?>");
965
        previousNodeWasElement = false;
966

    
967
      // Handle any other node type (do nothing)
968
      } else {
969
        // Any other types of nodes are not handled.
970
        // Probably should throw an exception here to indicate this
971
      }
972
      out.flush();
973
    }
974

    
975
    // Print the final end tag for the root element
976
    while(!openElements.empty())
977
    {
978
      NodeRecord currentElement = (NodeRecord)openElements.pop();
979
      util.debugMessage("\n POPPED: " + currentElement.nodename, 50);
980
      if ( currentElement.nodeprefix != null ) {
981
        out.print("</" + currentElement.nodeprefix + ":" + 
982
                  currentElement.nodename + ">" );
983
      } else {
984
        out.print("</" + currentElement.nodename + ">" );
985
      }
986
    }
987
    out.flush();
988
  }
989
  
990
  private boolean isRevisionOnly(DocumentIdentifier docid) throws Exception
991
  {
992
    //System.out.println("inRevisionOnly");
993
    DBConnection dbconn = null;
994
    int serialNumber = -1;
995
    PreparedStatement pstmt =null;
996
    String rev = docid.getRev();
997
    String newid = docid.getIdentifier();
998
    try
999
    {
1000
      dbconn=DBConnectionPool.
1001
                    getDBConnection("DocumentImpl.isRevisionOnly");
1002
      serialNumber=dbconn.getCheckOutSerialNumber();
1003
      pstmt = dbconn.prepareStatement("select rev from xml_documents " +
1004
                                  "where docid like '" + newid + "'");
1005
      pstmt.execute();
1006
      ResultSet rs = pstmt.getResultSet();
1007
      boolean tablehasrows = rs.next();
1008
      if(rev.equals("newest") || rev.equals("all"))
1009
      {
1010
        return false;
1011
      }
1012
    
1013
      if(tablehasrows)
1014
      {
1015
        int r = rs.getInt(1);
1016
        pstmt.close();
1017
        if(new Integer(rev).intValue() == r)
1018
        { //the current revision in in xml_documents
1019
          //System.out.println("returning false");
1020
          return false;
1021
        }
1022
        else if(new Integer(rev).intValue() < r)
1023
        { //the current revision is in xml_revisions.
1024
          //System.out.println("returning true");
1025
          return true;
1026
        }
1027
        else if(new Integer(rev).intValue() > r)
1028
        { //error, rev cannot be greater than r
1029
          throw new Exception("requested revision cannot be greater than " +
1030
                            "the latest revision number.");
1031
        }
1032
      }
1033
      // Get miss docid and rev, throw to McdDocNotFoundException
1034
      String missDocId = MetaCatUtil.getDocIdFromString(docid.toString());
1035
      String missRevision = 
1036
                  MetaCatUtil.getRevisionStringFromString(docid.toString());
1037
      throw new McdbDocNotFoundException("the requested docid '" + 
1038
                docid.toString() + "' does not exist", missDocId, missRevision);
1039
    }//try
1040
    finally
1041
    {
1042
      pstmt.close();
1043
      DBConnectionPool.returnDBConnection(dbconn, serialNumber);
1044
    }//finally
1045
  }
1046

    
1047
  private void getDocumentInfo(String docid) throws McdbException, 
1048
                                        AccessionNumberException, Exception
1049
  {
1050
    getDocumentInfo(new DocumentIdentifier(docid));
1051
  }
1052
  
1053
  /**
1054
   * Look up the document type information from the database
1055
   *
1056
   * @param docid the id of the document to look up
1057
   */
1058
  private void getDocumentInfo(DocumentIdentifier docid) throws McdbException
1059
                                                          , Exception
1060
  {
1061
    DBConnection dbconn = null;
1062
    int serialNumber = -1;
1063
    PreparedStatement pstmt = null;
1064
    String table = "xml_documents";
1065
        
1066
    try
1067
    {
1068
      if(isRevisionOnly(docid))
1069
      { //pull the document from xml_revisions instead of from xml_documents;
1070
        table = "xml_revisions";
1071
      }
1072
    }
1073
    // catch a McdbDocNotFoundException throw it
1074
    catch (McdbDocNotFoundException notFound)
1075
    {
1076
      throw notFound;
1077
    }
1078
    catch(Exception e)
1079
    {
1080
      
1081
      MetaCatUtil.debugMessage("error in DocumentImpl.getDocumentInfo: " + 
1082
                          e.getMessage(), 30);
1083
      throw e;
1084
    }
1085
    
1086

    
1087
    
1088
    try 
1089
    {
1090
      dbconn=DBConnectionPool.getDBConnection("DocumentImpl.getDocumentInfo");
1091
      serialNumber=dbconn.getCheckOutSerialNumber();
1092
      StringBuffer sql = new StringBuffer();
1093
// DOCTITLE attr cleared from the db
1094
//      sql.append("SELECT docname, doctype, rootnodeid, doctitle, ");
1095
      sql.append("SELECT docname, doctype, rootnodeid, ");
1096
      sql.append("date_created, date_updated, user_owner, user_updated, ");
1097
      sql.append("server_location, public_access, rev");
1098
      sql.append(" FROM ").append(table);
1099
      sql.append(" WHERE docid LIKE '").append(docid.getIdentifier());
1100
      sql.append("' and rev like '").append(docid.getRev()).append("'");
1101
      //System.out.println(sql.toString());
1102
      pstmt =
1103
        dbconn.prepareStatement(sql.toString());
1104
      // Bind the values to the query
1105
      //pstmt.setString(1, docid.getIdentifier());
1106
      //pstmt.setString(2, docid.getRev());
1107

    
1108
      pstmt.execute();
1109
      ResultSet rs = pstmt.getResultSet();
1110
      boolean tableHasRows = rs.next();
1111
      if (tableHasRows) {
1112
        this.docname        = rs.getString(1);
1113
        this.doctype        = rs.getString(2);
1114
        this.rootnodeid     = rs.getLong(3);
1115
// DOCTITLE attr cleared from the db
1116
//        this.doctitle       = rs.getString(4);
1117
        this.createdate     = rs.getString(4);
1118
        this.updatedate     = rs.getString(5);
1119
        this.userowner      = rs.getString(6);
1120
        this.userupdated    = rs.getString(7);
1121
        this.serverlocation = rs.getInt(8);
1122
        this.publicaccess   = rs.getString(9);
1123
        this.rev            = rs.getInt(10);
1124
      } 
1125
      pstmt.close();
1126
      
1127
      //get doc  home server name
1128
      
1129
      pstmt = dbconn.prepareStatement("select server " +
1130
                        "from xml_replication where serverid = ?");
1131
      //because connection use twise here, so we need to increase one
1132
      dbconn.increaseUsageCount(1);
1133
      pstmt.setInt(1, serverlocation);
1134
      pstmt.execute();
1135
      rs = pstmt.getResultSet();
1136
      tableHasRows = rs.next();
1137
      if (tableHasRows)
1138
      {
1139
        
1140
          String server = rs.getString(1);
1141
          //get homeserver name
1142
          if(!server.equals("localhost"))
1143
          {
1144
            this.docHomeServer=server;
1145
          }
1146
          else
1147
          {
1148
            this.docHomeServer=MetaCatUtil.getLocalReplicationServerName();
1149
          }
1150
          MetaCatUtil.debugMessage("server: "+docHomeServer, 50);
1151
        
1152
      }
1153
      pstmt.close();
1154
      if (this.doctype != null) {
1155
        pstmt =
1156
          dbconn.prepareStatement("SELECT system_id " +
1157
                                  "FROM xml_catalog " +
1158
                                 "WHERE public_id = ?");
1159
        //should increase usage count again
1160
        dbconn.increaseUsageCount(1);
1161
        // Bind the values to the query
1162
        pstmt.setString(1, doctype);
1163
  
1164
        pstmt.execute();
1165
        rs = pstmt.getResultSet();
1166
        tableHasRows = rs.next();
1167
        if (tableHasRows) {
1168
          this.system_id  = rs.getString(1);
1169
        } 
1170
        pstmt.close();
1171
      }
1172
    } catch (SQLException e) {
1173
      System.out.println("error in DocumentImpl.getDocumentInfo: " + 
1174
                          e.getMessage());
1175
      e.printStackTrace(System.out);
1176
      throw new McdbException("Error accessing database connection in " +
1177
                              "DocumentImpl.getDocumentInfo: ", e);
1178
    }
1179
    finally
1180
    {
1181
      try
1182
      {
1183
        pstmt.close();
1184
      }
1185
      catch (SQLException ee)
1186
      {
1187
        MetaCatUtil.debugMessage("error in DocumentImple.getDocumentInfo: "
1188
                                    +ee.getMessage(), 30);
1189
      }//catch
1190
      finally
1191
      {
1192
        DBConnectionPool.returnDBConnection(dbconn, serialNumber);
1193
      }
1194
    }
1195

    
1196
    if (this.docname == null) {
1197
      throw new McdbDocNotFoundException("Document not found: " + docid,
1198
                                 docid.getIdentifier(), docid.getRev());
1199
    }
1200
  }
1201

    
1202
  /**
1203
   * Look up the node data from the database
1204
   *
1205
   * @param rootnodeid the id of the root node of the node tree to look up
1206
   */
1207
  private TreeSet getNodeRecordList(long rootnodeid) throws McdbException
1208
  {
1209
    PreparedStatement pstmt = null;
1210
    DBConnection dbconn = null;
1211
    int serialNumber = -1;
1212
    TreeSet nodeRecordList = new TreeSet(new NodeComparator());
1213
    long nodeid = 0;
1214
    long parentnodeid = 0;
1215
    long nodeindex = 0;
1216
    String nodetype = null;
1217
    String nodename = null;
1218
    String nodeprefix = null;
1219
    String nodedata = null;
1220
    String quotechar = dbAdapter.getStringDelimiter();
1221

    
1222
    try {
1223
      dbconn=DBConnectionPool.
1224
                    getDBConnection("DocumentImpl.getNodeRecordList");
1225
      serialNumber=dbconn.getCheckOutSerialNumber();
1226
      pstmt =
1227
      dbconn.prepareStatement("SELECT nodeid,parentnodeid,nodeindex, " +
1228
           "nodetype,nodename,nodeprefix,nodedata " +               
1229
           "FROM xml_nodes WHERE rootnodeid = ?");
1230

    
1231
      // Bind the values to the query
1232
      pstmt.setLong(1, rootnodeid);
1233

    
1234
      pstmt.execute();
1235
      ResultSet rs = pstmt.getResultSet();
1236
      boolean tableHasRows = rs.next();
1237
      while (tableHasRows) {
1238
        nodeid = rs.getLong(1);
1239
        parentnodeid = rs.getLong(2);
1240
        nodeindex = rs.getLong(3);
1241
        nodetype = rs.getString(4);
1242
        nodename = rs.getString(5);
1243
        nodeprefix = rs.getString(6);
1244
        nodedata = rs.getString(7);
1245
        nodedata = MetaCatUtil.normalize(nodedata);
1246
        // add the data to the node record list hashtable
1247
        NodeRecord currentRecord = new NodeRecord(nodeid,parentnodeid,nodeindex,
1248
                                      nodetype, nodename, nodeprefix, nodedata);
1249
        nodeRecordList.add(currentRecord);
1250

    
1251
        // Advance to the next node
1252
        tableHasRows = rs.next();
1253
      } 
1254
      pstmt.close();
1255

    
1256
    } catch (SQLException e) {
1257
      throw new McdbException("Error in DocumentImpl.getNodeRecordList " +
1258
                              e.getMessage());
1259
    }
1260
    finally
1261
    {
1262
      try
1263
      {
1264
        pstmt.close();
1265
      }
1266
      catch (SQLException ee)
1267
      {
1268
        MetaCatUtil.debugMessage("error in DocumentImpl.getNodeRecordList: "
1269
                                    +ee.getMessage(), 30);
1270
      }
1271
      finally
1272
      {
1273
        DBConnectionPool.returnDBConnection(dbconn, serialNumber);
1274
      }
1275
    }
1276
      
1277

    
1278
    if (nodeRecordList != null) {
1279
      return nodeRecordList;
1280
    } else {
1281
      throw new McdbException("Error getting node data: " + docid);
1282
    }
1283
  }
1284
  
1285
// NOT USED ANY MORE
1286
//  /** creates SQL code and inserts new document into DB connection 
1287
//   default serverCode of 1*/
1288
//  private void writeDocumentToDB(String action, String user)
1289
//               throws SQLException, Exception
1290
//  {
1291
//    writeDocumentToDB(action, user, null, 1);
1292
//  }
1293

    
1294
 /** creates SQL code and inserts new document into DB connection */
1295
  private void writeDocumentToDB(String action, String user, String pub, 
1296
                                 String catalogid, int serverCode) 
1297
               throws SQLException, Exception {
1298
    String sysdate = dbAdapter.getDateTimeFunction();
1299

    
1300
    try {
1301
      PreparedStatement pstmt = null;
1302

    
1303
      if (action.equals("INSERT")) {
1304
        //AccessionNumber ac = new AccessionNumber();
1305
        //this.docid = ac.generate(docid, "INSERT");
1306
        
1307
        pstmt = connection.prepareStatement(
1308
                "INSERT INTO xml_documents " +
1309
                "(docid, rootnodeid, docname, doctype, " + 
1310
                "user_owner, user_updated, date_created, date_updated, " + 
1311
                "public_access, catalog_id, server_location, rev) " +
1312
                "VALUES (?, ?, ?, ?, ?, ?, " + sysdate + ", " + sysdate + 
1313
                ", ?, ?, ?, ?)");
1314
        // Increase dbconnection usage count
1315
        connection.increaseUsageCount(1);
1316
        
1317
        //note that the server_location is set to 1. 
1318
        //this means that "localhost" in the xml_replication table must
1319
        //always be the first entry!!!!!
1320
        
1321
        // Bind the values to the query
1322
        pstmt.setString(1, this.docid);
1323
        pstmt.setLong(2, rootnodeid);
1324
        pstmt.setString(3, docname);
1325
        pstmt.setString(4, doctype);
1326
        pstmt.setString(5, user);
1327
        pstmt.setString(6, user);
1328
        //public access is usefulless, so set it to null
1329
        pstmt.setString(7, null);
1330
        /*if ( pub == null ) {
1331
          pstmt.setString(7, null);
1332
        } else if ( pub.toUpperCase().equals("YES") || pub.equals("1") ) {
1333
          pstmt.setInt(7, 1);
1334
        } else if ( pub.toUpperCase().equals("NO") || pub.equals("0") ) {
1335
          pstmt.setInt(7, 0);
1336
        }*/
1337
        pstmt.setString(8, catalogid);
1338
        pstmt.setInt(9, serverCode);
1339
        pstmt.setInt(10, Integer.parseInt(updatedVersion)); 
1340
      } else if (action.equals("UPDATE")) {
1341

    
1342
        // Save the old document publicaccessentry in a backup table
1343
        DocumentImpl.archiveDocRevision(connection, docid, user );
1344
        DocumentImpl thisdoc = new DocumentImpl(docid, false);
1345
        int thisrev = thisdoc.getRev();
1346
        
1347
        //if the updated vesion is not greater than current one,
1348
        //throw it into a exception
1349
        if (Integer.parseInt(updatedVersion)<=thisrev)
1350
        {
1351
          throw new Exception("Next revision number couldn't be less"
1352
                               +" than or equal "+ thisrev);
1353
        }
1354
        else
1355
        {
1356
          //set the user specified revision 
1357
          thisrev=Integer.parseInt(updatedVersion);
1358
        }
1359
        
1360
        // Delete index for the old version of docid
1361
        // The new index is inserting on the next calls to DBSAXNode
1362
        pstmt = connection.prepareStatement(
1363
                "DELETE FROM xml_index WHERE docid='" + this.docid + "'");
1364
        // Increase dbconnection usage count
1365
        connection.increaseUsageCount(1);
1366
        
1367
        pstmt.execute();
1368
        pstmt.close();
1369

    
1370
        // Update the new document to reflect the new node tree
1371
        pstmt = connection.prepareStatement(
1372
            "UPDATE xml_documents " +
1373
            "SET rootnodeid = ?, docname = ?, doctype = ?, " +
1374
            "user_updated = ?, date_updated = " + sysdate + ", " +
1375
            "server_location = ?, rev = ?, public_access = ?, catalog_id = ? " +
1376
            "WHERE docid = ?");
1377
        // Increase dbconnection usage count
1378
        connection.increaseUsageCount(1);
1379
        // Bind the values to the query
1380
        pstmt.setLong(1, rootnodeid);
1381
        pstmt.setString(2, docname);
1382
        pstmt.setString(3, doctype);
1383
        pstmt.setString(4, user);
1384
        pstmt.setInt(5, serverCode);
1385
        pstmt.setInt(6, thisrev);
1386
        pstmt.setString(7, null);
1387
        /*if ( pub == null ) {
1388
          pstmt.setString(7, null);
1389
        } else if ( pub.toUpperCase().equals("YES") || pub.equals("1") ) {
1390
          pstmt .setInt(7, 1);
1391
        } else if ( pub.toUpperCase().equals("NO") || pub.equals("0") ) {
1392
          pstmt.setInt(7, 0);
1393
        }*/
1394
        pstmt.setString(8, catalogid);
1395
        pstmt.setString(9, this.docid);
1396

    
1397
      } else {
1398
        System.err.println("Action not supported: " + action);
1399
      }
1400

    
1401
      // Do the insertion
1402
      pstmt.execute();
1403
      
1404
      pstmt.close();
1405

    
1406
    } catch (SQLException sqle) {
1407
      throw sqle;
1408
    } catch (Exception e) {
1409
      throw e;
1410
    }
1411
  }
1412

    
1413
  /**
1414
   * Write an XML file to the database, given a filename
1415
   *
1416
   * @param conn the JDBC connection to the database
1417
   * @param filename the filename to be loaded into the database
1418
   * @param pub flag for public "read" access on document
1419
   * @param dtdfilename the dtd to be uploaded on server's file system
1420
   * @param action the action to be performed (INSERT OR UPDATE)
1421
   * @param docid the docid to use for the INSERT OR UPDATE
1422
   * @param user the user that owns the document
1423
   * @param groups the groups to which user belongs
1424
   */
1425
  /*public static String write(DBConnection conn,String filename,
1426
                             String pub, String dtdfilename,
1427
                             String action, String docid, String user,
1428
                             String[] groups )
1429
                throws Exception {
1430
                  
1431
    Reader dtd = null;
1432
    if ( dtdfilename != null ) {
1433
      dtd = new FileReader(new File(dtdfilename).toString());
1434
    }
1435
    return write ( conn, new FileReader(new File(filename).toString()),
1436
                   pub, dtd, action, docid, user, groups, false);
1437
  }*/
1438

    
1439
  public static String write(DBConnection conn,Reader xml,String pub,Reader dtd,
1440
                             String action, String docid, String user,
1441
                             String[] groups, String ruleBase, 
1442
                             boolean needValidation)
1443
                throws Exception {
1444
    //this method will be called in handleUpdateOrInsert method 
1445
    //in MetacatServlet class and now is wrapper into documentImple
1446
    // get server location for this doc
1447
    int serverLocation=getServerLocationNumber(docid);
1448
    return write(conn,xml,pub,dtd,action,docid,user,groups,serverLocation,false,
1449
                 ruleBase, needValidation);
1450
  }
1451

    
1452
 
1453
  
1454
  /**
1455
   * Write an XML file to the database, given a Reader
1456
   *
1457
   * @param conn the JDBC connection to the database
1458
   * @param xml the xml stream to be loaded into the database
1459
   * @param pub flag for public "read" access on xml document
1460
   * @param dtd the dtd to be uploaded on server's file system
1461
   * @param action the action to be performed (INSERT or UPDATE)
1462
   * @param accnum the docid + rev# to use on INSERT or UPDATE
1463
   * @param user the user that owns the document
1464
   * @param groups the groups to which user belongs
1465
   * @param serverCode the serverid from xml_replication on which this document
1466
   *        resides.
1467
   * @param override flag to stop insert replication checking.
1468
   *        if override = true then a document not belonging to the local server
1469
   *        will not be checked upon update for a file lock.
1470
   *        if override = false then a document not from this server, upon 
1471
   *        update will be locked and version checked.
1472
   */
1473

    
1474
  public static String write(DBConnection conn, Reader xml,String pub,
1475
                         Reader dtd, String action, String accnum, String user,
1476
                         String[] groups, int serverCode, boolean override,
1477
                         String ruleBase, boolean needValidation)
1478
                throws Exception
1479
  {
1480
    // NEW - WHEN CLIENT ALWAYS PROVIDE ACCESSION NUMBER INCLUDING REV IN IT
1481
    //MetaCatUtil util = new MetaCatUtil();
1482
    MetaCatUtil.debugMessage("conn usage count before writting: "
1483
                                      +conn.getUsageCount(), 50);
1484
    AccessionNumber ac = new AccessionNumber(accnum, action);
1485
    String docid = ac.getDocid();
1486
    String rev = ac.getRev();
1487
    MetaCatUtil.debugMessage("action: " + action + " servercode: " + 
1488
                             serverCode + " override: " + override, 10);
1489
                     
1490
    if((serverCode != 1 && action.equals("UPDATE")) && !override)
1491
    { //if this document being written is not a resident of this server then
1492
      //we need to try to get a lock from it's resident server.  If the
1493
      //resident server will not give a lock then we send the user a message
1494
      //saying that he/she needs to download a new copy of the file and
1495
      //merge the differences manually.
1496
      int istreamInt; 
1497
      char istreamChar;
1498
     
1499
      // check for 'write' permission for 'user' to update this document
1500
      if ( !hasWritePermission(user, groups, docid) ) {
1501
        throw new Exception("User " + user + 
1502
              " does not have permission to update XML Document #" + accnum);
1503
      }        
1504
  
1505
      DocumentIdentifier id = new DocumentIdentifier(accnum);
1506
      String updaterev = id.getRev();
1507
      String server=MetacatReplication.getServerNameForServerCode(serverCode);
1508
      MetacatReplication.replLog("attempting to lock " + accnum);
1509
      URL u = new URL("https://" + server + "?server="+
1510
        MetaCatUtil.getLocalReplicationServerName()+"&action=getlock&updaterev=" 
1511
           +updaterev + "&docid=" + docid);
1512
      //System.out.println("sending message: " + u.toString());
1513
      String serverResStr = MetacatReplication.getURLContent(u);
1514
      String openingtag =serverResStr.substring(0, serverResStr.indexOf(">")+1);
1515
      if(openingtag.equals("<lockgranted>"))
1516
      {//the lock was granted go ahead with the insert
1517
        try 
1518
        {
1519
          //System.out.println("In lockgranted");
1520
          MetacatReplication.replLog("lock granted for " + accnum + " from " +
1521
                                      server);
1522
          /*XMLReader parser = initializeParser(conn, action, docid, updaterev,
1523
                               validate, user, groups, pub, serverCode, dtd);*/
1524
          XMLReader parser = initializeParser(conn, action, docid, updaterev,
1525
                                        user, groups, pub, serverCode, 
1526
                                        dtd,ruleBase, needValidation); 
1527
          conn.setAutoCommit(false);
1528
          parser.parse(new InputSource(xml)); 
1529
          conn.commit();
1530
          conn.setAutoCommit(true);
1531
        } 
1532
        catch (Exception e) 
1533
        {
1534
          conn.rollback();
1535
          conn.setAutoCommit(true);
1536
          throw e;
1537
        }
1538
                
1539
        
1540
        
1541
        // Force replication the docid
1542
        ForceReplicationHandler frh = new ForceReplicationHandler
1543
                                                          (accnum, true, null);
1544
        return(accnum);
1545
   
1546
      }
1547

    
1548
      else if(openingtag.equals("<filelocked>"))
1549
      {//the file is currently locked by another user
1550
       //notify our user to wait a few minutes, check out a new copy and try
1551
       //again.
1552
        //System.out.println("file locked");
1553
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
1554
                                   server + " reason: file already locked");
1555
        throw new Exception("The file specified is already locked by another " +
1556
                            "user.  Please wait 30 seconds, checkout the " +
1557
                            "newer document, merge your changes and try " +
1558
                            "again.");
1559
      }
1560
      else if(openingtag.equals("<outdatedfile>"))
1561
      {//our file is outdated.  notify our user to check out a new copy of the
1562
       //file and merge his version with the new version.
1563
        //System.out.println("outdated file");
1564
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
1565
                                    server + " reason: local file outdated");
1566
        throw new Exception("The file you are trying to update is an outdated" +
1567
                            " version.  Please checkout the newest document, " +
1568
                            "merge your changes and try again.");
1569
      }
1570
    }
1571
    
1572
    if ( action.equals("UPDATE") ) {
1573
      // check for 'write' permission for 'user' to update this document
1574

    
1575
      if ( !hasWritePermission(user, groups, docid) ) {
1576
        throw new Exception("User " + user + 
1577
              " does not have permission to update XML Document #" + accnum);
1578
      }          
1579
    }
1580

    
1581
    try 
1582
    { 
1583
      
1584
      XMLReader parser = initializeParser(conn, action, docid, rev, 
1585
                                          user, groups, pub, serverCode, 
1586
                                          dtd, ruleBase, needValidation);
1587
   
1588
      conn.setAutoCommit(false);
1589
      parser.parse(new InputSource(xml));
1590
      conn.commit();
1591
      conn.setAutoCommit(true);
1592
    } 
1593
    catch (Exception e) 
1594
    {
1595
      conn.rollback();
1596
      conn.setAutoCommit(true);
1597
      throw e;
1598
    }
1599
    
1600
    // Force replicate out the new document to each server in our server list.
1601
    // Start the thread to replicate this new document out to the other servers
1602
    // true mean it is xml document
1603
    // null is because no metacat notify the force replication.
1604
    ForceReplicationHandler frh = new ForceReplicationHandler
1605
                                                  (accnum, action, true, null);
1606
      
1607
   
1608
    MetaCatUtil.debugMessage("Conn Usage count after writting: "
1609
                                                      +conn.getUsageCount(),50); 
1610
    return(accnum);
1611
  }
1612

    
1613
  /**
1614
   * Write an XML file to the database during replication
1615
   *
1616
   * @param conn the JDBC connection to the database
1617
   * @param xml the xml stream to be loaded into the database
1618
   * @param pub flag for public "read" access on xml document
1619
   * @param dtd the dtd to be uploaded on server's file system
1620
   * @param action the action to be performed (INSERT or UPDATE)
1621
   * @param accnum the docid + rev# to use on INSERT or UPDATE
1622
   * @param user the user that owns the document
1623
   * @param groups the groups to which user belongs
1624
   * @param homeServer the name of server which the document origanlly create
1625
   * @param validate, if the xml document is valid or not
1626
   * @param notifyServer, the server which notify local server the force 
1627
   *                       replication command
1628
   */
1629

    
1630
  public static String writeReplication(DBConnection conn, Reader xml, 
1631
                                        String pub, Reader dtd, String action, 
1632
                                        String accnum, String user,
1633
                                        String[] groups,String homeServer, 
1634
                                        String notifyServer,
1635
                                        String ruleBase, boolean needValidation)
1636
                                        throws Exception
1637
  {
1638
    // Docid without revision
1639
    String docid=MetaCatUtil.getDocIdFromString(accnum);
1640
    // Revision specified by user (int)
1641
    int userSpecifyRev=MetaCatUtil.getVersionFromString(accnum);
1642
    // Revision for this docid in current database
1643
    int revInDataBase=getLatestRevisionNumber(docid);
1644
    // String to store the revision
1645
    String rev = null;
1646
   
1647
    
1648
    //revIndataBase=-1, there is no record in xml_documents table
1649
    //the document is a new one for local server, inert it into table
1650
    //user specified rev should be great than 0
1651
    if (revInDataBase==-1 && userSpecifyRev>0 )
1652
    {
1653
        // rev equals user specified
1654
        rev=(new Integer(userSpecifyRev)).toString();
1655
        // action should be INSERT
1656
        action = "INSERT";
1657
    }
1658
    //rev is greater the last revsion number and revInDataBase isn't -1
1659
    // it is a updated  file
1660
    else if (userSpecifyRev>revInDataBase && revInDataBase>0)
1661
    {
1662
       // rev equals user specified
1663
       rev=(new Integer(userSpecifyRev)).toString();
1664
       // action should be update
1665
       action = "UPDATE";
1666
    }
1667
    // local server has newer version, then notify the remote server
1668
    else if ( userSpecifyRev < revInDataBase && revInDataBase > 0)
1669
    {
1670
      throw new Exception("Local server: "+MetaCatUtil.getOption("server")+
1671
                " has newer revision of doc: "+docid+"."+revInDataBase
1672
                 +". Please notify it.");
1673
    }
1674
    //other situation
1675
    else
1676
    {
1677
        
1678
        throw new Exception("The docid"+docid+"'s revision number couldn't be "
1679
                    +userSpecifyRev);
1680
    }
1681
    // Variable to store homeserver code
1682
    int serverCode=-2;
1683
    
1684
     // If server is not int the xml replication talbe, insert it into
1685
    // xml_replication table
1686
    //serverList.addToServerListIfItIsNot(homeServer);
1687
    insertServerIntoReplicationTable(homeServer);
1688
    // Get server code again
1689
    serverCode = getServerCode(homeServer);
1690
    
1691
    
1692
    MetaCatUtil.debugMessage("Document "+docid+"."+rev+" "+action+ " into local"
1693
                               +" metacat with servercode: "+ serverCode, 10);
1694
                        
1695
  
1696
    // insert into xml_nodes and xml_index table
1697
    try 
1698
    { 
1699
      
1700
      XMLReader parser = initializeParser(conn, action, docid, rev,
1701
                                          user, groups, pub, serverCode, dtd,
1702
                                          ruleBase, needValidation);
1703
      conn.setAutoCommit(false);
1704
      parser.parse(new InputSource(xml));
1705
      conn.commit();
1706
      conn.setAutoCommit(true);
1707
    } 
1708
    catch (Exception e) 
1709
    {
1710
      conn.rollback();
1711
      conn.setAutoCommit(true);
1712
      throw e;
1713
    }
1714
    
1715
    //Force replication to other server
1716
    ForceReplicationHandler forceReplication = new ForceReplicationHandler
1717
                                  (accnum, action, true, notifyServer);
1718
    
1719

    
1720
    return(accnum);
1721
  }
1722

    
1723
  
1724
  /**
1725
   * Delete an XML file from the database (actually, just make it a revision
1726
   * in the xml_revisions table)
1727
   *
1728
   * @param docid the ID of the document to be deleted from the database
1729
   */
1730
  public static void delete(String accnum,
1731
                                 String user, String[] groups )
1732
                throws Exception 
1733
  {
1734
    // OLD
1735
    //DocumentIdentifier id = new DocumentIdentifier(accnum);
1736
    //String docid = id.getIdentifier();
1737
    //String rev = id.getRev();
1738
    
1739
    // OLD
1740
    // Determine if the docid,rev are OK for DELETE
1741
    //AccessionNumber ac = new AccessionNumber(conn);
1742
    //docid = ac.generate(docid, rev, "DELETE");
1743
    DBConnection conn = null;
1744
    int serialNumber = -1;
1745
    PreparedStatement pstmt =null;
1746
    try
1747
    {
1748
      //check out DBConnection
1749
      conn=DBConnectionPool.
1750
                    getDBConnection("DocumentImpl.delete");
1751
      serialNumber=conn.getCheckOutSerialNumber();
1752

    
1753
      // NEW - WHEN CLIENT ALWAYS PROVIDE ACCESSION NUMBER INCLUDING REV IN IT
1754
      AccessionNumber ac = new AccessionNumber(accnum, "DELETE");
1755
      String docid = ac.getDocid();
1756
      String rev = ac.getRev();
1757
    
1758

    
1759
    // check for 'write' permission for 'user' to delete this document
1760
      if ( !hasWritePermission(user, groups, docid) ) {
1761
        throw new Exception("User " + user + 
1762
              " does not have permission to delete XML Document #" + accnum);
1763
      }
1764

    
1765
      conn.setAutoCommit(false);
1766
      // Copy the record to the xml_revisions table
1767
      DocumentImpl.archiveDocRevision(conn, docid, user );
1768

    
1769
      // Now delete it from the xml_index table
1770
      pstmt = conn.prepareStatement("DELETE FROM xml_index WHERE docid = ?");
1771
      pstmt.setString(1,docid);
1772
      pstmt.execute();
1773
      pstmt.close();
1774
      conn.increaseUsageCount(1);
1775
      
1776
      //stmt.execute("DELETE FROM xml_access WHERE docid = '" + docid + "'");
1777
      // Now delete it from xml_access table
1778
      pstmt = conn.
1779
              prepareStatement("DELETE FROM xml_access WHERE accessfileid = ?");
1780
      pstmt.setString(1, docid);
1781
      pstmt.execute();
1782
      pstmt.close();
1783
      conn.increaseUsageCount(1);
1784
      
1785
      // Delete it from relation table
1786
      pstmt = conn.
1787
               prepareStatement("DELETE FROM xml_relation WHERE docid = ?");
1788
      //increase usage count
1789
      conn.increaseUsageCount(1);
1790
      pstmt.setString(1, docid);
1791
      pstmt.execute();
1792
      pstmt.close();
1793
      
1794
      // Delete it from xml_doucments table
1795
      pstmt =conn.prepareStatement("DELETE FROM xml_documents WHERE docid = ?");
1796
      pstmt.setString(1, docid);
1797
      pstmt.execute();
1798
      pstmt.close();
1799
      //Usaga count increase 1
1800
      conn.increaseUsageCount(1);
1801
      
1802
      conn.commit();
1803
      conn.setAutoCommit(true);
1804
    }//try
1805
    finally
1806
    {
1807
      
1808
      try
1809
      {
1810
        // close preparedStatement
1811
        pstmt.close();
1812
      }//try
1813
      finally
1814
      {
1815
        //check in DBonnection
1816
        DBConnectionPool.returnDBConnection(conn, serialNumber);
1817
      }//finally
1818
    }//finally
1819
    //IF this is a package document:
1820
    //delete all of the relations that this document created.
1821
    //if the deleted document is a package document its relations should 
1822
    //no longer be active if it has been deleted from the system.
1823
    
1824
  }
1825

    
1826
  /** 
1827
    * Check for "WRITE" permission on @docid for @user and/or @groups 
1828
    * from DB connection 
1829
    */
1830
  private static boolean hasWritePermission (String user,
1831
                                  String[] groups, String docid ) 
1832
                  throws SQLException, Exception
1833
  {
1834
    // Check for WRITE permission on @docid for @user and/or @groups
1835
    PermissionController controller = new PermissionController(docid);
1836
    return controller.hasPermission(user,groups,
1837
                                    AccessControlInterface.WRITESTRING);
1838
  }
1839

    
1840
  /** 
1841
    * Check for "READ" permission base on docid, user and group
1842
    *@docid, the document
1843
    *@user, user name
1844
    *@group, user's group
1845
    * 
1846
    */
1847
  public static boolean hasReadPermission (String user,
1848
                                  String[] groups, String docId ) 
1849
                  throws SQLException, Exception
1850
  {
1851
    // Check for READ permission on @docid for @user and/or @groups
1852
    PermissionController controller = 
1853
                        new PermissionController(docId);
1854
    return controller.hasPermission(user,groups,
1855
                                            AccessControlInterface.READSTRING);
1856
  }  
1857

    
1858
  
1859
   /**
1860
   * Set up the parser handlers for writing the document to the database
1861
   */
1862
  private static XMLReader initializeParser(DBConnection dbconn, String action,
1863
                                            String docid, String rev, 
1864
                                            String user, 
1865
                                            String[] groups, String pub, 
1866
                                            int serverCode, Reader dtd,
1867
                                            String ruleBase, 
1868
                                            boolean needValidation) 
1869
                                            throws Exception 
1870
  {
1871
    XMLReader parser = null;
1872
    try 
1873
    {
1874
      // handler
1875
      ContentHandler chandler;
1876
      EntityResolver eresolver;
1877
      DTDHandler dtdhandler;  
1878
      // Get an instance of the parser
1879
      String parserName = MetaCatUtil.getOption("saxparser");
1880
      parser = XMLReaderFactory.createXMLReader(parserName);
1881
      if (ruleBase != null && ruleBase.equals(EML2))
1882
      {
1883
        MetaCatUtil.debugMessage("eml 2 parser", 20);
1884
        chandler = new EmlSAXHandler(dbconn, action, 
1885
                                    docid, rev, user, groups, pub, serverCode);
1886
        parser.setContentHandler((ContentHandler)chandler);
1887
        parser.setErrorHandler((ErrorHandler)chandler);
1888
        parser.setProperty(DECLARATIONHANDLERPROPERTY, chandler);
1889
        parser.setProperty(LEXICALPROPERTY, chandler);
1890
        // turn on schema validation feature
1891
        parser.setFeature(VALIDATIONFEATURE, true);
1892
        parser.setFeature(NAMESPACEFEATURE, true);
1893
        //parser.setFeature(NAMESPACEPREFIXESFEATURE, true);
1894
        parser.setFeature(SCHEMAVALIDATIONFEATURE, true);
1895
        // From DB to find the register external schema location
1896
        String externalSchemaLocation = null;
1897
        SchemaLocationResolver resolver = new SchemaLocationResolver();
1898
        externalSchemaLocation = resolver.getNameSpaceAndLocationString();
1899
        // Set external schemalocation.
1900
        if (externalSchemaLocation != null && 
1901
            !(externalSchemaLocation.trim()).equals(""))
1902
        {
1903
            parser.setProperty(EXTERNALSCHEMALOCATIONPROPERTY,
1904
                             externalSchemaLocation);
1905
        }
1906
      }
1907
      else
1908
      {
1909
        //create a DBSAXHandler object which has the revision specification
1910
        chandler = new DBSAXHandler(dbconn, action, 
1911
                                    docid, rev, user, groups, pub, serverCode);
1912
        parser.setContentHandler((ContentHandler)chandler);
1913
        parser.setErrorHandler((ErrorHandler)chandler);
1914
        parser.setProperty(DECLARATIONHANDLERPROPERTY, chandler);
1915
        parser.setProperty(LEXICALPROPERTY, chandler);
1916
      
1917
        if (ruleBase != null && ruleBase.equals(SCHEMA) && needValidation)
1918
        {
1919
          MetaCatUtil.debugMessage("General schema parser", 20);
1920
          // turn on schema validation feature
1921
          parser.setFeature(VALIDATIONFEATURE, true);
1922
          parser.setFeature(NAMESPACEFEATURE, true);
1923
          //parser.setFeature(NAMESPACEPREFIXESFEATURE, true);
1924
          parser.setFeature(SCHEMAVALIDATIONFEATURE, true);
1925
          // From DB to find the register external schema location
1926
          String externalSchemaLocation = null;
1927
          SchemaLocationResolver resolver = new SchemaLocationResolver();
1928
          externalSchemaLocation = resolver.getNameSpaceAndLocationString();
1929
          // Set external schemalocation.
1930
          if (externalSchemaLocation != null && 
1931
            !(externalSchemaLocation.trim()).equals(""))
1932
          {
1933
            parser.setProperty(EXTERNALSCHEMALOCATIONPROPERTY,
1934
                             externalSchemaLocation);
1935
          }
1936
     
1937
        }
1938
        else if (ruleBase != null && ruleBase.equals(DTD) && needValidation)
1939
        {
1940
          MetaCatUtil.debugMessage("dtd parser", 20);
1941
          // turn on dtd validaton feature
1942
          parser.setFeature(VALIDATIONFEATURE, true);
1943
          eresolver= new DBEntityResolver(dbconn, (DBSAXHandler)chandler, dtd);
1944
          dtdhandler = new DBDTDHandler(dbconn);
1945
          parser.setEntityResolver((EntityResolver)eresolver);
1946
          parser.setDTDHandler((DTDHandler)dtdhandler);
1947
        }
1948
        else
1949
        {
1950
          MetaCatUtil.debugMessage("other parser", 20);
1951
          // non validation
1952
          parser.setFeature(VALIDATIONFEATURE, false);
1953
          eresolver= new DBEntityResolver(dbconn, (DBSAXHandler)chandler, dtd);
1954
          dtdhandler = new DBDTDHandler(dbconn);
1955
          parser.setEntityResolver((EntityResolver)eresolver);
1956
          parser.setDTDHandler((DTDHandler)dtdhandler);
1957
        }
1958
      }//else
1959
    } 
1960
    catch (Exception e) 
1961
    {
1962
      throw e;
1963
    }
1964
    return parser;
1965
  }
1966

    
1967
  
1968
  /**
1969
   * Set up the parser handlers for writing the document to the database
1970
   */
1971
  /*private static XMLReader initializeParser(DBConnection dbconn, String action,
1972
                               String docid, String rev, boolean validate, 
1973
                                   String user, String[] groups, String pub, 
1974
                                   int serverCode, Reader dtd) 
1975
                           throws Exception 
1976
  {
1977
    XMLReader parser = null;
1978
    //DBConnection conn = null;
1979
    //int serialNumber = -1;
1980
    //
1981
    // Set up the SAX document handlers for parsing
1982
    //
1983
    try {
1984
       //check out DBConnection
1985
     
1986
      //create a DBSAXHandler object which has the revision specification
1987
      ContentHandler chandler = new DBSAXHandler(dbconn, action, 
1988
                                    docid, rev, user, groups, pub, serverCode);
1989
      EntityResolver eresolver= new DBEntityResolver(dbconn,
1990
                                                 (DBSAXHandler)chandler, dtd);
1991
      DTDHandler dtdhandler   = new DBDTDHandler(dbconn);
1992

    
1993
      // Get an instance of the parser
1994
      String parserName = MetaCatUtil.getOption("saxparser");
1995
      parser = XMLReaderFactory.createXMLReader(parserName);
1996

    
1997
      // Turn on validation
1998
      parser.setFeature("http://xml.org/sax/features/validation", validate);
1999
      // Turn off Including all external parameter entities
2000
      // (the external DTD subset also)
2001
      // Doesn't work well, probably the feature name is not correct
2002
      // parser.setFeature(
2003
      //  "http://xml.org/sax/features/external-parameter-entities", false);
2004
      
2005
      // Set Handlers in the parser
2006
      parser.setProperty("http://xml.org/sax/properties/declaration-handler",
2007
                         chandler);
2008
      parser.setProperty("http://xml.org/sax/properties/lexical-handler",
2009
                         chandler);
2010
      parser.setContentHandler((ContentHandler)chandler);
2011
      parser.setEntityResolver((EntityResolver)eresolver);
2012
      parser.setDTDHandler((DTDHandler)dtdhandler);
2013
      parser.setErrorHandler((ErrorHandler)chandler);
2014

    
2015
    } catch (Exception e) {
2016
      throw e;
2017
    }
2018
    //finally
2019
    //{
2020
      //DBConnectionPool.returnDBConnection(conn, serialNumber);
2021
    //}
2022

    
2023
    return parser;
2024
  }*/
2025

    
2026
  /**
2027
   * Save a document entry in the xml_revisions table 
2028
   * Connection use as a paramter is in order to rollback feature
2029
   */
2030
  private static void archiveDocRevision(DBConnection dbconn, String docid, 
2031
                                                    String user) 
2032
 {
2033
    String sysdate = dbAdapter.getDateTimeFunction();
2034
    //DBConnection conn = null;
2035
    //int serialNumber = -1;
2036
    PreparedStatement pstmt = null;
2037
    
2038
    // create a record in xml_revisions table 
2039
    // for that document as selected from xml_documents
2040
   
2041
   try
2042
   {
2043
     //check out DBConnection
2044
     /*conn=DBConnectionPool.
2045
                    getDBConnection("DocumentImpl.archiveDocRevision");
2046
     serialNumber=conn.getCheckOutSerialNumber();*/
2047
     pstmt = dbconn.prepareStatement(
2048
      "INSERT INTO xml_revisions " +
2049
        "(docid, rootnodeid, docname, doctype, " +
2050
        "user_owner, user_updated, date_created, date_updated, " +
2051
        "server_location, rev, public_access, catalog_id) " +
2052
      "SELECT ?, rootnodeid, docname, doctype, " + 
2053
        "user_owner, ?, " + sysdate + ", " + sysdate + ", "+
2054
        "server_location, rev, public_access, catalog_id " +
2055
      "FROM xml_documents " +
2056
      "WHERE docid = ?");
2057
      // Increase dbconnection usage count
2058
      dbconn.increaseUsageCount(1);
2059
      // Bind the values to the query and execute it
2060
      pstmt.setString(1, docid);
2061
      pstmt.setString(2, user);
2062
      pstmt.setString(3, docid);
2063
      pstmt.execute();
2064
      pstmt.close();
2065
   }//try
2066
   catch (SQLException e)
2067
   {
2068
     MetaCatUtil.debugMessage("Error in DocumentImpl.archiveDocRevision : "+
2069
                                e.getMessage(), 30);
2070
   }//catch
2071
   finally
2072
   {
2073
     try
2074
     {
2075
       pstmt.close();
2076
     }//try
2077
     catch (SQLException ee)
2078
     {
2079
       MetaCatUtil.debugMessage("Error in DocumnetImpl.archiveDocRevision: "+
2080
                                  ee.getMessage(), 50);
2081
     }//catch
2082
     //finally
2083
     //{
2084
       
2085
       //check in DBConnection
2086
       //DBConnectionPool.returnDBConnection(conn, serialNumber);
2087
     //}//finally
2088
   }//finnally
2089
                                  
2090

    
2091
  }//achiveDocRevision
2092
  
2093
  /** Save a document entry in the xml_revisions table */
2094
  private static void archiveDocRevision(String docid, String user) 
2095
 {
2096
    String sysdate = dbAdapter.getDateTimeFunction();
2097
    DBConnection conn = null;
2098
    int serialNumber = -1;
2099
    PreparedStatement pstmt = null;
2100
    
2101
    // create a record in xml_revisions table 
2102
    // for that document as selected from xml_documents
2103
   
2104
   try
2105
   {
2106
     //check out DBConnection
2107
     conn=DBConnectionPool.
2108
                    getDBConnection("DocumentImpl.archiveDocRevision");
2109
     serialNumber=conn.getCheckOutSerialNumber();
2110
     pstmt = conn.prepareStatement(
2111
      "INSERT INTO xml_revisions " +
2112
        "(docid, rootnodeid, docname, doctype, " +
2113
        "user_owner, user_updated, date_created, date_updated, " +
2114
        "server_location, rev, public_access, catalog_id) " +
2115
      "SELECT ?, rootnodeid, docname, doctype, " + 
2116
        "user_owner, ?, " + sysdate + ", " + sysdate + ", "+
2117
        "server_location, rev, public_access, catalog_id " +
2118
      "FROM xml_documents " +
2119
      "WHERE docid = ?");
2120
      // Bind the values to the query and execute it
2121
      pstmt.setString(1, docid);
2122
      pstmt.setString(2, user);
2123
      pstmt.setString(3, docid);
2124
      pstmt.execute();
2125
      pstmt.close();
2126
   }//try
2127
   catch (SQLException e)
2128
   {
2129
     MetaCatUtil.debugMessage("Error in DocumentImpl.archiveDocRevision : "+
2130
                                e.getMessage(), 30);
2131
   }//catch
2132
   finally
2133
   {
2134
     try
2135
     {
2136
       pstmt.close();
2137
     }//try
2138
     catch (SQLException ee)
2139
     {
2140
       MetaCatUtil.debugMessage("Error in DocumnetImpl.archiveDocRevision: "+
2141
                                  ee.getMessage(), 50);
2142
     }//catch
2143
     finally
2144
     {
2145
       //check in DBConnection
2146
       DBConnectionPool.returnDBConnection(conn, serialNumber);
2147
     }//finally
2148
   }//finnally
2149
                                  
2150

    
2151
  }//achiveDocRevision
2152
  
2153
  /**
2154
    * delete a entry in xml_table for given docid
2155
    * @param docId, the id of the document need to be delete
2156
    */
2157
  private static void deleteXMLDocuments(String docId) 
2158
                                         throws SQLException 
2159
  {
2160
    DBConnection conn = null;
2161
    int serialNumber = -1;
2162
    PreparedStatement pStmt = null;
2163
    try
2164
    {
2165
      //check out DBConnection
2166
      conn=DBConnectionPool.
2167
                    getDBConnection("DocumentImpl.deleteXMLDocuments");
2168
      serialNumber=conn.getCheckOutSerialNumber();
2169
      //delete a record 
2170
      pStmt = 
2171
             conn.prepareStatement("DELETE FROM xml_documents WHERE docid = '" 
2172
                                              + docId + "'");
2173
    pStmt.execute();
2174
    }//try
2175
    finally
2176
    {
2177
      try
2178
      {
2179
        pStmt.close();
2180
      }//try
2181
      catch (SQLException e)
2182
      {
2183
        MetaCatUtil.debugMessage("error in DocumentImpl.deleteXMLDocuments: "+
2184
                                  e.getMessage(), 50);
2185
      }//catch
2186
      finally
2187
      {
2188
        //return back DBconnection
2189
        DBConnectionPool.returnDBConnection(conn, serialNumber);
2190
      }//finally
2191
    }//finally
2192
      
2193

    
2194
  }//deleteXMLDocuments
2195
  
2196
  /**
2197
    * Get last revision number from database for a docid
2198
    * If couldn't find an entry,  -1 will return
2199
    * The return value is integer because we want compare it to there new one
2200
    * @param docid <sitecode>.<uniqueid> part of Accession Number
2201
    */
2202
  private static int getLatestRevisionNumber(String docId)
2203
                                      throws SQLException
2204
  {
2205
    int rev = 1;
2206
    PreparedStatement pStmt = null;
2207
    DBConnection dbConn = null;
2208
    int serialNumber = -1;
2209
    
2210
    try
2211
    {
2212
      //check out DBConnection
2213
      dbConn=DBConnectionPool.
2214
                    getDBConnection("DocumentImpl.getLatestRevisionNumber");
2215
      serialNumber=dbConn.getCheckOutSerialNumber();
2216
     
2217
      pStmt = dbConn.prepareStatement
2218
              ("SELECT rev FROM xml_documents WHERE docid='" + docId + "'");
2219
      pStmt.execute();
2220

    
2221
      ResultSet rs = pStmt.getResultSet();
2222
      boolean hasRow = rs.next();
2223
      if (hasRow)
2224
      {
2225
        rev = rs.getInt(1);
2226
        pStmt.close();
2227
      }
2228
      else
2229
      {
2230
        rev=-1;
2231
        pStmt.close();
2232
      }
2233
    }//try
2234
    finally
2235
    {
2236
      try
2237
      {
2238
        pStmt.close();
2239
      }
2240
      catch (Exception ee)
2241
      {
2242
        MetaCatUtil.debugMessage("Error in DocumentImpl."+
2243
                        "getLatestRevisionNumber: "+ee.getMessage(), 50);
2244
      }
2245
      finally
2246
      {
2247
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2248
      }
2249
    }//finally  
2250
      
2251
    return rev;
2252
  }//getLatestRevisionNumber
2253
  
2254
  /**
2255
   * Get server location form database for a accNum
2256
   * 
2257
   * @param accum <sitecode>.<uniqueid>.<rev>
2258
   */
2259
  private static int getServerLocationNumber(String accNum)
2260
                                            throws SQLException
2261
  {
2262
    //get rid of revNum part
2263
    String docId=MetaCatUtil.getDocIdFromString(accNum);
2264
    PreparedStatement pStmt = null;
2265
    int serverLocation = 1;
2266
    DBConnection conn = null;
2267
    int serialNumber = -1;
2268
    
2269
    try
2270
    {
2271
      //check out DBConnection
2272
      conn=DBConnectionPool.
2273
                    getDBConnection("DocumentImpl.getServerLocationNumber");
2274
      serialNumber=conn.getCheckOutSerialNumber();
2275
     
2276
      pStmt = conn.prepareStatement
2277
      ("SELECT server_location FROM xml_documents WHERE docid='" + docId + "'");
2278
      pStmt.execute();
2279

    
2280
      ResultSet rs = pStmt.getResultSet();
2281
      boolean hasRow = rs.next();
2282
      //if there is entry in xml_documents, get the serverlocation
2283
      if (hasRow)
2284
      {
2285
        serverLocation = rs.getInt(1);
2286
        pStmt.close();
2287
      }
2288
      else
2289
      {
2290
        //if htere is no entry in xml_documents, we consider it is new document
2291
        //the server location is local host and value is 1
2292
        serverLocation=1;
2293
        pStmt.close();
2294
      }
2295
    }//try
2296
    finally
2297
    {
2298
      try
2299
      {
2300
        pStmt.close();
2301
      }//try
2302
      catch (Exception ee)
2303
      {
2304
        MetaCatUtil.debugMessage("Error in DocumentImpl.getServerLocationNu(): "
2305
                                    +ee.getMessage(), 50);
2306
      }//catch
2307
      finally
2308
      {
2309
        DBConnectionPool.returnDBConnection(conn, serialNumber);
2310
      }//finally
2311
    }//finally
2312
      
2313
    return serverLocation;
2314
  }
2315
  
2316
  /**
2317
   * Given a server name, return its servercode in xml_replication table.
2318
   * If no server is found, -1 will return
2319
   * @param serverName, 
2320
   */
2321
  private static int getServerCode(String serverName) 
2322
  {
2323
    PreparedStatement pStmt=null;
2324
    int serverLocation=-2;
2325
    DBConnection dbConn = null;
2326
    int serialNumber = -1;
2327
    //MetaCatUtil util = new MetaCatUtil();
2328
    
2329
    
2330
    //we should consider about local host too
2331
    if (serverName.equals(MetaCatUtil.getLocalReplicationServerName()))
2332
    { 
2333
      serverLocation=1;
2334
      return serverLocation;
2335
    }
2336
    
2337
   
2338
    try
2339
    {
2340
      //check xml_replication table
2341
      //dbConn=util.openDBConnection();
2342
      //check out DBConnection
2343
      dbConn=DBConnectionPool.getDBConnection("DocumentImpl.getServerCode");
2344
      serialNumber=dbConn.getCheckOutSerialNumber();
2345
      pStmt = dbConn.prepareStatement
2346
      ("SELECT serverid FROM xml_replication WHERE server='" + serverName +"'");
2347
      pStmt.execute();
2348

    
2349
      ResultSet rs = pStmt.getResultSet();
2350
      boolean hasRow = rs.next();
2351
      //if there is entry in xml_replication, get the serverid
2352
      if (hasRow)
2353
      {
2354
        serverLocation = rs.getInt(1);
2355
        pStmt.close();
2356
      }
2357
      else
2358
      {
2359
        // if htere is no entry in xml_replication, -1 will return
2360
        serverLocation=-1;
2361
        pStmt.close();
2362
      }
2363
    }
2364
    catch (Exception e)
2365
    {
2366
      MetaCatUtil.debugMessage("Error in DocumentImpl.getServerCode(): "
2367
                                    +e.getMessage(), 30);
2368
    }
2369
    finally
2370
    {
2371
      try
2372
      {
2373
        pStmt.close();
2374
      }
2375
      catch (Exception ee)
2376
      {
2377
        MetaCatUtil.debugMessage("Error in DocumentImpl.getServerCode(): "
2378
                                    +ee.getMessage(), 50);
2379
      }
2380
      finally
2381
      {
2382
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2383
      }
2384
    }
2385
                 
2386
      
2387
    return serverLocation;
2388
  }
2389
  
2390
  /**
2391
   * Insert a server into xml_replcation table
2392
   * @param server, the name of server 
2393
   */
2394
  private static synchronized void 
2395
                                insertServerIntoReplicationTable(String server)
2396
  {
2397
    PreparedStatement pStmt=null;
2398
    DBConnection dbConn = null;
2399
    int serialNumber = -1;
2400
    
2401
    // Initial value for the server
2402
    int replicate = 0;
2403
    int dataReplicate = 0;
2404
    int hub = 0;
2405
   
2406
    try
2407
    {
2408
       // Get DBConnection
2409
       dbConn=DBConnectionPool.
2410
                getDBConnection("DocumentImpl.insertServIntoReplicationTable");
2411
       serialNumber=dbConn.getCheckOutSerialNumber();
2412
      
2413
      // Compare the server to dabase
2414
      pStmt = dbConn.prepareStatement
2415
      ("SELECT serverid FROM xml_replication WHERE server='" + server +"'");
2416
      pStmt.execute();
2417
      ResultSet rs = pStmt.getResultSet();
2418
      boolean hasRow = rs.next();
2419
      // Close preparedstatement and result set
2420
      pStmt.close();
2421
      rs.close();
2422
      
2423
      // If the server is not in the table, and server is not local host,
2424
      // insert it
2425
      if ( !hasRow 
2426
         && !server.equals(MetaCatUtil.getLocalReplicationServerName()))
2427
      {
2428
        // Set auto commit false
2429
        dbConn.setAutoCommit(false);
2430
        pStmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
2431
                      "(server, last_checked, replicate, datareplicate, hub) " +
2432
                       "VALUES ('" + server + "', to_date(" +
2433
                       "'01/01/00', 'MM/DD/YY'), '" +
2434
                       replicate +"', '"+dataReplicate+"','"+ hub + "')");
2435
        pStmt.execute();
2436
        dbConn.commit();
2437
        // Increase usage number
2438
        dbConn.increaseUsageCount(1);
2439
        pStmt.close();
2440
        
2441
      }
2442
    }//try
2443
    catch (Exception e)
2444
    {
2445
      MetaCatUtil.debugMessage("Error in DocumentImpl.insertServerIntoRepli(): "
2446
                                    +e.getMessage(), 30);
2447
    }//catch
2448
    finally
2449
    {
2450
     
2451
      try
2452
      {
2453
        // Set auto commit true
2454
        dbConn.setAutoCommit(true);
2455
        pStmt.close();
2456
        
2457
      }//try
2458
      catch (Exception ee)
2459
      {
2460
        MetaCatUtil.debugMessage("Error in DocumentImpl.insetServerIntoRepl(): "
2461
                                    +ee.getMessage(), 50);
2462
      }//catch
2463
      finally
2464
      {
2465
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2466
      }
2467
    
2468
    }//finally
2469

    
2470
  }
2471
  
2472
  
2473
  /**
2474
   * the main routine used to test the DBWriter utility.
2475
   * <p>
2476
   * Usage: java DocumentImpl <-f filename -a action -d docid>
2477
   *
2478
   * @param filename the filename to be loaded into the database
2479
   * @param action the action to perform (READ, INSERT, UPDATE, DELETE)
2480
   * @param docid the id of the document to process
2481
   */
2482
  static public void main(String[] args) {
2483
    DBConnection dbconn = null;
2484
    int serialNumber = -1;
2485
    try {
2486
      String filename    = null;
2487
      String dtdfilename = null;
2488
      String action      = null;
2489
      String docid       = null;
2490
      boolean showRuntime = false;
2491
      boolean useOldReadAlgorithm = false;
2492

    
2493
      // Parse the command line arguments
2494
      for ( int i=0 ; i < args.length; ++i ) {
2495
        if ( args[i].equals( "-f" ) ) {
2496
          filename =  args[++i];
2497
        } else if ( args[i].equals( "-r" ) ) {
2498
          dtdfilename =  args[++i];
2499
        } else if ( args[i].equals( "-a" ) ) {
2500
          action =  args[++i];
2501
        } else if ( args[i].equals( "-d" ) ) {
2502
          docid =  args[++i];
2503
        } else if ( args[i].equals( "-t" ) ) {
2504
          showRuntime = true;
2505
        } else if ( args[i].equals( "-old" ) ) {
2506
          useOldReadAlgorithm = true;
2507
        } else {
2508
          System.err.println
2509
            ( "   args[" +i+ "] '" +args[i]+ "' ignored." );
2510
        }
2511
      }
2512
      
2513
      // Check if the required arguments are provided
2514
      boolean argsAreValid = false;
2515
      if (action != null) {
2516
        if (action.equals("INSERT")) {
2517
          if (filename != null) {
2518
            argsAreValid = true;
2519
          } 
2520
        } else if (action.equals("UPDATE")) {
2521
          if ((filename != null) && (docid != null)) {
2522
            argsAreValid = true;
2523
          } 
2524
        } else if (action.equals("DELETE")) {
2525
          if (docid != null) {
2526
            argsAreValid = true;
2527
          } 
2528
        } else if (action.equals("READ")) {
2529
          if (docid != null) {
2530
            argsAreValid = true;
2531
          } 
2532
        } 
2533
      } 
2534

    
2535
      // Print usage message if the arguments are not valid
2536
      if (!argsAreValid) {
2537
        System.err.println("Wrong number of arguments!!!");
2538
        System.err.println(
2539
          "USAGE: java DocumentImpl [-t] <-a INSERT> [-d docid] <-f filename> "+
2540
          "[-r dtdfilename]");
2541
        System.err.println(
2542
          "   OR: java DocumentImpl [-t] <-a UPDATE -d docid -f filename> " +
2543
          "[-r dtdfilename]");
2544
        System.err.println(
2545
          "   OR: java DocumentImpl [-t] <-a DELETE -d docid>");
2546
        System.err.println(
2547
          "   OR: java DocumentImpl [-t] [-old] <-a READ -d docid>");
2548
        return;
2549
      }
2550
      
2551
      // Time the request if asked for
2552
      double startTime = System.currentTimeMillis();
2553
      
2554
      // Open a connection to the database
2555
      MetaCatUtil util = new MetaCatUtil();
2556
     
2557
      dbconn=DBConnectionPool.getDBConnection("DocumentImpl.main");
2558
      serialNumber=dbconn.getCheckOutSerialNumber();
2559

    
2560
      double connTime = System.currentTimeMillis();
2561
      // Execute the action requested (READ, INSERT, UPDATE, DELETE)
2562
      if (action.equals("READ")) {
2563
          DocumentImpl xmldoc = new DocumentImpl(docid );
2564
          if (useOldReadAlgorithm) {
2565
            System.out.println(xmldoc.readUsingSlowAlgorithm());
2566
          } else {
2567
            xmldoc.toXml(new PrintWriter(System.out), null, null);
2568
          }
2569
      } else if (action.equals("DELETE")) {
2570
        DocumentImpl.delete(docid, null, null);
2571
        System.out.println("Document deleted: " + docid);
2572
      } else {
2573
        /*String newdocid = DocumentImpl.write(dbconn, filename, null,
2574
                                             dtdfilename, action, docid,
2575
                                             null, null);
2576
        if ((docid != null) && (!docid.equals(newdocid))) {
2577
          if (action.equals("INSERT")) {
2578
            System.out.println("New document ID generated!!! ");
2579
          } else if (action.equals("UPDATE")) {
2580
            System.out.println("ERROR: Couldn't update document!!! ");
2581
          }
2582
        } else if ((docid == null) && (action.equals("UPDATE"))) {
2583
          System.out.println("ERROR: Couldn't update document!!! ");
2584
        }
2585
        System.out.println("Document processing finished for: " + filename
2586
              + " (" + newdocid + ")");*/
2587
      }
2588

    
2589
      double stopTime = System.currentTimeMillis();
2590
      double dbOpenTime = (connTime - startTime)/1000;
2591
      double insertTime = (stopTime - connTime)/1000;
2592
      double executionTime = (stopTime - startTime)/1000;
2593
      if (showRuntime) {
2594
        System.out.println("\n\nTotal Execution time was: " + 
2595
                           executionTime + " seconds.");
2596
        System.out.println("Time to open DB connection was: " + dbOpenTime + 
2597
                           " seconds.");
2598
        System.out.println("Time to insert document was: " + insertTime +
2599
                           " seconds.");
2600
      }
2601
      dbconn.close();
2602
    } catch (McdbException me) {
2603
      me.toXml(new PrintWriter(System.err));
2604
    } catch (AccessionNumberException ane) {
2605
      System.out.println(ane.getMessage());
2606
    } catch (Exception e) {
2607
      System.err.println("EXCEPTION HANDLING REQUIRED");
2608
      System.err.println(e.getMessage());
2609
      e.printStackTrace(System.err);
2610
    }
2611
    finally
2612
    {
2613
      // Return db connection
2614
      DBConnectionPool.returnDBConnection(dbconn, serialNumber);
2615
    }
2616
  }
2617
}
(29-29/54)