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 429 jones
import java.util.Iterator;
44 407 jones
import java.util.Stack;
45 429 jones
import java.util.TreeSet;
46 577 berkley
import java.util.Enumeration;
47 407 jones
48
import org.xml.sax.AttributeList;
49
import org.xml.sax.ContentHandler;
50
import org.xml.sax.DTDHandler;
51
import org.xml.sax.EntityResolver;
52
import org.xml.sax.ErrorHandler;
53
import org.xml.sax.InputSource;
54
import org.xml.sax.XMLReader;
55
import org.xml.sax.SAXException;
56
import org.xml.sax.SAXParseException;
57
import org.xml.sax.helpers.XMLReaderFactory;
58
59 561 berkley
import java.net.URL;
60
61 777 bojilova
import edu.ucsb.nceas.dbadapter.AbstractDatabase;
62 747 bojilova
63 393 jones
/**
64
 * A class that represents an XML document. It can be created with a simple
65 407 jones
 * document identifier from a database connection.  It also will write an
66
 * XML text document to a database connection using SAX.
67 393 jones
 */
68
public class DocumentImpl {
69
70 425 bojilova
  static final int ALL = 1;
71
  static final int WRITE = 2;
72
  static final int READ = 4;
73 777 bojilova
  private static final AbstractDatabase dbAdapter = MetaCatUtil.dbAdapter;
74 425 bojilova
75 393 jones
  private Connection conn = null;
76
  private String docid = null;
77 956 tao
  private String updatedVersion=null;
78 393 jones
  private String docname = null;
79
  private String doctype = null;
80 691 bojilova
// DOCTITLE attr cleared from the db
81
//  private String doctitle = null;
82 465 berkley
  private String createdate = null;
83
  private String updatedate = null;
84 393 jones
  private String system_id = null;
85 561 berkley
  private String userowner = null;
86
  private String userupdated = null;
87 575 berkley
  private int rev;
88 561 berkley
  private int serverlocation;
89 1059 tao
  private String docHomeServer;
90 697 bojilova
  private String publicaccess;
91 393 jones
  private long rootnodeid;
92
  private ElementNode rootNode = null;
93 429 jones
  private TreeSet nodeRecordList = null;
94 790 bojilova
95
  /**
96 800 jones
   * Constructor used to create a document and read the document information
97
   * from the database.  If readNodes is false, then the node data is not
98
   * read at this time, but is deferred until it is needed (such as when a
99
   * call to toXml() is made).
100 790 bojilova
   *
101
   * @param conn the database connection from which to read the document
102 800 jones
   * @param docid the identifier of the document to be created
103
   * @param readNodes flag indicating whether the xmlnodes should be read
104 790 bojilova
   */
105 802 bojilova
  public DocumentImpl(Connection conn, String docid, boolean readNodes)
106
         throws McdbException
107 790 bojilova
  {
108 801 jones
    try {
109
      this.conn = conn;
110
      this.docid = docid;
111
112
      // Look up the document information
113
      getDocumentInfo(docid);
114 800 jones
115 801 jones
      if (readNodes) {
116 800 jones
        // Download all of the document nodes using a single SQL query
117
        // The sort order of the records is determined by the NodeComparator
118
        // class, and needs to represent a depth-first traversal for the
119
        // toXml() method to work properly
120
        nodeRecordList = getNodeRecordList(rootnodeid);
121 801 jones
      }
122 800 jones
123 801 jones
    } catch (McdbException ex) {
124
      throw ex;
125
    } catch (Throwable t) {
126
      throw new McdbException("Error reading document from " +
127
                              "DocumentImpl.DocumentImpl: " + docid);
128 800 jones
    }
129 790 bojilova
  }
130 393 jones
131
  /**
132 396 jones
   * Constructor, creates document from database connection, used
133
   * for reading the document
134 393 jones
   *
135
   * @param conn the database connection from which to read the document
136
   * @param docid the identifier of the document to be created
137
   */
138
  public DocumentImpl(Connection conn, String docid) throws McdbException
139
  {
140 801 jones
    this(conn, docid, true);
141 393 jones
  }
142
143 396 jones
  /**
144 415 jones
   * Construct a new document instance, writing the contents to the database.
145
   * This method is called from DBSAXHandler because we need to know the
146
   * root element name for documents without a DOCTYPE before creating it.
147 396 jones
   *
148
   * @param conn the JDBC Connection to which all information is written
149
   * @param rootnodeid - sequence id of the root node in the document
150
   * @param docname - the name of DTD, i.e. the name immediately following
151
   *        the DOCTYPE keyword ( should be the root element name ) or
152
   *        the root element name if no DOCTYPE declaration provided
153
   *        (Oracle's and IBM parsers are not aware if it is not the
154
   *        root element name)
155
   * @param doctype - Public ID of the DTD, i.e. the name immediately
156
   *                  following the PUBLIC keyword in DOCTYPE declaration or
157
   *                  the docname if no Public ID provided or
158
   *                  null if no DOCTYPE declaration provided
159 680 bojilova
   * @param docid the docid to use for the INSERT OR UPDATE
160
   * @param action the action to be performed (INSERT OR UPDATE)
161
   * @param user the user that owns the document
162
   * @param pub flag for public "read" access on document
163
   * @param serverCode the serverid from xml_replication on which this document
164
   *        resides.
165 396 jones
   *
166
   */
167
  public DocumentImpl(Connection conn, long rootnodeid, String docname,
168 549 berkley
                      String doctype, String docid, String action, String user,
169 697 bojilova
                      String pub, String catalogid, int serverCode)
170 549 berkley
                      throws SQLException, Exception
171
  {
172
    this.conn = conn;
173
    this.rootnodeid = rootnodeid;
174
    this.docname = docname;
175
    this.doctype = doctype;
176
    this.docid = docid;
177 697 bojilova
    writeDocumentToDB(action, user, pub, catalogid, serverCode);
178 549 berkley
  }
179
180 956 tao
  /**
181
   * Construct a new document instance, writing the contents to the database.
182
   * This method is called from DBSAXHandler because we need to know the
183
   * root element name for documents without a DOCTYPE before creating it.
184
   *
185
   * In this constructor, the docid is without rev. There is a string rev to
186
   * specify the revision user want to upadate. The revion is only need to be
187
   * greater than current one. It is not need to be sequent number just after
188
   * current one. So it is only used in update action
189
   * @param conn the JDBC Connection to which all information is written
190
   * @param rootnodeid - sequence id of the root node in the document
191
   * @param docname - the name of DTD, i.e. the name immediately following
192
   *        the DOCTYPE keyword ( should be the root element name ) or
193
   *        the root element name if no DOCTYPE declaration provided
194
   *        (Oracle's and IBM parsers are not aware if it is not the
195
   *        root element name)
196
   * @param doctype - Public ID of the DTD, i.e. the name immediately
197
   *                  following the PUBLIC keyword in DOCTYPE declaration or
198
   *                  the docname if no Public ID provided or
199
   *                  null if no DOCTYPE declaration provided
200
   * @param docid the docid to use for the UPDATE, no version number
201
   * @param version, need to be update
202
   * @param action the action to be performed (INSERT OR UPDATE)
203
   * @param user the user that owns the document
204
   * @param pub flag for public "read" access on document
205
   * @param serverCode the serverid from xml_replication on which this document
206
   *        resides.
207
   *
208
   */
209
  public DocumentImpl(Connection conn, long rootNodeId, String docName,
210
                      String docType, String docId, String newRevision,
211
                      String action, String user,
212
                      String pub, String catalogId, int serverCode)
213
                      throws SQLException, Exception
214
  {
215
    this.conn = conn;
216
    this.rootnodeid = rootNodeId;
217
    this.docname = docName;
218
    this.doctype = docType;
219
    this.docid = docId;
220
    this.updatedVersion = newRevision;
221
    writeDocumentToDB(action, user, pub, catalogId, serverCode);
222
  }
223
224 798 jones
  /**
225 1026 tao
   * This method will be call in handleUploadRequest in MetacatServlet class
226
   */
227
  public static void registerDocument(
228
                     String docname, String doctype, String accnum, String user)
229
                     throws SQLException, AccessionNumberException, Exception
230
  {
231
    Connection dbConn = null;
232
    MetaCatUtil ut = new MetaCatUtil();
233 1063 tao
    try
234
    {
235
      dbConn = ut.openDBConnection();
236
      // get server location for this doc
237
      int serverLocation=getServerLocationNumber(dbConn,accnum);
238
      dbConn.close();
239
      registerDocument(docname, doctype,accnum, user, serverLocation);
240
    }
241
    catch (Exception e)
242
    {
243
      throw e;
244
    }
245
    finally
246
    {
247
      try
248
      {
249
        dbConn.close();
250
      }
251
      catch (Exception ee)
252
      {}
253
    }
254 1026 tao
255
  }
256
  /**
257 798 jones
   * Register a document that resides on the filesystem with the database.
258
   * (ie, just an entry in xml_documents, nothing in xml_nodes).
259
   * Creates a reference to a filesystem document (used for non-xml data files).
260 1055 tao
   * This class only be called in MetaCatServerlet.
261 798 jones
   * @param conn the JDBC Connection to which all information is written
262
   * @param docname - the name of DTD, i.e. the name immediately following
263
   *        the DOCTYPE keyword ( should be the root element name ) or
264
   *        the root element name if no DOCTYPE declaration provided
265
   *        (Oracle's and IBM parsers are not aware if it is not the
266
   *        root element name)
267
   * @param doctype - Public ID of the DTD, i.e. the name immediately
268
   *                  following the PUBLIC keyword in DOCTYPE declaration or
269
   *                  the docname if no Public ID provided or
270
   *                  null if no DOCTYPE declaration provided
271
   * @param accnum the accession number to use for the INSERT OR UPDATE, which
272
   *               includes a revision number for this revision of the document
273
   *               (e.g., knb.1.1)
274
   * @param user the user that owns the document
275
   * @param serverCode the serverid from xml_replication on which this document
276
   *        resides.
277
   */
278
  public static void registerDocument(
279
                     String docname, String doctype, String accnum,
280
                     String user, int serverCode)
281
                     throws SQLException, AccessionNumberException, Exception
282
  {
283
    Connection dbconn = null;
284
    MetaCatUtil util = new MetaCatUtil();
285 965 tao
    AccessionNumber ac;
286 798 jones
    try {
287
      dbconn = util.openDBConnection();
288 965 tao
      String docIdWithoutRev=MetaCatUtil.getDocIdFromString(accnum);
289
      int userSpecifyRev=MetaCatUtil.getVersionFromString(accnum);
290
      int revInDataBase=getLatestRevisionNumber(dbconn, docIdWithoutRev);
291
      //revIndataBase=-1, there is no record in xml_documents table
292
      //the data file is a new one, inert it into table
293
      //user specified rev should be great than 0
294
      if (revInDataBase==-1 && userSpecifyRev>0 )
295
      {
296
        ac = new AccessionNumber(dbconn, accnum, "insert");
297
      }
298
      //rev is greater the last revsion number and revInDataBase isn't -1
299
      // it is a updated data file
300
      else if (userSpecifyRev>revInDataBase && revInDataBase>0)
301
      {
302
303
        //archive the old entry
304
        archiveDocRevision(dbconn, docIdWithoutRev, user);
305
        //delete the old entry in xml_documents
306
        deleteXMLDocuments(dbconn, docIdWithoutRev);
307
        ac = new AccessionNumber(dbconn, accnum, "update");
308
      }
309
      //other situation
310
      else
311
      {
312
313
        throw new Exception("Revision number couldn't be "
314
                    +userSpecifyRev);
315
      }
316 798 jones
      String docid = ac.getDocid();
317
      String rev = ac.getRev();
318
      SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
319
      Date localtime = new Date();
320
      String dateString = formatter.format(localtime);
321
322 946 tao
      String sqlDateString = "to_date('" + dateString +
323
                                          "', 'YY-MM-DD HH24:MI:SS')";
324 798 jones
325
      StringBuffer sql = new StringBuffer();
326
      sql.append("insert into xml_documents (docid, docname, doctype, ");
327 946 tao
      sql.append("user_owner, user_updated, server_location, rev,date_created");
328 798 jones
      sql.append(", date_updated, public_access) values ('");
329
      sql.append(docid).append("','");
330
      sql.append(docname).append("','");
331
      sql.append(doctype).append("','");
332
      sql.append(user).append("','");
333
      sql.append(user).append("','");
334
      sql.append(serverCode).append("','");
335
      sql.append(rev).append("',");
336
      sql.append(sqlDateString).append(",");
337
      sql.append(sqlDateString).append(",");
338
      sql.append("'0')");
339
      PreparedStatement pstmt = dbconn.prepareStatement(sql.toString());
340
      pstmt.execute();
341
      pstmt.close();
342
      dbconn.close();
343 1063 tao
    }
344
    finally
345
    {
346
      try
347
      {
348
        dbconn.close();
349
      }
350
      catch (SQLException sqlE)
351
      {
352
        util.debugMessage("Error in DocumentImpl.registerDocument:" +
353
                                sqlE.getMessage(), 30);
354
      }
355 798 jones
    }
356
  }
357 1029 tao
358 1055 tao
    /**
359
   * Register a document that resides on the filesystem with the database.
360
   * (ie, just an entry in xml_documents, nothing in xml_nodes).
361
   * Creates a reference to a filesystem document (used for non-xml data files)
362
   * This method will be called for register data file in xml_documents in
363
   * Replication.
364
   * This method is revised from registerDocument.
365
   *
366
   * @param conn the JDBC Connection to which all information is written
367
   * @param docname - the name of DTD, i.e. the name immediately following
368
   *        the DOCTYPE keyword ( should be the root element name ) or
369
   *        the root element name if no DOCTYPE declaration provided
370
   *        (Oracle's and IBM parsers are not aware if it is not the
371
   *        root element name)
372
   * @param doctype - Public ID of the DTD, i.e. the name immediately
373
   *                  following the PUBLIC keyword in DOCTYPE declaration or
374
   *                  the docname if no Public ID provided or
375
   *                  null if no DOCTYPE declaration provided
376
   * @param accnum the accession number to use for the INSERT OR UPDATE, which
377
   *               includes a revision number for this revision of the document
378
   *               (e.g., knb.1.1)
379
   * @param user the user that owns the document
380
   * @param serverCode the serverid from xml_replication on which this document
381
   *        resides.
382
   */
383
  public static void registerDocumentInReplication(
384
                     String docname, String doctype, String accnum,
385
                     String user, int serverCode)
386
                     throws SQLException, AccessionNumberException, Exception
387
  {
388
    Connection dbconn = null;
389
    MetaCatUtil util = new MetaCatUtil();
390
    AccessionNumber ac;
391
    try {
392
      dbconn = util.openDBConnection();
393
      String docIdWithoutRev=MetaCatUtil.getDocIdFromString(accnum);
394
      int userSpecifyRev=MetaCatUtil.getVersionFromString(accnum);
395
      int revInDataBase=getLatestRevisionNumber(dbconn, docIdWithoutRev);
396
      //revIndataBase=-1, there is no record in xml_documents table
397
      //the data file is a new one, inert it into table
398
      //user specified rev should be great than 0
399
      if (revInDataBase==-1 && userSpecifyRev>0 )
400
      {
401 1063 tao
402 1055 tao
        ac = new AccessionNumber(dbconn, accnum, "insert");
403
      }
404
      //rev is greater the last revsion number and revInDataBase isn't -1
405
      // it is a updated data file
406
      else if (userSpecifyRev>revInDataBase && revInDataBase>0)
407
      {
408
409
        //archive the old entry
410
        archiveDocRevision(dbconn, docIdWithoutRev, user);
411
        //delete the old entry in xml_documents
412
        deleteXMLDocuments(dbconn, docIdWithoutRev);
413
        ac = new AccessionNumber(dbconn, accnum, "update");
414
      }
415
      //other situation
416
      else
417
      {
418
419
        throw new Exception("Revision number couldn't be "
420
                    +userSpecifyRev);
421
      }
422
      String docid = ac.getDocid();
423
      String rev = ac.getRev();
424
      SimpleDateFormat formatter = new SimpleDateFormat ("yy-MM-dd HH:mm:ss");
425
      Date localtime = new Date();
426
      String dateString = formatter.format(localtime);
427
428
      String sqlDateString = "to_date('" + dateString +
429
                                          "', 'YY-MM-DD HH24:MI:SS')";
430
431
      StringBuffer sql = new StringBuffer();
432
      sql.append("insert into xml_documents (docid, docname, doctype, ");
433
      sql.append("user_owner, user_updated, server_location, rev,date_created");
434
      sql.append(", date_updated, public_access) values ('");
435
      sql.append(docid).append("','");
436
      sql.append(docname).append("','");
437
      sql.append(doctype).append("','");
438
      sql.append(user).append("','");
439
      sql.append(user).append("','");
440
      sql.append(serverCode).append("','");
441
      sql.append(rev).append("',");
442
      sql.append(sqlDateString).append(",");
443
      sql.append(sqlDateString).append(",");
444
      sql.append("'0')");
445
      PreparedStatement pstmt = dbconn.prepareStatement(sql.toString());
446
      pstmt.execute();
447
      pstmt.close();
448
      dbconn.close();
449 1063 tao
    }
450
    finally
451
    {
452
      try
453
      {
454
        dbconn.close();
455
      }
456
      catch (SQLException sqlE)
457
      {
458
        util.debugMessage("Error in DocumentImpl.registerDocument:" +
459
                                sqlE.getMessage());
460
      }
461 1055 tao
    }
462
  }
463
464 1021 tao
 /**
465 1029 tao
   * This method will register a data file entry in xml_documents and save a
466 1055 tao
   * data file input Stream into file system.. It is only used in force
467
   * replication
468 1029 tao
   *
469
   * @param  input, the input stream which contain the file content.
470
   * @param  , the input stream which contain the file content
471
   * @param docname - the name of DTD, for data file, it is a docid number.
472
   * @param doctype - "BIN" for data file
473
   * @param accnum the accession number to use for the INSERT OR UPDATE, which
474
   *               includes a revision number for this revision of the document
475
   *               (e.g., knb.1.1)
476
   * @param user the user that owns the document
477
   * @param serverCode the serverid from xml_replication on which this document
478
   *        resides.
479
   */
480
 public static void writeDataFile(InputStream input, String filePath,
481 1063 tao
                                  String docname, String doctype, String accnum,
482
                                  String user, String docHomeServer)
483 1029 tao
                     throws SQLException, AccessionNumberException, Exception
484
 {
485 1063 tao
   int serverCode=-2;
486 1029 tao
    if (filePath==null||filePath.equals(""))
487
    {
488
      throw new
489
            Exception("Please specify the directory where file will be store");
490
    }
491
    if (accnum==null||accnum.equals(""))
492
    {
493
      throw new Exception("Please specify the stored file name");
494
    }
495 1063 tao
496
    //get server code for the home server
497
    serverCode=getServerCode(docHomeServer);
498
    //if the server is not in the xml replication table, insert it.
499
    if (serverCode==-1)
500
    {
501
      insertServerIntoReplicationTable(docHomeServer);
502
      //get server code again
503
      serverCode=getServerCode(docHomeServer);
504
    }
505
506 1029 tao
    //make sure user have file lock grant(local metacat means have it too)
507 1069 tao
    //if (getDataFileLockGrant(accnum))
508
    //{
509 1029 tao
      //register data file into xml_documents table
510 1055 tao
      registerDocumentInReplication(docname, doctype, accnum, user, serverCode);
511 1029 tao
      //write inputstream into file system.
512
      File dataDirectory = new File(filePath);
513
      File newFile = new File(dataDirectory, accnum);
514
515
      // create a buffered byte output stream
516
      // that uses a default-sized output buffer
517
      FileOutputStream fos = new FileOutputStream(newFile);
518
      BufferedOutputStream outPut = new BufferedOutputStream(fos);
519
520
      BufferedInputStream bis = null;
521
      bis = new BufferedInputStream(input);
522
      byte[] buf = new byte[4 * 1024]; // 4K buffer
523
      int b = bis.read(buf);
524
525
      while (b != -1)
526
      {
527
        outPut.write(buf, 0, b);
528
        b = bis.read(buf);
529
      }
530
      bis.close();
531
	    outPut.close();
532
	    fos.close();
533 1063 tao
534 1069 tao
    //}//if
535 1029 tao
 }
536
537 798 jones
538 1026 tao
539
  public static boolean getDataFileLockGrant(String accnum)
540
                                                  throws Exception
541
  {
542
    Connection dbConn = null;
543
    MetaCatUtil ut= new MetaCatUtil();
544 1063 tao
    try
545
    {
546
      dbConn = ut.openDBConnection();
547
      int serverLocation=getServerLocationNumber(dbConn,accnum);
548
      dbConn.close();
549
      return getDataFileLockGrant(accnum,serverLocation);
550
    }
551
    catch (Exception e)
552
    {
553
      try
554
      {
555
        dbConn.close();
556
      }
557
      catch (Exception ee)
558
      {}
559
      throw e;
560
    }
561 1026 tao
  }
562
563 393 jones
  /**
564 1026 tao
   * The method will check if metacat can get data file lock grant
565
   * If server code is 1, it get.
566
   * If server code is not 1 but call replication getlock successfully,
567
   * it get
568
   * else, it didn't get
569
   * @param accnum, the ID of the document
570
   * @param action, the action to the document
571
   * @param serverCode, the server location code
572
   */
573
  public static boolean getDataFileLockGrant(String accnum, int serverCode)
574
                                          throws Exception
575
  {
576
    boolean flag=true;
577
    MetaCatUtil util = new MetaCatUtil();
578
    String docid = util.getDocIdFromString(accnum);
579
    int rev = util.getVersionFromString(accnum);
580
581
    if (serverCode == 1)
582
    {
583
      flag=true;
584
      return flag;
585
    }
586
587
    //if((serverCode != 1 && action.equals("UPDATE")) )
588
    if (serverCode != 1)
589
    { //if this document being written is not a resident of this server then
590
      //we need to try to get a lock from it's resident server.  If the
591
      //resident server will not give a lock then we send the user a message
592
      //saying that he/she needs to download a new copy of the file and
593
      //merge the differences manually.
594
595
      String server = MetacatReplication.getServer(serverCode);
596
      MetacatReplication.replLog("attempting to lock " + accnum);
597
      URL u = new URL("https://" + server + "?server="
598
           +util.getLocalReplicationServerName()+"&action=getlock&updaterev="
599
           +rev + "&docid=" + docid);
600
      //System.out.println("sending message: " + u.toString());
601
      String serverResStr = MetacatReplication.getURLContent(u);
602
      String openingtag =serverResStr.substring(0, serverResStr.indexOf(">")+1);
603
      if(openingtag.equals("<lockgranted>"))
604
      {
605
        //the lock was granted go ahead with the insert
606
        //System.out.println("In lockgranted");
607
        MetacatReplication.replLog("lock granted for " + accnum + " from " +
608
                                      server);
609
        flag=true;
610
        return flag;
611
      }//if
612
613
      else if(openingtag.equals("<filelocked>"))
614
      {//the file is currently locked by another user
615
       //notify our user to wait a few minutes, check out a new copy and try
616
       //again.
617
        //System.out.println("file locked");
618
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
619
                                   server + " reason: file already locked");
620
        throw new Exception("The file specified is already locked by another " +
621
                            "user.  Please wait 30 seconds, checkout the " +
622
                            "newer document, merge your changes and try " +
623
                            "again.");
624
      }
625
      else if(openingtag.equals("<outdatedfile>"))
626
      {//our file is outdated.  notify our user to check out a new copy of the
627
       //file and merge his version with the new version.
628
        //System.out.println("outdated file");
629
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
630
                                    server + " reason: local file outdated");
631
        throw new Exception("The file you are trying to update is an outdated" +
632
                            " version.  Please checkout the newest document, " +
633
                            "merge your changes and try again.");
634
      }//else if
635
    }//if
