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