Project

General

Profile

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