636
637
   return flag;
638
639
  }//getDataFileLockGrant
640
641
  /**
642 393 jones
   * get the document name
643
   */
644
  public String getDocname() {
645
    return docname;
646
  }
647
648
  /**
649
   * get the document type (which is the PublicID)
650
   */
651
  public String getDoctype() {
652
    return doctype;
653
  }
654
655
  /**
656
   * get the system identifier
657
   */
658
  public String getSystemID() {
659
    return system_id;
660
  }
661
662
  /**
663
   * get the root node identifier
664
   */
665
  public long getRootNodeID() {
666
    return rootnodeid;
667
  }
668 465 berkley
669
  /**
670
   * get the creation date
671
   */
672
  public String getCreateDate() {
673
    return createdate;
674
  }
675
676
  /**
677
   * get the update date
678
   */
679
  public String getUpdateDate() {
680
    return updatedate;
681
  }
682 393 jones
683 396 jones
  /**
684
   * Get the document identifier (docid)
685
   */
686
  public String getDocID() {
687
    return docid;
688
  }
689 465 berkley
690 691 bojilova
// DOCTITLE attr cleared from the db
691
//  /**
692
//   *get the document title
693
//   */
694
//  public String getDocTitle() {
695
//    return doctitle;
696
//  }
697 561 berkley
698
  public String getUserowner() {
699
    return userowner;
700
  }
