Project

General

Profile

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