701
702
  public String getUserupdated() {
703
    return userupdated;
704
  }
705
706
  public int getServerlocation() {
707
    return serverlocation;
708
  }
709
710 1059 tao
  public String getDocHomeServer() {
711
    return docHomeServer;
712 1055 tao
  }
713 1059 tao
714 1055 tao
715 1059 tao
716 697 bojilova
  public String getPublicaccess() {
717 561 berkley
    return publicaccess;
718
  }
719 575 berkley
720
  public int getRev() {
721
    return rev;
722
  }
723 956 tao
724
   /**
725 429 jones
   * Print a string representation of the XML document
726 393 jones
   */
727
  public String toString()
728
  {
729 429 jones
    StringWriter docwriter = new StringWriter();
730 800 jones
    try {
731
      this.toXml(docwriter);
732
    } catch (McdbException mcdbe) {
733
      return null;
734
    }
735 429 jones
    String document = docwriter.toString();
736
    return document;
737
  }
738
739
  /**
740
   * Get a text representation of the XML document as a string
741
   * This older algorithm uses a recursive tree of Objects to represent the
742
   * nodes of the tree.  Each object is passed the data for the document
743
   * and searches all of the document data to find its children nodes and
744
   * recursively build.  Thus, because each node reads the whole document,
745
   * this algorithm is extremely slow for larger documents, and the time
746
   * to completion is O(N^N) wrt the number of nodes.  See toXml() for a
747
   * better algorithm.
748
   */
749 800 jones
  public String readUsingSlowAlgorithm() throws McdbException
750 429 jones
  {
751 393 jones
    StringBuffer doc = new StringBuffer();
752
753 800 jones
    // First, check that we have the needed node data, and get it if not
754
    if (nodeRecordList == null) {
755
      nodeRecordList = getNodeRecordList(rootnodeid);
756
    }
757
758 429 jones
    // Create the elements from the downloaded data in the TreeSet
759
    rootNode = new ElementNode(nodeRecordList, rootnodeid);
760
761 393 jones
    // Append the resulting document to the StringBuffer and return it
762
    doc.append("<?xml version=\"1.0\"?>\n");
763
764
    if (docname != null) {
765
      if ((doctype != null) && (system_id != null)) {
766
        doc.append("<!DOCTYPE " + docname + " PUBLIC \"" + doctype +
767
                   "\" \"" + system_id + "\">\n");
768
      } else {
769
        doc.append("<!DOCTYPE " + docname + ">\n");
770
      }
771
    }
772
    doc.append(rootNode.toString());
773
774
    return (doc.toString());
775
  }
776
777
  /**
778 429 jones
   * Print a text representation of the XML document to a Writer
779
   *
780
   * @param pw the Writer to which we print the document
781
   */
782 800 jones
  public void toXml(Writer pw) throws McdbException
783 429 jones
  {
784
    PrintWriter out = null;
785
    if (pw instanceof PrintWriter) {
786
      out = (PrintWriter)pw;
787
    } else {
788
      out = new PrintWriter(pw);
789
    }
790
791
    MetaCatUtil util = new MetaCatUtil();
792
793 800 jones
    // First, check that we have the needed node data, and get it if not
794
    if (nodeRecordList == null) {
795
      nodeRecordList = getNodeRecordList(rootnodeid);
796
    }
797
798 429 jones
    Stack openElements = new Stack();
799
    boolean atRootElement = true;
800
    boolean previousNodeWasElement = false;
801
802
    // Step through all of the node records we were given
803
    Iterator it = nodeRecordList.iterator();
804
    while (it.hasNext()) {
805
      NodeRecord currentNode = (NodeRecord)it.next();
806
      //util.debugMessage("[Got Node ID: " + currentNode.nodeid +
807
                          //" (" + currentNode.parentnodeid +
808
                          //", " + currentNode.nodeindex +
809
                          //", " + currentNode.nodetype +
810
                          //", " + currentNode.nodename +
811
                          //", " + currentNode.nodedata + ")]");
812
      // Print the end tag for the previous node if needed
813
      //
814
      // This is determined by inspecting the parent nodeid for the
815
      // currentNode.  If it is the same as the nodeid of the last element
816
      // that was pushed onto the stack, then we are still in that previous
817
      // parent element, and we do nothing.  However, if it differs, then we
818
      // have returned to a level above the previous parent, so we go into
819
      // a loop and pop off nodes and print out their end tags until we get
820
      // the node on the stack to match the currentNode parentnodeid
821
      //
822
      // So, this of course means that we rely on the list of elements
823
      // having been sorted in a depth first traversal of the nodes, which
824
      // is handled by the NodeComparator class used by the TreeSet
825
      if (!atRootElement) {
826
        NodeRecord currentElement = (NodeRecord)openElements.peek();
827
        if ( currentNode.parentnodeid != currentElement.nodeid ) {
828
          while ( currentNode.parentnodeid != currentElement.nodeid ) {
829
            currentElement = (NodeRecord)openElements.pop();
830
            util.debugMessage("\n POPPED: " + currentElement.nodename);
831 451 bojilova
            if (previousNodeWasElement) {
832
              out.print(">");
833
              previousNodeWasElement = false;
834
            }
835 826 bojilova
            if ( currentElement.nodeprefix != null ) {
836
              out.print("</" + currentElement.nodeprefix + ":" +
837
                        currentElement.nodename + ">" );
838
            } else {
839
              out.print("</" + currentElement.nodename + ">" );
840
            }
841 429 jones
            currentElement = (NodeRecord)openElements.peek();
842
          }
843
        }
844
      }
845
846
      // Handle the DOCUMENT node
847
      if (currentNode.nodetype.equals("DOCUMENT")) {
848
        out.println("<?xml version=\"1.0\"?>");
849
850
        if (docname != null) {
851
          if ((doctype != null) && (system_id != null)) {
852
            out.println("<!DOCTYPE " + docname + " PUBLIC \"" + doctype +
853
                       "\" \"" + system_id + "\">");
854
          } else {
855
            out.println("<!DOCTYPE " + docname + ">");
856
          }
857
        }
858
859
      // Handle the ELEMENT nodes
860
      } else if (currentNode.nodetype.equals("ELEMENT")) {
861
        if (atRootElement) {
862
          atRootElement = false;
863
        } else {
864
          if (previousNodeWasElement) {
865
            out.print(">");
866
          }
867
        }
868
        openElements.push(currentNode);
869
        util.debugMessage("\n PUSHED: " + currentNode.nodename);
870
        previousNodeWasElement = true;
871 826 bojilova
        if ( currentNode.nodeprefix != null ) {
872
          out.print("<" + currentNode.nodeprefix + ":" + currentNode.nodename);
873
        } else {
874
          out.print("<" + currentNode.nodename);
875
        }
876 429 jones
877
      // Handle the ATTRIBUTE nodes
878
      } else if (currentNode.nodetype.equals("ATTRIBUTE")) {
879 826 bojilova
        if ( currentNode.nodeprefix != null ) {
880
          out.print(" " + currentNode.nodeprefix + ":" + currentNode.nodename +
881
                    "=\"" + currentNode.nodedata + "\"");
882
        } else {
883
          out.print(" " + currentNode.nodename + "=\"" +
884
                    currentNode.nodedata + "\"");
885
        }
886 821 bojilova
887
      // Handle the NAMESPACE nodes
888
      } else if (currentNode.nodetype.equals("NAMESPACE")) {
889
        out.print(" xmlns:" + currentNode.nodename + "=\""
890
                 + currentNode.nodedata + "\"");
891
892
      // Handle the TEXT nodes
893 429 jones
      } else if (currentNode.nodetype.equals("TEXT")) {
894
        if (previousNodeWasElement) {
895
          out.print(">");
896
        }
897
        out.print(currentNode.nodedata);
898
        previousNodeWasElement = false;
899
900
      // Handle the COMMENT nodes
901
      } else if (currentNode.nodetype.equals("COMMENT")) {
902
        if (previousNodeWasElement) {
903
          out.print(">");
904
        }
905
        out.print("<!--" + currentNode.nodedata + "-->");
906
        previousNodeWasElement = false;
907
908
      // Handle the PI nodes
909
      } else if (currentNode.nodetype.equals("PI")) {
910
        if (previousNodeWasElement) {
911
          out.print(">");
912
        }
913
        out.print("<?" + currentNode.nodename + " " +
914
                        currentNode.nodedata + "?>");
915
        previousNodeWasElement = false;
916
917
      // Handle any other node type (do nothing)
918
      } else {
919
        // Any other types of nodes are not handled.
920
        // Probably should throw an exception here to indicate this
921
      }
922
      out.flush();
923
    }
924
925
    // Print the final end tag for the root element
926 686 berkley
    while(!openElements.empty())
927
    {
928
      NodeRecord currentElement = (NodeRecord)openElements.pop();
929
      util.debugMessage("\n POPPED: " + currentElement.nodename);
930 826 bojilova
      if ( currentElement.nodeprefix != null ) {
931
        out.print("</" + currentElement.nodeprefix + ":" +
932
                  currentElement.nodename + ">" );
933
      } else {
934
        out.print("</" + currentElement.nodename + ">" );
935
      }
936 686 berkley
    }
937 429 jones
    out.flush();
938
  }
939 622 berkley
940
  private boolean isRevisionOnly(DocumentIdentifier docid) throws Exception
941
  {
942
    //System.out.println("inRevisionOnly");
943
    PreparedStatement pstmt;
944
    String rev = docid.getRev();
945
    String newid = docid.getIdentifier();
946
    pstmt = conn.prepareStatement("select rev from xml_documents " +
947
                                  "where docid like '" + newid + "'");
948
    pstmt.execute();
949
    ResultSet rs = pstmt.getResultSet();
950
    boolean tablehasrows = rs.next();
951
    if(rev.equals("newest") || rev.equals("all"))
952
    {
953
      return false;
954
    }
955
956
    if(tablehasrows)
957
    {
958
      int r = rs.getInt(1);
959 667 berkley
      pstmt.close();
960 622 berkley
      if(new Integer(rev).intValue() == r)
961
      { //the current revision in in xml_documents
962
        //System.out.println("returning false");
963
        return false;
964
      }
965
      else if(new Integer(rev).intValue() < r)
966
      { //the current revision is in xml_revisions.
967
        //System.out.println("returning true");
968
        return true;
969
      }
970
      else if(new Integer(rev).intValue() > r)
971
      { //error, rev cannot be greater than r
972
        throw new Exception("requested revision cannot be greater than " +
973
                            "the latest revision number.");
974
      }
975
    }
976
    throw new Exception("the requested docid '" + docid.toString() +
977
                        "' does not exist");
978
  }
979 429 jones
980 800 jones
  private void getDocumentInfo(String docid) throws McdbException,
981 622 berkley
                                                    AccessionNumberException
982
  {
983
    getDocumentInfo(new DocumentIdentifier(docid));
984
  }
985
986 429 jones
  /**
987 393 jones
   * Look up the document type information from the database
988
   *
989
   * @param docid the id of the document to look up
990
   */
991 622 berkley
  private void getDocumentInfo(DocumentIdentifier docid) throws McdbException
992 393 jones
  {
993
    PreparedStatement pstmt;
994 622 berkley
    String table = "xml_documents";
995 1059 tao
996 622 berkley
    try
997
    {
998
      if(isRevisionOnly(docid))
999
      { //pull the document from xml_revisions instead of from xml_documents;
1000
        table = "xml_revisions";
1001
      }
1002
    }
1003
    catch(Exception e)
1004
    {
1005 675 berkley
      System.out.println("error in DocumentImpl.getDocumentInfo: " +
1006
                          e.getMessage());
1007 622 berkley
    }
1008
1009
    //deal with the key words here.
1010
1011
    if(docid.getRev().equals("all"))
1012
    {
1013
1014
    }
1015
1016 393 jones
    try {
1017 622 berkley
      StringBuffer sql = new StringBuffer();
1018 691 bojilova
// DOCTITLE attr cleared from the db
1019
//      sql.append("SELECT docname, doctype, rootnodeid, doctitle, ");
1020
      sql.append("SELECT docname, doctype, rootnodeid, ");
1021 697 bojilova
      sql.append("date_created, date_updated, user_owner, user_updated, ");
1022
      sql.append("server_location, public_access, rev");
1023
      sql.append(" FROM ").append(table);
1024 622 berkley
      sql.append(" WHERE docid LIKE '").append(docid.getIdentifier());
1025
      sql.append("' and rev like '").append(docid.getRev()).append("'");
1026
      //System.out.println(sql.toString());
1027 393 jones
      pstmt =
1028 622 berkley
        conn.prepareStatement(sql.toString());
1029 393 jones
      // Bind the values to the query
1030 622 berkley
      //pstmt.setString(1, docid.getIdentifier());
1031
      //pstmt.setString(2, docid.getRev());
1032 393 jones
1033
      pstmt.execute();
1034
      ResultSet rs = pstmt.getResultSet();
1035
      boolean tableHasRows = rs.next();
1036
      if (tableHasRows) {
1037 561 berkley
        this.docname        = rs.getString(1);
1038
        this.doctype        = rs.getString(2);
1039
        this.rootnodeid     = rs.getLong(3);
1040 691 bojilova
// DOCTITLE attr cleared from the db
1041
//        this.doctitle       = rs.getString(4);
1042 692 bojilova
        this.createdate     = rs.getString(4);
1043
        this.updatedate     = rs.getString(5);
1044
        this.userowner      = rs.getString(6);
1045
        this.userupdated    = rs.getString(7);
1046
        this.serverlocation = rs.getInt(8);
1047 697 bojilova
        this.publicaccess   = rs.getString(9);
1048
        this.rev            = rs.getInt(10);
1049 393 jones
      }
1050 818 berkley
      pstmt.close();
1051 1059 tao
1052
      //get doc  home server name
1053
1054
      pstmt = conn.prepareStatement("select server " +
1055
                        "from xml_replication where serverid = ?");
1056
1057
1058
      pstmt.setInt(1, serverlocation);
1059
      pstmt.execute();
1060
      rs = pstmt.getResultSet();
1061
      tableHasRows = rs.next();
1062
      if (tableHasRows)
1063
      {
1064
1065
          String server = rs.getString(1);
1066
          //get homeserver name
1067
          if(!server.equals("localhost"))
1068
          {
1069
            this.docHomeServer=server;
1070
          }
1071
          else
1072
          {
1073
            this.docHomeServer=MetaCatUtil.getLocalReplicationServerName();
1074
          }
1075
          MetaCatUtil.debugMessage("server: "+docHomeServer, 50);
1076
1077
      }
1078
      pstmt.close();
1079 393 jones
      if (this.doctype != null) {
1080
        pstmt =
1081
          conn.prepareStatement("SELECT system_id " +
1082
                                  "FROM xml_catalog " +
1083 769 bojilova
                                 "WHERE public_id = ?");
1084 393 jones
        // Bind the values to the query
1085
        pstmt.setString(1, doctype);
1086
1087
        pstmt.execute();
1088
        rs = pstmt.getResultSet();
1089
        tableHasRows = rs.next();
1090
        if (tableHasRows) {
1091
          this.system_id  = rs.getString(1);
1092
        }
1093 818 berkley
        pstmt.close();
1094 393 jones
      }
1095
    } catch (SQLException e) {
1096 675 berkley
      System.out.println("error in DocumentImpl.getDocumentInfo: " +
1097
                          e.getMessage());
1098 622 berkley
      e.printStackTrace(System.out);
1099 675 berkley
      throw new McdbException("Error accessing database connection in " +
1100
                              "DocumentImpl.getDocumentInfo: ", e);
1101 393 jones
    }
1102
1103
    if (this.docname == null) {
1104
      throw new McdbDocNotFoundException("Document not found: " + docid);
1105
    }
1106
  }
1107
1108
  /**
1109
   * Look up the node data from the database
1110
   *
1111 396 jones
   * @param rootnodeid the id of the root node of the node tree to look up
1112 393 jones
   */
1113 396 jones
  private TreeSet getNodeRecordList(long rootnodeid) throws McdbException
1114 393 jones
  {
1115
    PreparedStatement pstmt;
1116
    TreeSet nodeRecordList = new TreeSet(new NodeComparator());
1117
    long nodeid = 0;
1118
    long parentnodeid = 0;
1119
    long nodeindex = 0;
1120
    String nodetype = null;
1121
    String nodename = null;
1122 826 bojilova
    String nodeprefix = null;
1123 393 jones
    String nodedata = null;
1124 899 berkley
    String quotechar = dbAdapter.getStringDelimiter();
1125 393 jones
1126
    try {
1127
      pstmt =
1128
      conn.prepareStatement("SELECT nodeid,parentnodeid,nodeindex, " +
1129 899 berkley
           "nodetype,nodename,nodeprefix,nodedata " +
1130 396 jones
           "FROM xml_nodes WHERE rootnodeid = ?");
1131 393 jones
1132
      // Bind the values to the query
1133 396 jones
      pstmt.setLong(1, rootnodeid);
1134 393 jones
1135
      pstmt.execute();
1136
      ResultSet rs = pstmt.getResultSet();
1137
      boolean tableHasRows = rs.next();
1138
      while (tableHasRows) {
1139
        nodeid = rs.getLong(1);
1140
        parentnodeid = rs.getLong(2);
1141
        nodeindex = rs.getLong(3);
1142
        nodetype = rs.getString(4);
1143
        nodename = rs.getString(5);
1144 826 bojilova
        nodeprefix = rs.getString(6);
1145
        nodedata = rs.getString(7);
1146 899 berkley
        nodedata = MetaCatUtil.normalize(nodedata);
1147 393 jones
        // add the data to the node record list hashtable
1148 826 bojilova
        NodeRecord currentRecord = new NodeRecord(nodeid,parentnodeid,nodeindex,
1149 946 tao
                                      nodetype, nodename, nodeprefix, nodedata);
1150 393 jones
        nodeRecordList.add(currentRecord);
1151
1152
        // Advance to the next node
1153
        tableHasRows = rs.next();
1154
      }
1155
      pstmt.close();
1156
1157
    } catch (SQLException e) {
1158 826 bojilova
      throw new McdbException("Error in DocumentImpl.getNodeRecordList " +
1159
                              e.getMessage());
1160 393 jones
    }
1161
1162
    if (nodeRecordList != null) {
1163
      return nodeRecordList;
1164
    } else {
1165
      throw new McdbException("Error getting node data: " + docid);
1166
    }
1167
  }
1168 549 berkley
1169 697 bojilova
// NOT USED ANY MORE
1170
//  /** creates SQL code and inserts new document into DB connection
1171
//   default serverCode of 1*/
1172
//  private void writeDocumentToDB(String action, String user)
1173
//               throws SQLException, Exception
1174
//  {
1175
//    writeDocumentToDB(action, user, null, 1);
1176
//  }
1177 393 jones
1178 459 bojilova
 /** creates SQL code and inserts new document into DB connection */
1179 680 bojilova
  private void writeDocumentToDB(String action, String user, String pub,
1180 697 bojilova
                                 String catalogid, int serverCode)
1181 459 bojilova
               throws SQLException, Exception {
1182 754 bojilova
    String sysdate = dbAdapter.getDateTimeFunction();
1183 747 bojilova
1184 459 bojilova
    try {
1185
      PreparedStatement pstmt = null;
1186
1187
      if (action.equals("INSERT")) {
1188
        //AccessionNumber ac = new AccessionNumber();
1189
        //this.docid = ac.generate(docid, "INSERT");
1190 1069 tao
        System.out.println("before pstmt");
1191 459 bojilova
        pstmt = conn.prepareStatement(
1192 697 bojilova
                "INSERT INTO xml_documents " +
1193
                "(docid, rootnodeid, docname, doctype, " +
1194
                "user_owner, user_updated, date_created, date_updated, " +
1195 1072 tao
                "public_access, catalog_id, server_location, rev) " +
1196 747 bojilova
                "VALUES (?, ?, ?, ?, ?, ?, " + sysdate + ", " + sysdate +
1197 1072 tao
                ", ?, ?, ?, ?)");
1198 549 berkley
        //note that the server_location is set to 1.
1199
        //this means that "localhost" in the xml_replication table must
1200
        //always be the first entry!!!!!
1201
1202 459 bojilova
        // Bind the values to the query
1203
        pstmt.setString(1, this.docid);
1204
        pstmt.setLong(2, rootnodeid);
1205
        pstmt.setString(3, docname);
1206
        pstmt.setString(4, doctype);
1207
        pstmt.setString(5, user);
1208
        pstmt.setString(6, user);
1209 1069 tao
        //public access is usefulless, so set it to null
1210
        pstmt.setString(7, null);
1211
        /*if ( pub == null ) {
1212 680 bojilova
          pstmt.setString(7, null);
1213 697 bojilova
        } else if ( pub.toUpperCase().equals("YES") || pub.equals("1") ) {
1214 680 bojilova
          pstmt.setInt(7, 1);
1215 697 bojilova
        } else if ( pub.toUpperCase().equals("NO") || pub.equals("0") ) {
1216 680 bojilova
          pstmt.setInt(7, 0);
1217 1069 tao
        }*/
1218 697 bojilova
        pstmt.setString(8, catalogid);
1219
        pstmt.setInt(9, serverCode);
1220 1072 tao
        pstmt.setInt(10, Integer.parseInt(updatedVersion));
1221 459 bojilova
      } else if (action.equals("UPDATE")) {
1222
1223 1072 tao
        // Save the old document publicaccessentry in a backup table
1224 459 bojilova
        DocumentImpl.archiveDocRevision( conn, docid, user );
1225 575 berkley
        DocumentImpl thisdoc = new DocumentImpl(conn, docid);
1226
        int thisrev = thisdoc.getRev();
1227 956 tao
1228
        //if the updated vesion is not greater than current one,
1229
        //throw it into a exception
1230
        if (Integer.parseInt(updatedVersion)<=thisrev)
1231
        {
1232
          throw new Exception("Next revision number couldn't be less"
1233
                               +" than or equal "+ thisrev);
1234
        }
1235
        else
1236
        {
1237
          //set the user specified revision
1238
          thisrev=Integer.parseInt(updatedVersion);
1239
        }
1240
1241 459 bojilova
        // Delete index for the old version of docid
1242
        // The new index is inserting on the next calls to DBSAXNode
1243
        pstmt = conn.prepareStatement(
1244
                "DELETE FROM xml_index WHERE docid='" + this.docid + "'");
1245
        pstmt.execute();
1246 818 berkley
        pstmt.close();
1247 459 bojilova
1248
        // Update the new document to reflect the new node tree
1249
        pstmt = conn.prepareStatement(
1250
            "UPDATE xml_documents " +
1251
            "SET rootnodeid = ?, docname = ?, doctype = ?, " +
1252 747 bojilova
            "user_updated = ?, date_updated = " + sysdate + ", " +
1253 697 bojilova
            "server_location = ?, rev = ?, public_access = ?, catalog_id = ? " +
1254 769 bojilova
            "WHERE docid = ?");
1255 459 bojilova
        // Bind the values to the query
1256
        pstmt.setLong(1, rootnodeid);
1257
        pstmt.setString(2, docname);
1258
        pstmt.setString(3, doctype);
1259
        pstmt.setString(4, user);
1260 549 berkley
        pstmt.setInt(5, serverCode);
1261 575 berkley
        pstmt.setInt(6, thisrev);
1262 1069 tao
        pstmt.setString(7, null);
1263
        /*if ( pub == null ) {
1264 680 bojilova
          pstmt.setString(7, null);
1265 697 bojilova
        } else if ( pub.toUpperCase().equals("YES") || pub.equals("1") ) {
1266 680 bojilova
          pstmt .setInt(7, 1);
1267 697 bojilova
        } else if ( pub.toUpperCase().equals("NO") || pub.equals("0") ) {
1268 680 bojilova
          pstmt.setInt(7, 0);
1269 1069 tao
        }*/
1270 697 bojilova
        pstmt.setString(8, catalogid);
1271
        pstmt.setString(9, this.docid);
1272 575 berkley
1273 459 bojilova
      } else {
1274
        System.err.println("Action not supported: " + action);
1275
      }
1276
1277
      // Do the insertion
1278
      pstmt.execute();
1279 1069 tao
      System.out.println("after excecute");
1280 459 bojilova
      pstmt.close();
1281
1282
    } catch (SQLException sqle) {
1283
      throw sqle;
1284
    } catch (Exception e) {
1285
      throw e;
1286
    }
1287
  }
1288
1289
  /**
1290 407 jones
   * Write an XML file to the database, given a filename
1291 393 jones
   *
1292 408 jones
   * @param conn the JDBC connection to the database
1293 407 jones
   * @param filename the filename to be loaded into the database
1294 680 bojilova
   * @param pub flag for public "read" access on document
1295
   * @param dtdfilename the dtd to be uploaded on server's file system
1296 407 jones
   * @param action the action to be performed (INSERT OR UPDATE)
1297
   * @param docid the docid to use for the INSERT OR UPDATE
1298 680 bojilova
   * @param user the user that owns the document
1299 802 bojilova
   * @param groups the groups to which user belongs
1300 393 jones
   */
1301 598 bojilova
  public static String write(Connection conn,String filename,
1302 680 bojilova
                             String pub, String dtdfilename,
1303 598 bojilova
                             String action, String docid, String user,
1304 802 bojilova
                             String[] groups )
1305 457 bojilova
                throws Exception {
1306 598 bojilova
1307
    Reader dtd = null;
1308
    if ( dtdfilename != null ) {
1309
      dtd = new FileReader(new File(dtdfilename).toString());
1310
    }
1311 555 bojilova
    return write ( conn, new FileReader(new File(filename).toString()),
1312 802 bojilova
                   pub, dtd, action, docid, user, groups, false);
1313 407 jones
  }
1314 598 bojilova
1315 680 bojilova
  public static String write(Connection conn,Reader xml,String pub,Reader dtd,
1316 598 bojilova
                             String action, String docid, String user,
1317 802 bojilova
                             String[] groups, boolean validate)
1318 549 berkley
                throws Exception {
1319 1012 tao
    //this method will be called in handleUpdateOrInsert method
1320
    //in MetacatServlet class
1321
    // get server location for this doc
1322
    int serverLocation=getServerLocationNumber(conn,docid);
1323
    //System.out.println("server location: "+serverLocation);
1324
    return write(conn,xml,pub,dtd,action,docid,user,groups,serverLocation,false,
1325
                 validate);
1326 598 bojilova
  }
1327
1328 680 bojilova
  public static String write(Connection conn, Reader xml, String pub,
1329 598 bojilova
                             String action, String docid, String user,
1330 802 bojilova
                             String[] groups )
1331 598 bojilova
                throws Exception {
1332 571 berkley
    if(action.equals("UPDATE"))
1333
    {//if the document is being updated then use the servercode from the
1334
     //originally inserted document.
1335
      DocumentImpl doc = new DocumentImpl(conn, docid);
1336
      int servercode = doc.getServerlocation();
1337 802 bojilova
      return write(conn, xml, pub, action, docid, user, groups, servercode);
1338 571 berkley
    }
1339
    else
1340
    {//if the file is being inserted then the servercode is always 1
1341 802 bojilova
      return write(conn, xml, pub, action, docid, user, groups, 1);
1342 571 berkley
    }
1343 549 berkley
  }
1344
1345 559 berkley
  public static String write( Connection conn, Reader xml,
1346
                              String action, String docid, String user,
1347 802 bojilova
                              String[] groups, int serverCode )
1348 598 bojilova
                throws Exception
1349 559 berkley
  {
1350 802 bojilova
    return write(conn,xml,null,action,docid,user,groups,serverCode);
1351 559 berkley
  }
1352
1353 680 bojilova
  public static String write( Connection conn, Reader xml, String pub,
1354 577 berkley
                              String action, String docid, String user,
1355 802 bojilova
                              String[] groups, int serverCode)
1356 598 bojilova
                throws Exception
1357 577 berkley
  {
1358 802 bojilova
    return write(conn,xml,pub,null,action,docid,user,groups,
1359 695 bojilova
                 serverCode,false,false);
1360 577 berkley
  }
1361
1362 680 bojilova
  public static String write( Connection conn, Reader xml, String pub,
1363 600 bojilova
                              String action, String docid, String user,
1364 802 bojilova
                              String[] groups, int serverCode, boolean override)
1365 600 bojilova
                throws Exception
1366
  {
1367 802 bojilova
    return write(conn,xml,pub,null,action,docid,user,groups,
1368 695 bojilova
                 serverCode,override,false);
1369 600 bojilova
  }
1370
1371 407 jones
  /**
1372
   * Write an XML file to the database, given a Reader
1373
   *
1374 408 jones
   * @param conn the JDBC connection to the database
1375 407 jones
   * @param xml the xml stream to be loaded into the database
1376 680 bojilova
   * @param pub flag for public "read" access on xml document
1377
   * @param dtd the dtd to be uploaded on server's file system
1378 734 bojilova
   * @param action the action to be performed (INSERT or UPDATE)
1379
   * @param accnum the docid + rev# to use on INSERT or UPDATE
1380 580 berkley
   * @param user the user that owns the document
1381 802 bojilova
   * @param groups the groups to which user belongs
1382 580 berkley
   * @param serverCode the serverid from xml_replication on which this document
1383
   *        resides.
1384
   * @param override flag to stop insert replication checking.
1385
   *        if override = true then a document not belonging to the local server
1386
   *        will not be checked upon update for a file lock.
1387
   *        if override = false then a document not from this server, upon
1388
   *        update will be locked and version checked.
1389 407 jones
   */
1390 559 berkley
1391 680 bojilova
  public static String write( Connection conn,Reader xml,String pub,Reader dtd,
1392 734 bojilova
                              String action, String accnum, String user,
1393 802 bojilova
                              String[] groups, int serverCode, boolean override,
1394 695 bojilova
                              boolean validate)
1395 598 bojilova
                throws Exception
1396 573 berkley
  {
1397 779 bojilova
    // NEW - WHEN CLIENT ALWAYS PROVIDE ACCESSION NUMBER INCLUDING REV IN IT
1398 1012 tao
    MetaCatUtil util = new MetaCatUtil();
1399 779 bojilova
    AccessionNumber ac = new AccessionNumber(conn, accnum, action);
1400
    String docid = ac.getDocid();
1401
    String rev = ac.getRev();
1402 590 berkley
    MetaCatUtil.debugMessage("action: " + action + " servercode: " +
1403 1055 tao
                             serverCode + " override: " + override, 10);
1404 580 berkley
1405 577 berkley
    if((serverCode != 1 && action.equals("UPDATE")) && !override)
1406 559 berkley
    { //if this document being written is not a resident of this server then
1407
      //we need to try to get a lock from it's resident server.  If the
1408
      //resident server will not give a lock then we send the user a message
1409
      //saying that he/she needs to download a new copy of the file and
1410
      //merge the differences manually.
1411 567 berkley
      int istreamInt;
1412 561 berkley
      char istreamChar;
1413 779 bojilova
      DocumentIdentifier id = new DocumentIdentifier(accnum);
1414
      String updaterev = id.getRev();
1415 561 berkley
      String server = MetacatReplication.getServer(serverCode);
1416 734 bojilova
      MetacatReplication.replLog("attempting to lock " + accnum);
1417 1012 tao
      URL u = new URL("https://" + server + "?server="
1418
           +util.getLocalReplicationServerName()+"&action=getlock&updaterev="
1419
           +updaterev + "&docid=" + docid);
1420
      //System.out.println("sending message: " + u.toString());
1421 569 berkley
      String serverResStr = MetacatReplication.getURLContent(u);
1422 946 tao
      String openingtag =serverResStr.substring(0, serverResStr.indexOf(">")+1);
1423 561 berkley
      if(openingtag.equals("<lockgranted>"))
1424
      {//the lock was granted go ahead with the insert
1425 571 berkley
        try
1426
        {
1427 1012 tao
          //System.out.println("In lockgranted");
1428 734 bojilova
          MetacatReplication.replLog("lock granted for " + accnum + " from " +
1429 584 berkley
                                      server);
1430 956 tao
          XMLReader parser = initializeParser(conn, action, docid, updaterev,
1431
                                  validate, user, groups, pub, serverCode, dtd);
1432 571 berkley
          conn.setAutoCommit(false);
1433 695 bojilova
          parser.parse(new InputSource(xml));
1434 571 berkley
          conn.commit();
1435
          conn.setAutoCommit(true);
1436
        }
1437
        catch (Exception e)
1438
        {
1439
          conn.rollback();
1440
          conn.setAutoCommit(true);
1441
          throw e;
1442
        }
1443
1444 590 berkley
1445 1039 tao
1446
        //If Metacat is super hub, tell all servers in its server list to get
1447
        //the new document, ture mean it is xml document
1448
        if ((util.getOption("hub")).equals("super"))
1449
        {
1450
          ForceReplicationHandler frh = new ForceReplicationHandler(accnum,
1451
                true, ReplicationHandler.buildServerList(conn));
1452
        }
1453
        else
1454
        {
1455
          //after inserting the document locally, tell the document's homeserver
1456
          //to come get a copy from here.
1457
1458
          ForceReplicationHandler frh = new ForceReplicationHandler(accnum,
1459
                true, ReplicationHandler.getHomeServer(docid));
1460
        }
1461 779 bojilova
        return (accnum);
1462 561 berkley
      }
1463 734 bojilova
1464 561 berkley
      else if(openingtag.equals("<filelocked>"))
1465
      {//the file is currently locked by another user
1466
       //notify our user to wait a few minutes, check out a new copy and try
1467
       //again.
1468 584 berkley
        //System.out.println("file locked");
1469 734 bojilova
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
1470 584 berkley
                                   server + " reason: file already locked");
1471 571 berkley
        throw new Exception("The file specified is already locked by another " +
1472
                            "user.  Please wait 30 seconds, checkout the " +
1473
                            "newer document, merge your changes and try " +
1474
                            "again.");
1475 561 berkley
      }
1476
      else if(openingtag.equals("<outdatedfile>"))
1477
      {//our file is outdated.  notify our user to check out a new copy of the
1478
       //file and merge his version with the new version.
1479 584 berkley
        //System.out.println("outdated file");
1480 734 bojilova
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
1481 584 berkley
                                    server + " reason: local file outdated");
1482 571 berkley
        throw new Exception("The file you are trying to update is an outdated" +
1483
                            " version.  Please checkout the newest document, " +
1484
                            "merge your changes and try again.");
1485 561 berkley
      }
1486 559 berkley
    }
1487 571 berkley
1488 425 bojilova
    if ( action.equals("UPDATE") ) {
1489 441 bojilova
      // check for 'write' permission for 'user' to update this document
1490 628 berkley
1491 802 bojilova
      if ( !hasPermission(conn, user, groups, docid) ) {
1492 441 bojilova
        throw new Exception("User " + user +
1493 734 bojilova
              " does not have permission to update XML Document #" + accnum);
1494 425 bojilova
      }
1495
    }
1496
1497 571 berkley
    try
1498 638 bojilova
    {
1499 956 tao
1500
      XMLReader parser = initializeParser(conn, action, docid, rev, validate,
1501 802 bojilova
                                          user, groups, pub, serverCode, dtd);
1502 555 bojilova
      conn.setAutoCommit(false);
1503
      parser.parse(new InputSource(xml));
1504
      conn.commit();
1505
      conn.setAutoCommit(true);
1506 571 berkley
    }
1507
    catch (Exception e)
1508
    {
1509 555 bojilova
      conn.rollback();
1510
      conn.setAutoCommit(true);
1511
      throw e;
1512
    }
1513 577 berkley
1514
    //force replicate out the new document to each server in our server list.
1515
    if(serverCode == 1)
1516 1012 tao
    {
1517
1518
      //start the thread to replicate this new document out to the other servers
1519 1021 tao
      //true mean it is xml document
1520
      ForceReplicationHandler frh = new ForceReplicationHandler
1521 1039 tao
                (accnum, action, true,ReplicationHandler.buildServerList(conn));
1522 956 tao
1523 577 berkley
    }
1524 457 bojilova
1525 779 bojilova
    return(accnum);
1526 393 jones
  }
1527 396 jones
1528 407 jones
  /**
1529 1055 tao
   * Write an XML file to the database during replication
1530
   *
1531
   * @param conn the JDBC connection to the database
1532
   * @param xml the xml stream to be loaded into the database
1533
   * @param pub flag for public "read" access on xml document
1534
   * @param dtd the dtd to be uploaded on server's file system
1535
   * @param action the action to be performed (INSERT or UPDATE)
1536
   * @param accnum the docid + rev# to use on INSERT or UPDATE
1537
   * @param user the user that owns the document
1538
   * @param groups the groups to which user belongs
1539
   * @param homeServer the name of server which the document origanlly create
1540
   * @param validate, if the xml document is valid or not
1541
   */
1542
1543
  public static String writeReplication( Connection conn,Reader xml,String pub,
1544
                Reader dtd, String action, String accnum, String user,
1545
                            String[] groups,String homeServer, boolean validate)
1546
                throws Exception
1547
  {
1548
    // NEW - WHEN CLIENT ALWAYS PROVIDE ACCESSION NUMBER INCLUDING REV IN IT
1549
    MetaCatUtil util = new MetaCatUtil();
1550 1069 tao
    //AccessionNumber ac = new AccessionNumber(conn, accnum, action);
1551
    //String docid = ac.getDocid();
1552
    // String rev = ac.getRev();
1553
    String docid=util.getDocIdFromString(accnum);
1554
    String rev=(new Integer(util.getVersionFromString(accnum))).toString();
1555
1556
    //check if xml_documents table has the document or not
1557
    //if not, set action to insert
1558
    if (getLatestRevisionNumber(conn,docid)==-1)
1559
    {
1560
      action="INSERT";
1561
    }
1562
1563 1055 tao
    int serverCode=-2;
1564
    //get server code for the home server
1565
    serverCode=getServerCode(homeServer);
1566
    //if the server is not in the xml replication table, insert it.
1567
    if (serverCode==-1)
1568
    {
1569
      insertServerIntoReplicationTable(homeServer);
1570
      //get server code again
1571
      serverCode=getServerCode(homeServer);
1572
    }
1573
1574
    MetaCatUtil.debugMessage("action: " + action + " servercode: " +
1575
                             serverCode, 10);
1576
1577 1069 tao
    /*if((serverCode != 1 && action.equals("UPDATE")) )
1578
    {
1579 1055 tao
      int istreamInt;
1580
      char istreamChar;
1581
      DocumentIdentifier id = new DocumentIdentifier(accnum);
1582
      String updaterev = id.getRev();
1583
      String server = MetacatReplication.getServer(serverCode);
1584
      MetacatReplication.replLog("attempting to lock " + accnum);
1585
      URL u = new URL("https://" + server + "?server="
1586
           +util.getLocalReplicationServerName()+"&action=getlock&updaterev="
1587
           +updaterev + "&docid=" + docid);
1588 1069 tao
1589 1055 tao
      String serverResStr = MetacatReplication.getURLContent(u);
1590
      String openingtag =serverResStr.substring(0, serverResStr.indexOf(">")+1);
1591
      if(openingtag.equals("<lockgranted>"))
1592 1069 tao
      {
1593 1055 tao
        try
1594
        {
1595 1069 tao
1596 1055 tao
          MetacatReplication.replLog("lock granted for " + accnum + " from " +
1597
                                      server);
1598
          XMLReader parser = initializeParser(conn, action, docid, updaterev,
1599
                                  validate, user, groups, pub, serverCode, dtd);
1600
          conn.setAutoCommit(false);
1601
          parser.parse(new InputSource(xml));
1602
          conn.commit();
1603
          conn.setAutoCommit(true);
1604
        }
1605
        catch (Exception e)
1606
        {
1607
          conn.rollback();
1608
          conn.setAutoCommit(true);
1609
          throw e;
1610
        }
1611
        return (accnum);
1612
      }
1613
1614
      else if(openingtag.equals("<filelocked>"))
1615 1069 tao
      {
1616 1055 tao
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
1617
                                   server + " reason: file already locked");
1618
        throw new Exception("The file specified is already locked by another " +
1619
                            "user.  Please wait 30 seconds, checkout the " +
1620
                            "newer document, merge your changes and try " +
1621
                            "again.");
1622
      }
1623
      else if(openingtag.equals("<outdatedfile>"))
1624 1069 tao
      {
1625 1055 tao
        MetacatReplication.replLog("lock denied for " + accnum + " on " +
1626
                                    server + " reason: local file outdated");
1627
        throw new Exception("The file you are trying to update is an outdated" +
1628
                            " version.  Please checkout the newest document, " +
1629
                            "merge your changes and try again.");
1630
      }
1631 1069 tao
    }*/
1632 1055 tao
1633 1069 tao
    /*if ( action.equals("UPDATE") ) {
1634
1635 1055 tao
      if ( !hasPermission(conn, user, groups, docid) ) {
1636
        throw new Exception("User " + user +
1637
              " does not have permission to update XML Document #" + accnum);
1638
      }
1639 1069 tao
    }*/
1640 1055 tao
1641
    try
1642
    {
1643
1644
      XMLReader parser = initializeParser(conn, action, docid, rev, validate,
1645
                                          user, groups, pub, serverCode, dtd);
1646
      conn.setAutoCommit(false);
1647
      parser.parse(new InputSource(xml));
1648
      conn.commit();
1649
      conn.setAutoCommit(true);
1650
    }
1651
    catch (Exception e)
1652
    {
1653
      conn.rollback();
1654
      conn.setAutoCommit(true);
1655
      throw e;
1656
    }
1657
1658
    return(accnum);
1659
  }
1660
1661
1662
  /**
1663 407 jones
   * Delete an XML file from the database (actually, just make it a revision
1664
   * in the xml_revisions table)
1665
   *
1666
   * @param docid the ID of the document to be deleted from the database
1667
   */
1668 734 bojilova
  public static void delete( Connection conn, String accnum,
1669 802 bojilova
                                 String user, String[] groups )
1670 734 bojilova
                throws Exception
1671
  {
1672 779 bojilova
    // OLD
1673
    //DocumentIdentifier id = new DocumentIdentifier(accnum);
1674
    //String docid = id.getIdentifier();
1675
    //String rev = id.getRev();
1676 628 berkley
1677 779 bojilova
    // OLD
1678 734 bojilova
    // Determine if the docid,rev are OK for DELETE
1679 779 bojilova
    //AccessionNumber ac = new AccessionNumber(conn);
1680
    //docid = ac.generate(docid, rev, "DELETE");
1681 396 jones
1682 779 bojilova
    // NEW - WHEN CLIENT ALWAYS PROVIDE ACCESSION NUMBER INCLUDING REV IN IT
1683
    AccessionNumber ac = new AccessionNumber(conn, accnum, "DELETE");
1684
    String docid = ac.getDocid();
1685
    String rev = ac.getRev();
1686
1687
1688 441 bojilova
    // check for 'write' permission for 'user' to delete this document
1689 802 bojilova
    if ( !hasPermission(conn, user, groups, docid) ) {
1690 441 bojilova
      throw new Exception("User " + user +
1691 734 bojilova
              " does not have permission to delete XML Document #" + accnum);
1692 425 bojilova
    }
1693
1694 407 jones
    conn.setAutoCommit(false);
1695
    // Copy the record to the xml_revisions table
1696 425 bojilova
    DocumentImpl.archiveDocRevision( conn, docid, user );
1697 396 jones
1698 407 jones
    // Now delete it from the xml_documents table
1699 628 berkley
1700 407 jones
    Statement stmt = conn.createStatement();
1701 425 bojilova
    stmt.execute("DELETE FROM xml_index WHERE docid = '" + docid + "'");
1702 688 bojilova
    //stmt.execute("DELETE FROM xml_access WHERE docid = '" + docid + "'");
1703 645 bojilova
    stmt.execute("DELETE FROM xml_access WHERE accessfileid = '" + docid + "'");
1704
    stmt.execute("DELETE FROM xml_relation WHERE docid = '" + docid + "'");
1705 785 bojilova
    stmt.execute("DELETE FROM xml_documents WHERE docid = '" + docid + "'");
1706 407 jones
    stmt.close();
1707
    conn.commit();
1708 457 bojilova
    conn.setAutoCommit(true);
1709 634 berkley
    //IF this is a package document:
1710
    //delete all of the relations that this document created.
1711
    //if the deleted document is a package document its relations should
1712
    //no longer be active if it has been deleted from the system.
1713 645 bojilova
1714 407 jones
  }
1715 638 bojilova
1716 570 bojilova
  /**
1717 802 bojilova
    * Check for "WRITE" permission on @docid for @user and/or @groups
1718 570 bojilova
    * from DB connection
1719
    */
1720 802 bojilova
  private static boolean hasPermission ( Connection conn, String user,
1721
                                  String[] groups, String docid )
1722 958 tao
                  throws SQLException, Exception
1723 570 bojilova
  {
1724 802 bojilova
    // Check for WRITE permission on @docid for @user and/or @groups
1725 570 bojilova
    AccessControlList aclobj = new AccessControlList(conn);
1726 802 bojilova
    return aclobj.hasPermission("WRITE", user, groups, docid);
1727 425 bojilova
  }
1728
1729 946 tao
  /**
1730
    * Check for "READ" permission base on docid, user and group
1731
    *@docid, the document
1732
    *@user, user name
1733
    *@group, user's group
1734
    *
1735
    */
1736
  public boolean hasReadPermission ( Connection conn, String user,
1737
                                  String[] groups, String docId )
1738 958 tao
                  throws SQLException, Exception
1739 946 tao
  {
1740
    // Check for READ permission on @docid for @user and/or @groups
1741
    AccessControlList aclObj = new AccessControlList(conn);
1742
    return aclObj.hasPermission("READ", user, groups, docId);
1743
  }
1744
1745 396 jones
  /**
1746 407 jones
   * Set up the parser handlers for writing the document to the database
1747
   */
1748 598 bojilova
  private static XMLReader initializeParser(Connection conn, String action,
1749 956 tao
                               String docid, String rev, boolean validate,
1750 802 bojilova
                                   String user, String[] groups, String pub,
1751 695 bojilova
                                   int serverCode, Reader dtd)
1752 598 bojilova
                           throws Exception
1753
  {
1754 407 jones
    XMLReader parser = null;
1755
    //
1756
    // Set up the SAX document handlers for parsing
1757
    //
1758
    try {
1759 956 tao
      //create a DBSAXHandler object which has the revision specification
1760
      ContentHandler chandler = new DBSAXHandler(conn, action, docid, rev,
1761 802 bojilova
                                                 user, groups, pub, serverCode);
1762 645 bojilova
      EntityResolver eresolver= new DBEntityResolver(conn,
1763
                                                 (DBSAXHandler)chandler, dtd);
1764 598 bojilova
      DTDHandler dtdhandler   = new DBDTDHandler(conn);
1765 407 jones
1766
      // Get an instance of the parser
1767 802 bojilova
      String parserName = MetaCatUtil.getOption("saxparser");
1768 407 jones
      parser = XMLReaderFactory.createXMLReader(parserName);
1769
1770 660 bojilova
      // Turn on validation
1771 695 bojilova
      parser.setFeature("http://xml.org/sax/features/validation", validate);
1772 660 bojilova
      // Turn off Including all external parameter entities
1773
      // (the external DTD subset also)
1774
      // Doesn't work well, probably the feature name is not correct
1775
      // parser.setFeature(
1776
      //  "http://xml.org/sax/features/external-parameter-entities", false);
1777 407 jones
1778
      // Set Handlers in the parser
1779
      parser.setProperty("http://xml.org/sax/properties/declaration-handler",
1780
                         chandler);
1781
      parser.setProperty("http://xml.org/sax/properties/lexical-handler",
1782
                         chandler);
1783
      parser.setContentHandler((ContentHandler)chandler);
1784 598 bojilova
      parser.setEntityResolver((EntityResolver)eresolver);
1785 407 jones
      parser.setDTDHandler((DTDHandler)dtdhandler);
1786
      parser.setErrorHandler((ErrorHandler)chandler);
1787
1788
    } catch (Exception e) {
1789 457 bojilova
      throw e;
1790 407 jones
    }
1791
1792
    return parser;
1793
  }
1794
1795 459 bojilova
  /** Save a document entry in the xml_revisions table */
1796
  private static void archiveDocRevision(Connection conn, String docid,
1797 552 berkley
                                         String user)
1798 1063 tao
 {
1799 754 bojilova
    String sysdate = dbAdapter.getDateTimeFunction();
1800 459 bojilova
    // create a record in xml_revisions table
1801
    // for that document as selected from xml_documents
1802 1063 tao
1803
   try
1804
   {
1805
     PreparedStatement pstmt = conn.prepareStatement(
1806 459 bojilova
      "INSERT INTO xml_revisions " +
1807 771 bojilova
        "(docid, rootnodeid, docname, doctype, " +
1808 697 bojilova
        "user_owner, user_updated, date_created, date_updated, " +
1809
        "server_location, rev, public_access, catalog_id) " +
1810 771 bojilova
      "SELECT ?, rootnodeid, docname, doctype, " +
1811 747 bojilova
        "user_owner, ?, " + sysdate + ", " + sysdate + ", "+
1812
        "server_location, rev, public_access, catalog_id " +
1813 459 bojilova
      "FROM xml_documents " +
1814
      "WHERE docid = ?");
1815 1063 tao
      // Bind the values to the query and execute it
1816
      pstmt.setString(1, docid);
1817
      pstmt.setString(2, user);
1818
      pstmt.setString(3, docid);
1819
      pstmt.execute();
1820
      pstmt.close();
1821
   }
1822
   catch (SQLException e)
1823
   {
1824
   }
1825
1826 459 bojilova
1827
  }
1828 965 tao
1829
  /**
1830
    * delete a entry in xml_table for given docid
1831
    * @param docId, the id of the document need to be delete
1832
    */
1833
  private static void deleteXMLDocuments(Connection conn, String docId)
1834
                                         throws SQLException
1835
  {
1836
    //delete a record
1837
    PreparedStatement pStmt =
1838
             conn.prepareStatement("DELETE FROM xml_documents WHERE docid = '"
1839
                                              + docId + "'");
1840
    pStmt.execute();
1841
    pStmt.close();
1842 459 bojilova
1843 965 tao
  }//deleteXMLDocuments
1844
1845 407 jones
  /**
1846 965 tao
    * Get last revision number from database for a docid
1847
    * If couldn't find an entry,  -1 will return
1848
    * The return value is integer because we want compare it to there new one
1849
    * @param docid <sitecode>.<uniqueid> part of Accession Number
1850
    */
1851
  private static int getLatestRevisionNumber(Connection conn, String docId)
1852
                                      throws SQLException
1853
  {
1854
    int rev = 1;
1855
    PreparedStatement pStmt;
1856
1857
    pStmt = conn.prepareStatement
1858
              ("SELECT rev FROM xml_documents WHERE docid='" + docId + "'");
1859
    pStmt.execute();
1860
1861
    ResultSet rs = pStmt.getResultSet();
1862
    boolean hasRow = rs.next();
1863
    if (hasRow)
1864
    {
1865
      rev = rs.getInt(1);
1866
      pStmt.close();
1867
    }
1868
    else
1869
    {
1870
      rev=-1;
1871
      pStmt.close();
1872
    }
1873
1874
    return rev;
1875
  }//getLatestRevisionNumber
1876
1877
  /**
1878 1012 tao
   * Get server location form database for a accNum
1879
   *
1880
   * @param accum <sitecode>.<uniqueid>.<rev>
1881
   */
1882
  private static int getServerLocationNumber(Connection conn, String accNum)
1883
                                            throws SQLException
1884
  {
1885
    //get rid of revNum part
1886
    String docId=MetaCatUtil.getDocIdFromString(accNum);
1887
    PreparedStatement pStmt;
1888
    int serverLocation;
1889
1890
    pStmt = conn.prepareStatement
1891
      ("SELECT server_location FROM xml_documents WHERE docid='" + docId + "'");
1892
    pStmt.execute();
1893
1894
    ResultSet rs = pStmt.getResultSet();
1895
    boolean hasRow = rs.next();
1896
    //if there is entry in xml_documents, get the serverlocation
1897
    if (hasRow)
1898
    {
1899
      serverLocation = rs.getInt(1);
1900
      pStmt.close();
1901
    }
1902
    else
1903
    {
1904
      // if htere is no entry in xml_documents, we consider it is new document
1905
      // the server location is local host and value is 1
1906
      serverLocation=1;
1907
      pStmt.close();
1908
    }
1909
1910
    return serverLocation;
1911
  }
1912 1055 tao
1913 1012 tao
  /**
1914 1055 tao
   * Given a server name, return its servercode in xml_replication table.
1915
   * If no server is found, -1 will return
1916
   * @param serverName,
1917
   */
1918
  private static int getServerCode(String serverName)
1919
  {
1920
    PreparedStatement pStmt=null;
1921
    int serverLocation=-2;
1922
    Connection dbConn = null;
1923
    MetaCatUtil util = new MetaCatUtil();
1924
1925
1926
    //we should consider about local host too
1927
    if (serverName.equals(util.getLocalReplicationServerName()))
1928
    {
1929
      serverLocation=1;
1930
      return serverLocation;
1931
    }
1932
1933
1934
    try
1935
    {
1936
      //check xml_replication table
1937 1063 tao
      dbConn=util.openDBConnection();
1938 1055 tao
      pStmt = dbConn.prepareStatement
1939
      ("SELECT serverid FROM xml_replication WHERE server='" + serverName +"'");
1940
      pStmt.execute();
1941
1942
      ResultSet rs = pStmt.getResultSet();
1943
      boolean hasRow = rs.next();
1944
      //if there is entry in xml_replication, get the serverid
1945
      if (hasRow)
1946
      {
1947
        serverLocation = rs.getInt(1);
1948
        pStmt.close();
1949
      }
1950
      else
1951
      {
1952
        // if htere is no entry in xml_replication, -1 will return
1953
        serverLocation=-1;
1954
        pStmt.close();
1955
      }
1956
    }
1957
    catch (Exception e)
1958
    {
1959
      util.debugMessage("Error in DocumentImpl.getServerCode(): "
1960
                                    +e.getMessage(), 30);
1961
    }
1962
    finally
1963
    {
1964
      try
1965
      {
1966 1063 tao
        dbConn.close();
1967 1055 tao
      }
1968
      catch (Exception ee)
1969
      {}
1970
    }
1971
1972
1973
    return serverLocation;
1974
  }
1975
1976
  /**
1977
   * Insert a server into xml_replcation table
1978
   * @param server, the name of server
1979
   */
1980
  private static void  insertServerIntoReplicationTable(String server)
1981
  {
1982
    PreparedStatement pStmt=null;
1983
    Connection dbConn = null;
1984
    int replicate = 1;
1985
    MetaCatUtil util = new MetaCatUtil();
1986
    try
1987
    {
1988 1063 tao
       dbConn=util.openDBConnection();
1989 1055 tao
       pStmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
1990
                                      "(server, last_checked, replicate) " +
1991
                                      "VALUES ('" + server + "', to_date(" +
1992
                                      "'01/01/00', 'MM/DD/YY'), '" +
1993
                                      replicate + "')");
1994
        pStmt.execute();
1995
        pStmt.close();
1996
        dbConn.commit();
1997
    }
1998
    catch (Exception e)
1999
    {
2000
      util.debugMessage("Error in DocumentImpl.getServerCode(): "
2001
                                    +e.getMessage(), 30);
2002
    }
2003
    finally
2004
    {
2005
      try
2006
      {
2007
        pStmt.close();
2008 1063 tao
        dbConn.close();
2009 1055 tao
      }
2010
      catch (Exception ee)
2011
      {}
2012
    }
2013
2014
  }
2015
2016
2017
  /**
2018 407 jones
   * the main routine used to test the DBWriter utility.
2019
   * <p>
2020
   * Usage: java DocumentImpl <-f filename -a action -d docid>
2021
   *
2022
   * @param filename the filename to be loaded into the database
2023
   * @param action the action to perform (READ, INSERT, UPDATE, DELETE)
2024
   * @param docid the id of the document to process
2025
   */
2026
  static public void main(String[] args) {
2027
2028
    try {
2029 555 bojilova
      String filename    = null;
2030 598 bojilova
      String dtdfilename = null;
2031 555 bojilova
      String action      = null;
2032
      String docid       = null;
2033 429 jones
      boolean showRuntime = false;
2034
      boolean useOldReadAlgorithm = false;
2035 407 jones
2036 408 jones
      // Parse the command line arguments
2037 407 jones
      for ( int i=0 ; i < args.length; ++i ) {
2038
        if ( args[i].equals( "-f" ) ) {
2039
          filename =  args[++i];
2040 598 bojilova
        } else if ( args[i].equals( "-r" ) ) {
2041
          dtdfilename =  args[++i];
2042 407 jones
        } else if ( args[i].equals( "-a" ) ) {
2043
          action =  args[++i];
2044
        } else if ( args[i].equals( "-d" ) ) {
2045
          docid =  args[++i];
2046 429 jones
        } else if ( args[i].equals( "-t" ) ) {
2047
          showRuntime = true;
2048
        } else if ( args[i].equals( "-old" ) ) {
2049
          useOldReadAlgorithm = true;
2050 407 jones
        } else {
2051
          System.err.println
2052
            ( "   args[" +i+ "] '" +args[i]+ "' ignored." );
2053
        }
2054
      }
2055
2056 408 jones
      // Check if the required arguments are provided
2057 407 jones
      boolean argsAreValid = false;
2058
      if (action != null) {
2059
        if (action.equals("INSERT")) {
2060
          if (filename != null) {
2061
            argsAreValid = true;
2062
          }
2063
        } else if (action.equals("UPDATE")) {
2064
          if ((filename != null) && (docid != null)) {
2065
            argsAreValid = true;
2066
          }
2067
        } else if (action.equals("DELETE")) {
2068
          if (docid != null) {
2069
            argsAreValid = true;
2070
          }
2071
        } else if (action.equals("READ")) {
2072
          if (docid != null) {
2073
            argsAreValid = true;
2074
          }
2075
        }
2076
      }
2077
2078 408 jones
      // Print usage message if the arguments are not valid
2079 407 jones
      if (!argsAreValid) {
2080
        System.err.println("Wrong number of arguments!!!");
2081
        System.err.println(
2082 598 bojilova
          "USAGE: java DocumentImpl [-t] <-a INSERT> [-d docid] <-f filename> "+
2083 680 bojilova
          "[-r dtdfilename]");
2084 407 jones
        System.err.println(
2085 598 bojilova
          "   OR: java DocumentImpl [-t] <-a UPDATE -d docid -f filename> " +
2086 680 bojilova
          "[-r dtdfilename]");
2087 407 jones
        System.err.println(
2088 429 jones
          "   OR: java DocumentImpl [-t] <-a DELETE -d docid>");
2089 407 jones
        System.err.println(
2090 429 jones
          "   OR: java DocumentImpl [-t] [-old] <-a READ -d docid>");
2091 407 jones
        return;
2092
      }
2093 429 jones
2094
      // Time the request if asked for
2095
      double startTime = System.currentTimeMillis();
2096
2097 407 jones
      // Open a connection to the database
2098
      MetaCatUtil util = new MetaCatUtil();
2099
      Connection dbconn = util.openDBConnection();
2100
2101 463 berkley
      double connTime = System.currentTimeMillis();
2102 408 jones
      // Execute the action requested (READ, INSERT, UPDATE, DELETE)
2103 407 jones
      if (action.equals("READ")) {
2104
          DocumentImpl xmldoc = new DocumentImpl( dbconn, docid );
2105 429 jones
          if (useOldReadAlgorithm) {
2106
            System.out.println(xmldoc.readUsingSlowAlgorithm());
2107
          } else {
2108
            xmldoc.toXml(new PrintWriter(System.out));
2109
          }
2110 408 jones
      } else if (action.equals("DELETE")) {
2111 425 bojilova
        DocumentImpl.delete(dbconn, docid, null, null);
2112 408 jones
        System.out.println("Document deleted: " + docid);
2113 407 jones
      } else {
2114 680 bojilova
        String newdocid = DocumentImpl.write(dbconn, filename, null,
2115 598 bojilova
                                             dtdfilename, action, docid,
2116
                                             null, null);
2117 408 jones
        if ((docid != null) && (!docid.equals(newdocid))) {
2118
          if (action.equals("INSERT")) {
2119
            System.out.println("New document ID generated!!! ");
2120
          } else if (action.equals("UPDATE")) {
2121
            System.out.println("ERROR: Couldn't update document!!! ");
2122 407 jones
          }
2123 408 jones
        } else if ((docid == null) && (action.equals("UPDATE"))) {
2124
          System.out.println("ERROR: Couldn't update document!!! ");
2125 407 jones
        }
2126 408 jones
        System.out.println("Document processing finished for: " + filename
2127
              + " (" + newdocid + ")");
2128 407 jones
      }
2129
2130 429 jones
      double stopTime = System.currentTimeMillis();
2131 463 berkley
      double dbOpenTime = (connTime - startTime)/1000;
2132
      double insertTime = (stopTime - connTime)/1000;
2133 429 jones
      double executionTime = (stopTime - startTime)/1000;
2134
      if (showRuntime) {
2135 463 berkley
        System.out.println("\n\nTotal Execution time was: " +
2136
                           executionTime + " seconds.");
2137
        System.out.println("Time to open DB connection was: " + dbOpenTime +
2138
                           " seconds.");
2139
        System.out.println("Time to insert document was: " + insertTime +
2140
                           " seconds.");
2141 429 jones
      }
2142 463 berkley
      dbconn.close();
2143 407 jones
    } catch (McdbException me) {
2144
      me.toXml(new PrintWriter(System.err));
2145
    } catch (AccessionNumberException ane) {
2146
      System.out.println(ane.getMessage());
2147
    } catch (Exception e) {
2148
      System.err.println("EXCEPTION HANDLING REQUIRED");
2149
      System.err.println(e.getMessage());
2150
      e.printStackTrace(System.err);
2151
    }
2152
  }
2153 393 jones
}