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
        // Opening separate db connection for deleting and writing
1184 2297 jones
        // XML Index -- be sure that it is all in one db transaction
1185
        int serialNumber = -1;
1186
        DBConnection dbConn = null;
1187
        try {
1188
            dbConn = DBConnectionPool.getDBConnection(
1189
                "DocumentImpl.buildIndex");
1190
            serialNumber = dbConn.getCheckOutSerialNumber();
1191
            dbConn.setAutoCommit(false);
1192
            //make sure record is done
1193
            //checkDocumentTable();
1194 2372 sgarg
1195 2297 jones
            // Delete the previous index entries for this document
1196
            deleteNodeIndex(dbConn);
1197 2372 sgarg
1198 2297 jones
            // Step through all of the node records we were given
1199
            // and build the new index and update the database
1200
            it = nodeRecordLists.iterator();
1201
            while (it.hasNext()) {
1202
                NodeRecord currentNode = (NodeRecord) it.next();
1203
                HashMap pathList = new HashMap();
1204
                if (currentNode.nodetype.equals("ELEMENT") ||
1205
                    currentNode.nodetype.equals("ATTRIBUTE") ) {
1206 2269 jones
1207 2297 jones
                    if (atRootElement) {
1208
                        rootNodeId = currentNode.getNodeId();
1209
                        atRootElement = false;
1210
                    }
1211 2372 sgarg
                    traverseParents(nodeRecordMap, rootNodeId,
1212 2297 jones
                            currentNode.getNodeId(),
1213 2436 sgarg
                            currentNode.getNodeId(), "", pathList);
1214 2297 jones
                    updateNodeIndex(dbConn, pathList);
1215 2269 jones
                }
1216
            }
1217 2297 jones
            dbConn.commit();
1218
        } catch (SQLException e) {
1219
            MetaCatUtil.debugMessage(
1220
                "SQL Exception while inserting path index in " +
1221
                "DocumentImpl.buildIndex for document " + docid, 10);
1222 2301 jones
      		MetaCatUtil.debugMessage(e.getMessage(), 10);
1223 2297 jones
            e.printStackTrace();
1224
            try {
1225
                dbConn.rollback();
1226
            } catch (SQLException sqle) {
1227 2301 jones
            	MetaCatUtil.debugMessage(
1228
					"Error while rolling back commit in DocumentImpl.buildIndex"
1229 2297 jones
                    + "\n" + sqle.getMessage(), 10);
1230
            }
1231
        } finally {
1232 2301 jones
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1233 2269 jones
        }
1234
    }
1235
1236 2292 sgarg
    /**
1237
     * Recurse up the parent node hierarchy and add each node to the
1238 2269 jones
     * hashmap of paths to be indexed.
1239
     *
1240
     * @param records the set of records hashed by nodeId
1241 2293 jones
     * @param rootNodeId the id of the root element of the document
1242 2297 jones
     * @param leafNodeId the id of the leafNode being processed
1243 2269 jones
     * @param id the id of the current node to be processed
1244
     * @param children the string representation of all child nodes of this id
1245 2297 jones
     * @param pathList the hash to which paths are added
1246 2376 sgarg
     * @param nodedata the nodedata for the current node
1247 2269 jones
     */
1248 2372 sgarg
    private void traverseParents(HashMap records, long rootNodeId,
1249
            long leafNodeId, long id,
1250 2436 sgarg
            String children, HashMap pathList) {
1251 2297 jones
        Long nodeId = new Long(id);
1252
        NodeRecord current = (NodeRecord)records.get(nodeId);
1253
        long parentId = current.getParentNodeId();
1254 2269 jones
        String currentName = current.getNodeName();
1255
        if (current.nodetype.equals("ELEMENT") ||
1256
            current.nodetype.equals("ATTRIBUTE") ) {
1257
1258 2293 jones
            if (children.equals("")) {
1259 2315 jones
                if (current.nodetype.equals("ATTRIBUTE")) {
1260
                    currentName = "@" + currentName;
1261
                }
1262
                MetaCatUtil.debugMessage("A: " + currentName +"\n", 60);
1263 2376 sgarg
                pathList.put(currentName, new PathIndexEntry(leafNodeId,
1264 2436 sgarg
                    currentName, docid, doctype, parentId));
1265 2293 jones
            }
1266 2269 jones
            currentName = "/" + currentName;
1267
            currentName = currentName + children;
1268
            if (parentId != 0) {
1269 2297 jones
                traverseParents(records, rootNodeId, leafNodeId,
1270 2436 sgarg
                    parentId, currentName, pathList);
1271 2269 jones
            }
1272 2297 jones
            String path = current.getNodeName() + children;
1273 2269 jones
            if (!children.equals("")) {
1274 2315 jones
                MetaCatUtil.debugMessage("B: " + path +"\n", 60);
1275 2372 sgarg
                pathList.put(path, new PathIndexEntry(leafNodeId, path, docid,
1276 2436 sgarg
                    doctype, parentId));
1277 2269 jones
            }
1278 2293 jones
            if (id == rootNodeId) {
1279 2297 jones
                String fullPath = '/' + path;
1280 2315 jones
                MetaCatUtil.debugMessage("C: " + fullPath +"\n", 60);
1281 2297 jones
                pathList.put(fullPath, new PathIndexEntry(leafNodeId, fullPath,
1282 2436 sgarg
                    docid, doctype, parentId));
1283 2293 jones
            }
1284 2269 jones
        }
1285
    }
1286
1287 2297 jones
    /**
1288 2372 sgarg
     * Delete the paths from the xml_index table on the database in preparation
1289 2297 jones
     * of a subsequent update.
1290
     *
1291
     * @param conn the database connection to use, keeping a single transaction
1292
     * @throws SQLException if there is an error deleting from the db
1293
     */
1294 2301 jones
    private void deleteNodeIndex(DBConnection conn) throws SQLException
1295 2297 jones
    {
1296
        String familyId = MetaCatUtil.getDocIdFromString(docid);
1297
        String sql = "DELETE FROM xml_index WHERE docid LIKE ?";
1298
        MetaCatUtil.debugMessage(sql, 55);
1299 2315 jones
        MetaCatUtil.debugMessage("SQL is: " + sql, 60);
1300 2372 sgarg
1301 2297 jones
        PreparedStatement pstmt = conn.prepareStatement(sql);
1302
1303
        // Increase usage count for the connection
1304
        conn.increaseUsageCount(1);
1305 2372 sgarg
1306 2297 jones
        // Execute the delete and close the statement
1307
        pstmt.setString(1, familyId);
1308
        int rows = pstmt.executeUpdate();
1309
        pstmt.close();
1310
        MetaCatUtil.debugMessage("Deleted " + rows + " rows from xml_index " +
1311
            "for document " + docid, 55);
1312
    }
1313 2372 sgarg
1314 2297 jones
    /**
1315 2301 jones
	 * Insert the paths from the pathList into the xml_index table on the
1316 2297 jones
     * database.
1317
     *
1318
     * @param conn the database connection to use, keeping a single transaction
1319
     * @param pathList the hash of paths to insert
1320
     * @throws SQLException if there is an error inserting into the db
1321
     */
1322 2372 sgarg
    private void updateNodeIndex(DBConnection conn, HashMap pathList)
1323 2301 jones
    	throws SQLException
1324 2297 jones
    {
1325
        // Create an insert statement to reuse for all of the path
1326
        // insertions
1327
        PreparedStatement pstmt = conn.prepareStatement(
1328
                "INSERT INTO xml_index (nodeid, path, docid, doctype, " +
1329 2435 sgarg
                "parentnodeid) " + "VALUES (?, ?, ?, ?, ?)");
1330 2297 jones
        // Increase usage count for the connection
1331
        conn.increaseUsageCount(1);
1332
        String familyId = MetaCatUtil.getDocIdFromString(docid);
1333
        pstmt.setString(3, familyId);
1334
        pstmt.setString(4, doctype);
1335 2372 sgarg
1336 2297 jones
        // Step through the hashtable and insert each of the path values
1337
        Iterator it = pathList.values().iterator();
1338
        while (it.hasNext()) {
1339
            PathIndexEntry entry = (PathIndexEntry)it.next();
1340 2315 jones
            MetaCatUtil.debugMessage("Inserting: " + entry.nodeId +
1341
                " (" + entry.parentId + "): " + entry.path, 60);
1342 2297 jones
            pstmt.setLong(1, entry.nodeId);
1343
            pstmt.setString(2, entry.path);
1344
            pstmt.setLong(5, entry.parentId);
1345
            pstmt.executeUpdate();
1346
        }
1347
        // Close the database statement
1348
        pstmt.close();
1349
    }
1350 2372 sgarg
1351 2249 jones
    private boolean isRevisionOnly(DocumentIdentifier docid) throws Exception
1352 622 berkley
    {
1353 2249 jones
        //System.out.println("inRevisionOnly");
1354
        DBConnection dbconn = null;
1355
        int serialNumber = -1;
1356
        PreparedStatement pstmt = null;
1357
        String rev = docid.getRev();
1358
        String newid = docid.getIdentifier();
1359
        try {
1360
            dbconn = DBConnectionPool
1361
                    .getDBConnection("DocumentImpl.isRevisionOnly");
1362
            serialNumber = dbconn.getCheckOutSerialNumber();
1363
            pstmt = dbconn.prepareStatement("select rev from xml_documents "
1364
                    + "where docid like '" + newid + "'");
1365
            pstmt.execute();
1366
            ResultSet rs = pstmt.getResultSet();
1367
            boolean tablehasrows = rs.next();
1368
            if (rev.equals("newest") || rev.equals("all")) { return false; }
1369
1370
            if (tablehasrows) {
1371
                int r = rs.getInt(1);
1372
                pstmt.close();
1373
                if (new Integer(rev).intValue() == r) { //the current revision
1374
                                                        // in in xml_documents
1375
                    //System.out.println("returning false");
1376
                    return false;
1377
                } else if (new Integer(rev).intValue() < r) { //the current
1378
                                                              // revision is in
1379
                                                              // xml_revisions.
1380
                    //System.out.println("returning true");
1381
                    return true;
1382
                } else if (new Integer(rev).intValue() > r) { //error, rev
1383
                                                              // cannot be
1384
                                                              // greater than r
1385
                throw new Exception(
1386
                        "requested revision cannot be greater than "
1387
                                + "the latest revision number."); }
1388
            }
1389
            // Get miss docid and rev, throw to McdDocNotFoundException
1390
            String missDocId = MetaCatUtil.getDocIdFromString(docid.toString());
1391
            String missRevision = MetaCatUtil.getRevisionStringFromString(docid
1392
                    .toString());
1393
            throw new McdbDocNotFoundException("the requested docid '"
1394
                    + docid.toString() + "' does not exist", missDocId,
1395
                    missRevision);
1396
        }//try
1397
        finally {
1398
            pstmt.close();
1399
            DBConnectionPool.returnDBConnection(dbconn, serialNumber);
1400
        }//finally
1401 622 berkley
    }
1402 2249 jones
1403
    private void getDocumentInfo(String docid) throws McdbException,
1404
            AccessionNumberException, Exception
1405 622 berkley
    {
1406 2249 jones
        getDocumentInfo(new DocumentIdentifier(docid));
1407 622 berkley
    }
1408 1292 tao
1409 2249 jones
    /**
1410
     * Look up the document type information from the database
1411 2253 sgarg
     *
1412 2249 jones
     * @param docid
1413
     *            the id of the document to look up
1414
     */
1415
    private void getDocumentInfo(DocumentIdentifier docid)
1416
            throws McdbException, Exception
1417
    {
1418
        DBConnection dbconn = null;
1419
        int serialNumber = -1;
1420
        PreparedStatement pstmt = null;
1421
        String table = "xml_documents";
1422 2092 tao
1423 2249 jones
        try {
1424
            if (isRevisionOnly(docid)) { //pull the document from xml_revisions
1425
                                         // instead of from xml_documents;
1426
                table = "xml_revisions";
1427
            }
1428
        }
1429
        // catch a McdbDocNotFoundException throw it
1430
        catch (McdbDocNotFoundException notFound) {
1431
            throw notFound;
1432
        } catch (Exception e) {
1433 2092 tao
1434 2249 jones
            MetaCatUtil.debugMessage("error in DocumentImpl.getDocumentInfo: "
1435
                    + e.getMessage(), 30);
1436
            throw e;
1437
        }
1438 393 jones
1439 2249 jones
        try {
1440
            dbconn = DBConnectionPool
1441
                    .getDBConnection("DocumentImpl.getDocumentInfo");
1442
            serialNumber = dbconn.getCheckOutSerialNumber();
1443
            StringBuffer sql = new StringBuffer();
1444
            sql.append("SELECT docname, doctype, rootnodeid, ");
1445
            sql.append("date_created, date_updated, user_owner, user_updated,");
1446
            sql.append(" server_location, public_access, rev");
1447
            sql.append(" FROM ").append(table);
1448
            sql.append(" WHERE docid LIKE '").append(docid.getIdentifier());
1449
            sql.append("' and rev like '").append(docid.getRev()).append("'");
1450 2259 sgarg
1451 2249 jones
            pstmt = dbconn.prepareStatement(sql.toString());
1452 2092 tao
1453 2249 jones
            pstmt.execute();
1454
            ResultSet rs = pstmt.getResultSet();
1455
            boolean tableHasRows = rs.next();
1456
            if (tableHasRows) {
1457
                this.docname = rs.getString(1);
1458
                this.doctype = rs.getString(2);
1459
                this.rootnodeid = rs.getLong(3);
1460
                this.createdate = rs.getString(4);
1461
                this.updatedate = rs.getString(5);
1462
                this.userowner = rs.getString(6);
1463
                this.userupdated = rs.getString(7);
1464
                this.serverlocation = rs.getInt(8);
1465
                this.publicaccess = rs.getString(9);
1466
                this.rev = rs.getInt(10);
1467
            }
1468
            pstmt.close();
1469 2092 tao
1470 2249 jones
            //get doc home server name
1471
            pstmt = dbconn.prepareStatement("select server "
1472
                    + "from xml_replication where serverid = ?");
1473
            //because connection use twice here, so we need to increase one
1474
            dbconn.increaseUsageCount(1);
1475
            pstmt.setInt(1, serverlocation);
1476
            pstmt.execute();
1477
            rs = pstmt.getResultSet();
1478
            tableHasRows = rs.next();
1479
            if (tableHasRows) {
1480 2092 tao
1481 2249 jones
                String server = rs.getString(1);
1482
                //get homeserver name
1483
                if (!server.equals("localhost")) {
1484
                    this.docHomeServer = server;
1485
                } else {
1486
                    this.docHomeServer = MetaCatUtil
1487
                            .getLocalReplicationServerName();
1488
                }
1489
                MetaCatUtil.debugMessage("server: " + docHomeServer, 50);
1490 2092 tao
1491 2249 jones
            }
1492
            pstmt.close();
1493
            if (this.doctype != null) {
1494
                pstmt = dbconn.prepareStatement("SELECT system_id, entry_type "
1495
                        + "FROM xml_catalog " + "WHERE public_id = ?");
1496
                //should increase usage count again
1497
                dbconn.increaseUsageCount(1);
1498
                // Bind the values to the query
1499
                pstmt.setString(1, doctype);
1500 2092 tao
1501 2249 jones
                pstmt.execute();
1502
                rs = pstmt.getResultSet();
1503
                tableHasRows = rs.next();
1504
                if (tableHasRows) {
1505
                    this.system_id = rs.getString(1);
1506
                    this.validateType = rs.getString(2);
1507 2092 tao
1508 2249 jones
                }
1509
                pstmt.close();
1510
            }
1511
        } catch (SQLException e) {
1512
            System.out.println("error in DocumentImpl.getDocumentInfo: "
1513
                    + e.getMessage());
1514
            e.printStackTrace(System.out);
1515
            throw new McdbException("Error accessing database connection in "
1516
                    + "DocumentImpl.getDocumentInfo: ", e);
1517
        } finally {
1518
            try {
1519
                pstmt.close();
1520
            } catch (SQLException ee) {
1521
                MetaCatUtil.debugMessage(
1522
                        "error in DocumentImple.getDocumentInfo: "
1523
                                + ee.getMessage(), 30);
1524
            } finally {
1525
                DBConnectionPool.returnDBConnection(dbconn, serialNumber);
1526
            }
1527 2092 tao
        }
1528 393 jones
1529 2253 sgarg
        if (this.docname == null) {
1530 2249 jones
            throw new McdbDocNotFoundException(
1531
                "Document not found: " + docid, docid.getIdentifier(), docid
1532 2253 sgarg
                        .getRev());
1533 2249 jones
        }
1534 393 jones
    }
1535 2092 tao
1536 2249 jones
    /**
1537
     * Look up the node data from the database, but some node would be shown
1538
     * because of access control
1539 2253 sgarg
     *
1540 2249 jones
     * @param rootnodeid
1541
     *            the id of the root node of the node tree to look up
1542
     * @param accessControl
1543
     *            the hashtable has control info
1544
     */
1545
    private TreeSet getPartNodeRecordList(long rootnodeid,
1546
            Hashtable accessControl) throws McdbException
1547
    {
1548
        PreparedStatement pstmt = null;
1549
        DBConnection dbconn = null;
1550
        int serialNumber = -1;
1551
        TreeSet nodeRecordList = new TreeSet(new NodeComparator());
1552
        long nodeid = 0;
1553
        long parentnodeid = 0;
1554
        long nodeindex = 0;
1555
        String nodetype = null;
1556
        String nodename = null;
1557
        String nodeprefix = null;
1558
        String nodedata = null;
1559
        String quotechar = dbAdapter.getStringDelimiter();
1560
        String sql = "SELECT nodeid,parentnodeid,nodeindex, "
1561
                + "nodetype,nodename,nodeprefix,nodedata "
1562
                + "FROM xml_nodes WHERE rootnodeid = ?";
1563 2092 tao
1564 2249 jones
        // go through the access control for some nodes
1565
        Enumeration en = accessControl.elements();
1566
        while (en.hasMoreElements()) {
1567
            SubTree tree = (SubTree) en.nextElement();
1568
            long startId = tree.getStartNodeId();
1569
            long endId = tree.getEndNodeId();
1570
            sql = sql + " AND(nodeid < " + startId + " OR nodeid > " + endId
1571
                    + ")";
1572 2092 tao
1573 2249 jones
        }
1574
        MetaCatUtil.debugMessage("The final query to select part node tree: "
1575
                + sql, 25);
1576 393 jones
1577 2249 jones
        try {
1578
            dbconn = DBConnectionPool
1579
                    .getDBConnection("DocumentImpl.getPartNodeRecordList");
1580
            serialNumber = dbconn.getCheckOutSerialNumber();
1581
            pstmt = dbconn.prepareStatement(sql);
1582 1439 tao
1583 2249 jones
            // Bind the values to the query
1584
            pstmt.setLong(1, rootnodeid);
1585
            pstmt.execute();
1586
            ResultSet rs = pstmt.getResultSet();
1587
            boolean tableHasRows = rs.next();
1588
            while (tableHasRows) {
1589
                nodeid = rs.getLong(1);
1590
                parentnodeid = rs.getLong(2);
1591
                nodeindex = rs.getLong(3);
1592
                nodetype = rs.getString(4);
1593
                nodename = rs.getString(5);
1594
                nodeprefix = rs.getString(6);
1595
                nodedata = rs.getString(7);
1596
                nodedata = MetaCatUtil.normalize(nodedata);
1597
                // add the data to the node record list hashtable
1598
                NodeRecord currentRecord = new NodeRecord(nodeid, parentnodeid,
1599
                        nodeindex, nodetype, nodename, nodeprefix, nodedata);
1600
                nodeRecordList.add(currentRecord);
1601 1439 tao
1602 2249 jones
                // Advance to the next node
1603
                tableHasRows = rs.next();
1604
            }
1605
            pstmt.close();
1606 1439 tao
1607 2249 jones
        } catch (SQLException e) {
1608
            throw new McdbException(
1609
                    "Error in DocumentImpl.getPartNodeRecordList "
1610
                            + e.getMessage());
1611
        } finally {
1612
            try {
1613
                pstmt.close();
1614
            } catch (SQLException ee) {
1615
                MetaCatUtil.debugMessage(
1616
                        "error in DocumentImpl.getPartNodeRecordList: "
1617
                                + ee.getMessage(), 30);
1618
            } finally {
1619
                DBConnectionPool.returnDBConnection(dbconn, serialNumber);
1620
            }
1621
        }
1622 1439 tao
1623 2249 jones
        if (!nodeRecordList.isEmpty()) {
1624 2092 tao
1625 2249 jones
            return nodeRecordList;
1626
        } else {
1627 2092 tao
1628 2249 jones
            throw new McdbException("Error getting node data: " + docid);
1629
        }
1630 2092 tao
    }
1631 2249 jones
1632
    /**
1633
     * Look up the node data from the database
1634 2253 sgarg
     *
1635 2249 jones
     * @param rootnodeid
1636
     *            the id of the root node of the node tree to look up
1637
     */
1638
    private TreeSet getNodeRecordList(long rootnodeid) throws McdbException
1639 1439 tao
    {
1640 2249 jones
        PreparedStatement pstmt = null;
1641
        DBConnection dbconn = null;
1642
        int serialNumber = -1;
1643
        TreeSet nodeRecordList = new TreeSet(new NodeComparator());
1644
        long nodeid = 0;
1645
        long parentnodeid = 0;
1646
        long nodeindex = 0;
1647
        String nodetype = null;
1648
        String nodename = null;
1649
        String nodeprefix = null;
1650
        String nodedata = null;
1651
        String quotechar = dbAdapter.getStringDelimiter();
1652 2092 tao
1653 2249 jones
        try {
1654
            dbconn = DBConnectionPool
1655
                    .getDBConnection("DocumentImpl.getNodeRecordList");
1656
            serialNumber = dbconn.getCheckOutSerialNumber();
1657
            pstmt = dbconn
1658
                    .prepareStatement("SELECT nodeid,parentnodeid,nodeindex, "
1659
                            + "nodetype,nodename,nodeprefix,nodedata "
1660
                            + "FROM xml_nodes WHERE rootnodeid = ?");
1661 2092 tao
1662 2249 jones
            // Bind the values to the query
1663
            pstmt.setLong(1, rootnodeid);
1664 393 jones
1665 2249 jones
            pstmt.execute();
1666
            ResultSet rs = pstmt.getResultSet();
1667
            boolean tableHasRows = rs.next();
1668
            while (tableHasRows) {
1669
                nodeid = rs.getLong(1);
1670
                parentnodeid = rs.getLong(2);
1671
                nodeindex = rs.getLong(3);
1672
                nodetype = rs.getString(4);
1673
                nodename = rs.getString(5);
1674
                nodeprefix = rs.getString(6);
1675
                nodedata = rs.getString(7);
1676
                // add the data to the node record list hashtable
1677
                NodeRecord currentRecord = new NodeRecord(nodeid, parentnodeid,
1678
                        nodeindex, nodetype, nodename, nodeprefix, nodedata);
1679
                nodeRecordList.add(currentRecord);
1680 393 jones
1681 2249 jones
                // Advance to the next node
1682
                tableHasRows = rs.next();
1683
            }
1684
            pstmt.close();
1685 393 jones
1686 2249 jones
        } catch (SQLException e) {
1687
            throw new McdbException("Error in DocumentImpl.getNodeRecordList "
1688
                    + e.getMessage());
1689
        } finally {
1690
            try {
1691
                pstmt.close();
1692
            } catch (SQLException ee) {
1693
                MetaCatUtil.debugMessage(
1694
                        "error in DocumentImpl.getNodeRecordList: "
1695
                                + ee.getMessage(), 30);
1696
            } finally {
1697
                DBConnectionPool.returnDBConnection(dbconn, serialNumber);
1698
            }
1699
        }
1700 393 jones
1701 2249 jones
        return nodeRecordList;
1702 393 jones
1703
    }
1704 2249 jones
1705
    /** creates SQL code and inserts new document into DB connection */
1706
    private void writeDocumentToDB(String action, String user, String pub,
1707
            String catalogid, int serverCode) throws SQLException, Exception
1708 1217 tao
    {
1709 2249 jones
        String sysdate = dbAdapter.getDateTimeFunction();
1710 2092 tao
1711 2249 jones
        try {
1712
            PreparedStatement pstmt = null;
1713 2092 tao
1714 2249 jones
            if (action.equals("INSERT")) {
1715
                //AccessionNumber ac = new AccessionNumber();
1716
                //this.docid = ac.generate(docid, "INSERT");
1717 2092 tao
1718 2249 jones
                pstmt = connection
1719
                        .prepareStatement("INSERT INTO xml_documents "
1720
                        + "(docid, rootnodeid, docname, doctype, user_owner, "
1721
                        + "user_updated, date_created, date_updated, "
1722
                        + "public_access, catalog_id, server_location, rev) "
1723
                        + "VALUES (?, ?, ?, ?, ?, ?, " + sysdate + ", "
1724
                        + sysdate + ", ?, ?, ?, ?)");
1725
                // Increase dbconnection usage count
1726
                connection.increaseUsageCount(1);
1727 393 jones
1728 2249 jones
                //note that the server_location is set to 1.
1729
                //this means that "localhost" in the xml_replication table must
1730
                //always be the first entry!!!!!
1731 747 bojilova
1732 2249 jones
                // Bind the values to the query
1733
                pstmt.setString(1, this.docid);
1734
                pstmt.setLong(2, rootnodeid);
1735
                pstmt.setString(3, docname);
1736
                pstmt.setString(4, doctype);
1737
                pstmt.setString(5, user);
1738
                pstmt.setString(6, user);
1739
                //public access is usefulless, so set it to null
1740
                pstmt.setString(7, null);
1741
                /*
1742
                 * if ( pub == null ) { pstmt.setString(7, null); } else if (
1743
                 * pub.toUpperCase().equals("YES") || pub.equals("1") ) {
1744
                 * pstmt.setInt(7, 1); } else if (
1745
                 * pub.toUpperCase().equals("NO") || pub.equals("0") ) {
1746
                 * pstmt.setInt(7, 0); }
1747
                 */
1748
                pstmt.setString(8, catalogid);
1749
                pstmt.setInt(9, serverCode);
1750
                pstmt.setInt(10, Integer.parseInt(updatedVersion));
1751
            } else if (action.equals("UPDATE")) {
1752 459 bojilova
1753 2249 jones
                // Save the old document publicaccessentry in a backup table
1754
                DocumentImpl.archiveDocRevision(connection, docid, user);
1755
                MetaCatUtil.debugMessage("after archiveDoc", 40);
1756
                DocumentImpl thisdoc = new DocumentImpl(docid, false);
1757
                int thisrev = thisdoc.getRev();
1758
                MetaCatUtil.debugMessage("this revsion is: " + thisrev, 40);
1759
                //if the updated vesion is not greater than current one,
1760
                //throw it into a exception
1761
                if (Integer.parseInt(updatedVersion) <= thisrev) {
1762
                    throw new Exception("Next revision number couldn't be less"
1763
                            + " than or equal " + thisrev);
1764
                } else {
1765
                    //set the user specified revision
1766
                    thisrev = Integer.parseInt(updatedVersion);
1767
                }
1768
                MetaCatUtil.debugMessage("final revsion is: " + thisrev, 40);
1769
                boolean useXMLIndex = (new Boolean(MetaCatUtil
1770
                        .getOption("usexmlindex"))).booleanValue();
1771
                if (useXMLIndex) {
1772
                    MetaCatUtil.debugMessage("before delete", 40);
1773
                    // Delete index for the old version of docid
1774
                    // The new index is inserting on the next calls to DBSAXNode
1775
                    pstmt = connection
1776
                            .prepareStatement("DELETE FROM xml_index WHERE docid='"
1777
                                    + this.docid + "'");
1778
                    MetaCatUtil.debugMessage("after delete", 40);
1779
                    // Increase dbconnection usage count
1780
                    connection.increaseUsageCount(1);
1781 2092 tao
1782 2249 jones
                    pstmt.execute();
1783
                    pstmt.close();
1784
                }
1785 2092 tao
1786 2249 jones
                // Update the new document to reflect the new node tree
1787
                pstmt = connection
1788
                        .prepareStatement("UPDATE xml_documents "
1789
                        + "SET rootnodeid = ?, docname = ?, doctype = ?, "
1790
                        + "user_updated = ?, date_updated = "
1791
                        + sysdate
1792
                        + ", "
1793
                        + "server_location = ?, rev = ?, public_access = ?, "
1794
                        + "catalog_id = ? "
1795
                        + "WHERE docid = ?");
1796
                // Increase dbconnection usage count
1797
                connection.increaseUsageCount(1);
1798
                // Bind the values to the query
1799
                pstmt.setLong(1, rootnodeid);
1800
                pstmt.setString(2, docname);
1801
                pstmt.setString(3, doctype);
1802
                pstmt.setString(4, user);
1803
                pstmt.setInt(5, serverCode);
1804
                pstmt.setInt(6, thisrev);
1805
                pstmt.setString(7, null);
1806
                /*
1807
                 * if ( pub == null ) { pstmt.setString(7, null); } else if (
1808
                 * pub.toUpperCase().equals("YES") || pub.equals("1") ) { pstmt
1809
                 * .setInt(7, 1); } else if ( pub.toUpperCase().equals("NO") ||
1810
                 * pub.equals("0") ) { pstmt.setInt(7, 0); }
1811
                 */
1812
                pstmt.setString(8, catalogid);
1813
                pstmt.setString(9, this.docid);
1814 2092 tao
1815 2249 jones
            } else {
1816
                System.err.println("Action not supported: " + action);
1817
            }
1818 459 bojilova
1819 2249 jones
            // Do the insertion
1820
            pstmt.execute();
1821 2092 tao
1822
            pstmt.close();
1823 2249 jones
1824
        } catch (SQLException sqle) {
1825
            throw sqle;
1826
        } catch (Exception e) {
1827
            throw e;
1828 2076 jones
        }
1829 459 bojilova
    }
1830
1831 2249 jones
    /**
1832
     * Write an XML file to the database, given a filename
1833 2253 sgarg
     *
1834 2249 jones
     * @param conn
1835
     *            the JDBC connection to the database
1836
     * @param filename
1837
     *            the filename to be loaded into the database
1838
     * @param pub
1839
     *            flag for public "read" access on document
1840
     * @param dtdfilename
1841
     *            the dtd to be uploaded on server's file system
1842
     * @param action
1843
     *            the action to be performed (INSERT OR UPDATE)
1844
     * @param docid
1845
     *            the docid to use for the INSERT OR UPDATE
1846
     * @param user
1847
     *            the user that owns the document
1848
     * @param groups
1849
     *            the groups to which user belongs
1850
     */
1851
    /*
1852
     * public static String write(DBConnection conn,String filename, String pub,
1853
     * String dtdfilename, String action, String docid, String user, String[]
1854
     * groups ) throws Exception {
1855 2253 sgarg
     *
1856 2249 jones
     * Reader dtd = null; if ( dtdfilename != null ) { dtd = new FileReader(new
1857
     * File(dtdfilename).toString()); } return write ( conn, new FileReader(new
1858
     * File(filename).toString()), pub, dtd, action, docid, user, groups,
1859
     * false); }
1860
     */
1861 2092 tao
1862 2249 jones
    public static String write(DBConnection conn, Reader xml, String pub,
1863
            Reader dtd, String action, String docid, String user,
1864
            String[] groups, String ruleBase, boolean needValidation)
1865
            throws Exception
1866
    {
1867
        //this method will be called in handleUpdateOrInsert method
1868
        //in MetacatServlet class and now is wrapper into documentImple
1869
        // get server location for this doc
1870
        int serverLocation = getServerLocationNumber(docid);
1871
        return write(conn, xml, pub, dtd, action, docid, user, groups,
1872
                serverLocation, false, ruleBase, needValidation);
1873 598 bojilova
    }
1874
1875 2249 jones
    /**
1876
     * Write an XML file to the database, given a Reader
1877 2253 sgarg
     *
1878 2249 jones
     * @param conn
1879
     *            the JDBC connection to the database
1880
     * @param xml
1881
     *            the xml stream to be loaded into the database
1882
     * @param pub
1883
     *            flag for public "read" access on xml document
1884
     * @param dtd
1885
     *            the dtd to be uploaded on server's file system
1886
     * @param action
1887
     *            the action to be performed (INSERT or UPDATE)
1888
     * @param accnum
1889
     *            the docid + rev# to use on INSERT or UPDATE
1890
     * @param user
1891
     *            the user that owns the document
1892
     * @param groups
1893
     *            the groups to which user belongs
1894
     * @param serverCode
1895
     *            the serverid from xml_replication on which this document
1896
     *            resides.
1897
     * @param override
1898
     *            flag to stop insert replication checking. if override = true
1899
     *            then a document not belonging to the local server will not be
1900
     *            checked upon update for a file lock. if override = false then
1901
     *            a document not from this server, upon update will be locked
1902
     *            and version checked.
1903
     */
1904 598 bojilova
1905 2249 jones
    public static String write(DBConnection conn, Reader xml, String pub,
1906
            Reader dtd, String action, String accnum, String user,
1907
            String[] groups, int serverCode, boolean override, String ruleBase,
1908
            boolean needValidation) throws Exception
1909
    {
1910
        // NEW - WHEN CLIENT ALWAYS PROVIDE ACCESSION NUMBER INCLUDING REV IN IT
1911
        //MetaCatUtil util = new MetaCatUtil();
1912
        MetaCatUtil.debugMessage("conn usage count before writting: "
1913
                + conn.getUsageCount(), 50);
1914
        AccessionNumber ac = new AccessionNumber(accnum, action);
1915
        String docid = ac.getDocid();
1916
        String rev = ac.getRev();
1917
        MetaCatUtil.debugMessage("action: " + action + " servercode: "
1918
                + serverCode + " override: " + override, 10);
1919 2092 tao
1920 2253 sgarg
        if ((serverCode != 1 && action.equals("UPDATE")) && !override) {
1921 2249 jones
            // if this document being written is not a resident of this server
1922
            // then we need to try to get a lock from it's resident server. If
1923
            // the resident server will not give a lock then we send the user
1924
            // a  message saying that he/she needs to download a new copy of
1925
            // the file and merge the differences manually.
1926
            int istreamInt;
1927
            char istreamChar;
1928 2092 tao
1929 2249 jones
            // check for 'write' permission for 'user' to update this document
1930 2253 sgarg
            if (!hasWritePermission(user, groups, accnum)) {
1931 2249 jones
                throw new Exception(
1932
                    "User " + user
1933
                    + " does not have permission to update XML Document #"
1934 2253 sgarg
                    + accnum);
1935 2249 jones
            }
1936 559 berkley
1937 2249 jones
            DocumentIdentifier id = new DocumentIdentifier(accnum);
1938
            String updaterev = id.getRev();
1939
            String server = MetacatReplication
1940
                    .getServerNameForServerCode(serverCode);
1941
            MetacatReplication.replLog("attempting to lock " + accnum);
1942
            URL u = new URL("https://" + server + "?server="
1943
                    + MetaCatUtil.getLocalReplicationServerName()
1944
                    + "&action=getlock&updaterev=" + updaterev + "&docid="
1945
                    + docid);
1946
            //System.out.println("sending message: " + u.toString());
1947
            String serverResStr = MetacatReplication.getURLContent(u);
1948
            String openingtag = serverResStr.substring(0, serverResStr
1949
                    .indexOf(">") + 1);
1950
            if (openingtag.equals("<lockgranted>")) {//the lock was granted go
1951
                                                     // ahead with the insert
1952
                XMLReader parser = null;
1953
                try {
1954
                    //System.out.println("In lockgranted");
1955
                    MetacatReplication.replLog("lock granted for " + accnum
1956
                            + " from " + server);
1957
                    /*
1958
                     * XMLReader parser = initializeParser(conn, action, docid,
1959
                     * updaterev, validate, user, groups, pub, serverCode, dtd);
1960
                     */
1961
                    parser = initializeParser(conn, action, docid, updaterev,
1962
                            user, groups, pub, serverCode, dtd, ruleBase,
1963
                            needValidation);
1964
                    conn.setAutoCommit(false);
1965
                    parser.parse(new InputSource(xml));
1966
                    conn.commit();
1967
                    conn.setAutoCommit(true);
1968
                } catch (Exception e) {
1969
                    conn.rollback();
1970
                    conn.setAutoCommit(true);
1971
                    //if it is a eml2 document, we need delete online data
1972
                    if (parser != null) {
1973
                        ContentHandler handler = parser.getContentHandler();
1974
                        if (handler instanceof Eml200SAXHandler) {
1975
                            Eml200SAXHandler eml = (Eml200SAXHandler) handler;
1976
                            eml.deleteInlineFiles();
1977
                        }
1978
                    }
1979
                    throw e;
1980
                }
1981
                // run write into access db base one relation table and access
1982
                // object
1983
                runRelationAndAccessHandler(accnum, user, groups, serverCode);
1984 2092 tao
1985 2249 jones
                // Force replication the docid
1986
                ForceReplicationHandler frh = new ForceReplicationHandler(
1987
                        accnum, true, null);
1988
                return (accnum);
1989 2092 tao
1990 2249 jones
            }
1991 2092 tao
1992 2249 jones
            else if (openingtag.equals("<filelocked>")) {
1993
                // the file is currently locked by another user notify our
1994 2253 sgarg
                // user to wait a few minutes, check out a new copy and try
1995 2249 jones
                // again.
1996
                MetacatReplication.replLog("lock denied for " + accnum + " on "
1997
                        + server + " reason: file already locked");
1998
                throw new Exception(
1999
                        "The file specified is already locked by another "
2000
                                + "user.  Please wait 30 seconds, checkout the "
2001
                                + "newer document, merge your changes and try "
2002
                                + "again.");
2003
            } else if (openingtag.equals("<outdatedfile>")) {
2004
                // our file is outdated. notify our user to check out a new
2005
                // copy of the file and merge his version with the new version.
2006
                //System.out.println("outdated file");
2007
                MetacatReplication.replLog("lock denied for " + accnum + " on "
2008
                        + server + " reason: local file outdated");
2009
                throw new Exception(
2010
                        "The file you are trying to update is an outdated"
2011
                        + " version.  Please checkout the newest document, "
2012
                        + "merge your changes and try again.");
2013 1781 tao
            }
2014 571 berkley
        }
2015 2092 tao
2016 2249 jones
        if (action.equals("UPDATE")) {
2017
            // check for 'write' permission for 'user' to update this document
2018 2253 sgarg
            if (!hasWritePermission(user, groups, accnum)) {
2019 2249 jones
                throw new Exception(
2020
                    "User " + user
2021
                    + " does not have permission to update XML Document #"
2022
                    + accnum); }
2023
        }
2024
        XMLReader parser = null;
2025
        try {
2026
            parser = initializeParser(conn, action, docid, rev, user, groups,
2027
                    pub, serverCode, dtd, ruleBase, needValidation);
2028 2092 tao
2029 2249 jones
            conn.setAutoCommit(false);
2030
            parser.parse(new InputSource(xml));
2031
            conn.commit();
2032
            conn.setAutoCommit(true);
2033
        } catch (Exception e) {
2034
            conn.rollback();
2035
            conn.setAutoCommit(true);
2036
            //if it is a eml2 document, we need delete online data
2037
            if (parser != null) {
2038
                ContentHandler handler = parser.getContentHandler();
2039
                if (handler instanceof Eml200SAXHandler) {
2040
                    Eml200SAXHandler eml = (Eml200SAXHandler) handler;
2041
                    eml.deleteInlineFiles();
2042
                }
2043
            }
2044
            throw e;
2045
        }
2046 734 bojilova
2047 2249 jones
        // run access db base on relation table and access object
2048
        runRelationAndAccessHandler(accnum, user, groups, serverCode);
2049 2092 tao
2050 2420 sgarg
        // Delete enteries from xml_queryresult for given docid if
2051
        // action is UPDATE
2052
        // These enteries will be created again when the docid is part of a
2053
        // result next time
2054
        if (action.equals("UPDATE")) {
2055
          try {
2056
              PreparedStatement pstmt = null;
2057
              pstmt = conn.prepareStatement(
2058
                      "DELETE FROM xml_queryresult WHERE docid = ?");
2059
              pstmt.setString(1, docid);
2060
              pstmt.execute();
2061
              pstmt.close();
2062
              conn.increaseUsageCount(1);
2063
          } catch (Exception e){
2064
              MetaCatUtil.debugMessage("Error in deleting enteries from "
2065
                                       + "xml_queryresult where docid is "
2066
                                       + docid + " in DBQuery.write: "
2067
                                       + e.getMessage(), 20);
2068
           }
2069
2070
        }
2071
2072 2249 jones
        // Force replicate out the new document to each server in our server
2073 2253 sgarg
        // list. Start the thread to replicate this new document out to the
2074
        // other servers true mean it is xml document null is because no
2075 2249 jones
        // metacat notify the force replication.
2076
        ForceReplicationHandler frh = new ForceReplicationHandler(accnum,
2077
                action, true, null);
2078 628 berkley
2079 2249 jones
        MetaCatUtil.debugMessage("Conn Usage count after writting: "
2080
                + conn.getUsageCount(), 50);
2081
        return (accnum);
2082 425 bojilova
    }
2083 2092 tao
2084 2249 jones
    /**
2085
     * Write an XML file to the database during replication
2086 2253 sgarg
     *
2087 2249 jones
     * @param conn
2088
     *            the JDBC connection to the database
2089
     * @param xml
2090
     *            the xml stream to be loaded into the database
2091
     * @param pub
2092
     *            flag for public "read" access on xml document
2093
     * @param dtd
2094
     *            the dtd to be uploaded on server's file system
2095
     * @param action
2096
     *            the action to be performed (INSERT or UPDATE)
2097
     * @param accnum
2098
     *            the docid + rev# to use on INSERT or UPDATE
2099
     * @param user
2100
     *            the user that owns the document
2101
     * @param groups
2102
     *            the groups to which user belongs
2103
     * @param homeServer
2104
     *            the name of server which the document origanlly create
2105
     * @param validate,
2106
     *            if the xml document is valid or not
2107
     * @param notifyServer,
2108
     *            the server which notify local server the force replication
2109
     *            command
2110
     */
2111
    public static String writeReplication(DBConnection conn, Reader xml,
2112
            String pub, Reader dtd, String action, String accnum, String user,
2113
            String[] groups, String homeServer, String notifyServer,
2114
            String ruleBase, boolean needValidation) throws Exception
2115 571 berkley
    {
2116 2249 jones
        MetaCatUtil.debugMessage("user in replication" + user, 30);
2117
        // Docid without revision
2118
        String docid = MetaCatUtil.getDocIdFromAccessionNumber(accnum);
2119
        // Revision specified by user (int)
2120
        int userSpecifyRev = MetaCatUtil.getRevisionFromAccessionNumber(accnum);
2121
        MetaCatUtil.debugMessage("The user specifyRev: " + userSpecifyRev, 30);
2122
        // Revision for this docid in current database
2123
        int revInDataBase = getLatestRevisionNumber(docid);
2124
        MetaCatUtil.debugMessage("The rev in data base: " + revInDataBase, 30);
2125
        // String to store the revision
2126
        String rev = null;
2127 2092 tao
2128 2249 jones
        //revIndataBase=-1, there is no record in xml_documents table
2129
        //the document is a new one for local server, inert it into table
2130
        //user specified rev should be great than 0
2131
        if (revInDataBase == -1 && userSpecifyRev >= 0) {
2132
            // rev equals user specified
2133
            rev = (new Integer(userSpecifyRev)).toString();
2134
            // action should be INSERT
2135
            action = "INSERT";
2136
        }
2137
        //rev is greater the last revsion number and revInDataBase isn't -1
2138
        // it is a updated file
2139
        else if (userSpecifyRev > revInDataBase && revInDataBase >= 0) {
2140
            // rev equals user specified
2141
            rev = (new Integer(userSpecifyRev)).toString();
2142
            // action should be update
2143
            action = "UPDATE";
2144
        }
2145
        // local server has newer version, then notify the remote server
2146
        else if (userSpecifyRev < revInDataBase && revInDataBase > 0) {
2147
            throw new Exception("Local server: "
2148
                    + MetaCatUtil.getOption("server")
2149
                    + " has newer revision of doc: " + docid + "."
2150
                    + revInDataBase + ". Please notify it.");
2151
        }
2152
        //other situation
2153
        else {
2154 2092 tao
2155 2249 jones
            throw new Exception("The docid" + docid
2156
                    + "'s revision number couldn't be " + userSpecifyRev);
2157
        }
2158
        // Variable to store homeserver code
2159
        int serverCode = -2;
2160 2092 tao
2161 2249 jones
        // If server is not int the xml replication talbe, insert it into
2162
        // xml_replication table
2163
        //serverList.addToServerListIfItIsNot(homeServer);
2164
        insertServerIntoReplicationTable(homeServer);
2165
        // Get server code again
2166
        serverCode = getServerCode(homeServer);
2167 2092 tao
2168 2249 jones
        MetaCatUtil
2169
                .debugMessage("Document " + docid + "." + rev + " " + action
2170
                        + " into local" + " metacat with servercode: "
2171
                        + serverCode, 10);
2172 396 jones
2173 2249 jones
        // insert into xml_nodes table
2174
        XMLReader parser = null;
2175
        try {
2176 1055 tao
2177 2249 jones
            parser = initializeParser(conn, action, docid, rev, user, groups,
2178
                    pub, serverCode, dtd, ruleBase, needValidation);
2179
            conn.setAutoCommit(false);
2180
            parser.parse(new InputSource(xml));
2181
            conn.commit();
2182
            conn.setAutoCommit(true);
2183
        } catch (Exception e) {
2184
            conn.rollback();
2185
            conn.setAutoCommit(true);
2186
            if (parser != null) {
2187
                ContentHandler handler = parser.getContentHandler();
2188
                if (handler instanceof Eml200SAXHandler) {
2189
                    Eml200SAXHandler eml = (Eml200SAXHandler) handler;
2190
                    eml.deleteInlineFiles();
2191
                }
2192
            }
2193
            throw e;
2194
        }
2195 2092 tao
2196 2249 jones
        // run write into access db base on relation table and access rule
2197
        try {
2198
            runRelationAndAccessHandler(accnum, user, groups, serverCode);
2199
        } catch (Exception ee) {
2200
            MetacatReplication.replErrorLog("Failed to " + "create access "
2201
                    + "rule for package: " + accnum + " because "
2202
                    + ee.getMessage());
2203
            MetaCatUtil.debugMessage("Failed to  " + "create access "
2204
                    + "rule for package: " + accnum + " because "
2205
                    + ee.getMessage(), 30);
2206
        }
2207
        //Force replication to other server
2208
        ForceReplicationHandler forceReplication = new ForceReplicationHandler(
2209
                accnum, action, true, notifyServer);
2210 2092 tao
2211 2249 jones
        return (accnum);
2212 1069 tao
    }
2213 2249 jones
2214
    /* Running write record to xml_relation and xml_access */
2215
    private static void runRelationAndAccessHandler(String accnumber,
2216
            String userName, String[] group, int servercode) throws Exception
2217 1055 tao
    {
2218 2249 jones
        DBConnection dbconn = null;
2219
        int serialNumber = -1;
2220
        PreparedStatement pstmt = null;
2221
        String documenttype = getDocTypeFromDBForCurrentDocument(accnumber);
2222
        try {
2223
            String packagedoctype = MetaCatUtil.getOption("packagedoctype");
2224
            Vector packagedoctypes = new Vector();
2225
            packagedoctypes = MetaCatUtil.getOptionList(packagedoctype);
2226
            String docIdWithoutRev = MetaCatUtil.getDocIdFromString(accnumber);
2227 2253 sgarg
            if (documenttype != null &&
2228 2249 jones
                    packagedoctypes.contains(documenttype)) {
2229
                dbconn = DBConnectionPool.getDBConnection(
2230
                        "DocumentImpl.runRelationAndAccessHandeler");
2231
                serialNumber = dbconn.getCheckOutSerialNumber();
2232
                dbconn.setAutoCommit(false);
2233
                // from the relations get the access file id for that package
2234
                String aclid = RelationHandler.getAccessFileID(docIdWithoutRev);
2235
                // if there are access file, write ACL for that package
2236
                if (aclid != null) {
2237
                    runAccessControlList(dbconn, aclid, userName, group,
2238
                            servercode);
2239
                }
2240
                dbconn.commit();
2241
                dbconn.setAutoCommit(true);
2242
            }
2243
            // if it is an access file
2244
            else if (documenttype != null
2245
                    && MetaCatUtil.getOptionList(
2246
                            MetaCatUtil.getOption("accessdoctype")).contains(
2247
                            documenttype)) {
2248
                dbconn = DBConnectionPool.getDBConnection(
2249
                        "DocumentImpl.runRelationAndAccessHandeler");
2250
                serialNumber = dbconn.getCheckOutSerialNumber();
2251
                dbconn.setAutoCommit(false);
2252
                // write ACL for the package
2253
                runAccessControlList(dbconn, docIdWithoutRev, userName, group,
2254
                        servercode);
2255
                dbconn.commit();
2256
                dbconn.setAutoCommit(true);
2257 2092 tao
2258 2249 jones
            }
2259
2260
        } catch (Exception e) {
2261
            if (dbconn != null) {
2262
                dbconn.rollback();
2263
                dbconn.setAutoCommit(true);
2264
            }
2265
            MetaCatUtil.debugMessage(
2266
                    "Error in DocumentImple.runRelationAndAccessHandler "
2267
                            + e.getMessage(), 30);
2268
            throw e;
2269
        } finally {
2270
            if (dbconn != null) {
2271
                DBConnectionPool.returnDBConnection(dbconn, serialNumber);
2272
            }
2273
        }
2274 1292 tao
    }
2275 2092 tao
2276 2249 jones
    // It runs in xmlIndex thread. It writes ACL for a package.
2277
    private static void runAccessControlList(DBConnection conn, String aclid,
2278
            String users, String[] group, int servercode) throws Exception
2279 2092 tao
    {
2280 2249 jones
        // read the access file from xml_nodes
2281
        // parse the access file and store the access info into xml_access
2282
        AccessControlList aclobj = new AccessControlList(conn, aclid, users,
2283
                group, servercode);
2284 2092 tao
2285
    }
2286
2287 2249 jones
    /* Method get document type from db */
2288
    private static String getDocTypeFromDBForCurrentDocument(String accnumber)
2289
            throws SQLException
2290 2092 tao
    {
2291 2249 jones
        String docoumentType = null;
2292
        String docid = null;
2293
        PreparedStatement pstate = null;
2294
        ResultSet rs = null;
2295
        String sql = "SELECT doctype FROM xml_documents where docid = ?";
2296
        DBConnection dbConnection = null;
2297
        int serialNumber = -1;
2298
        try {
2299
            //get rid of revision number
2300
            docid = MetaCatUtil.getDocIdFromString(accnumber);
2301
            dbConnection = DBConnectionPool.getDBConnection(
2302
                    "DocumentImpl.getDocTypeFromDBForCurrentDoc");
2303
            serialNumber = dbConnection.getCheckOutSerialNumber();
2304
            pstate = dbConnection.prepareStatement(sql);
2305
            //bind variable
2306
            pstate.setString(1, docid);
2307
            //excute query
2308
            pstate.execute();
2309
            //handle resultset
2310
            rs = pstate.getResultSet();
2311
            if (rs.next()) {
2312
                docoumentType = rs.getString(1);
2313
            }
2314
            rs.close();
2315
            pstate.close();
2316
        }//try
2317
        catch (SQLException e) {
2318
            MetaCatUtil.debugMessage("error in DocumentImpl."
2319
                    + "getDocTypeFromDBForCurrentDocument " + e.getMessage(),
2320
                    30);
2321
            throw e;
2322
        }//catch
2323
        finally {
2324
            pstate.close();
2325
            DBConnectionPool.returnDBConnection(dbConnection, serialNumber);
2326
        }//
2327
        MetaCatUtil.debugMessage("The current doctype from db is: "
2328
                + docoumentType, 35);
2329
        return docoumentType;
2330 1591 tao
    }
2331 1055 tao
2332 2249 jones
    /**
2333
     * Delete an XML file from the database (actually, just make it a revision
2334
     * in the xml_revisions table)
2335 2253 sgarg
     *
2336 2249 jones
     * @param docid
2337
     *            the ID of the document to be deleted from the database
2338
     */
2339 2298 tao
    public static void delete(String accnum, String user, String[] groups, String notifyServer)
2340 2249 jones
            throws Exception
2341 1575 tao
    {
2342 2092 tao
2343 2249 jones
        DBConnection conn = null;
2344
        int serialNumber = -1;
2345
        PreparedStatement pstmt = null;
2346 2298 tao
        boolean isXML   = true;
2347 2249 jones
        try {
2348
            //check out DBConnection
2349
            conn = DBConnectionPool.getDBConnection("DocumentImpl.delete");
2350
            serialNumber = conn.getCheckOutSerialNumber();
2351 2092 tao
2352 2249 jones
            // NEW - WHEN CLIENT ALWAYS PROVIDE ACCESSION NUMBER INCLUDING REV
2353
            // IN IT
2354 2298 tao
            //AccessionNumber ac = new AccessionNumber(accnum, "DELETE");
2355
            String docid = MetaCatUtil.getDocIdFromAccessionNumber(accnum);
2356
            //String rev = ac.getRev();
2357 2092 tao
2358 2372 sgarg
            // Check if the document exists.
2359
            pstmt = conn.prepareStatement("SELECT * FROM xml_documents "
2360
                                          + "WHERE docid = ?");
2361
            pstmt.setString(1, docid);
2362
            pstmt.execute();
2363
            ResultSet rs = pstmt.getResultSet();
2364
            if(!rs.next()){
2365
                rs.close();
2366
                throw new Exception("Docid " + accnum + " does not exsist. "
2367
                                    + "Please check that you have specified the"
2368
                                    + " revision number of the document also.");
2369
            }
2370
            rs.close();
2371
            pstmt.close();
2372
            conn.increaseUsageCount(1);
2373
2374 2298 tao
            // get the type of deleting docid, this will be used in forcereplication
2375
            String type = getDocTypeFromDB(conn, docid);
2376
            if (type != null && type.trim().equals("BIN"))
2377
            {
2378
              isXML = false;
2379
            }
2380
2381 2249 jones
            MetaCatUtil.debugMessage("Start deleting doc " + docid + "...", 20);
2382
            // check for 'write' permission for 'user' to delete this document
2383 2429 sgarg
            if (!hasAllPermission(user, groups, accnum)) {
2384
                boolean adminIsAuthenticated = false;
2385
                String[] administrators = null;
2386
                String adminList = MetaCatUtil.getOption("administrators");
2387
                try {
2388
                    administrators = adminList.split(":");
2389
                } catch (Exception pse) {
2390
                    administrators = null;
2391
                    MetaCatUtil.debugMessage("Error in DocumentImpl.delete: "
2392
                                             + pse.getMessage(), 20);
2393
                }
2394
                for (int i = 0; i < administrators.length; i++) {
2395
                    if (user.equals(administrators[i])) {
2396
                        adminIsAuthenticated = true;
2397
                    }
2398
                }
2399 2092 tao
2400 2429 sgarg
                if(!adminIsAuthenticated){
2401
                    throw new Exception(
2402
                        "User " + user
2403
                        + " does not have permission to delete XML Document #"
2404
                        + accnum);
2405
                }
2406
            }
2407
2408 2249 jones
            conn.setAutoCommit(false);
2409
            // Copy the record to the xml_revisions table
2410
            DocumentImpl.archiveDocRevision(conn, docid, user);
2411 2092 tao
2412 2249 jones
            // Now delete it from the xml_index table
2413
            boolean useXMLIndex = (new Boolean(MetaCatUtil
2414
                    .getOption("usexmlindex"))).booleanValue();
2415 2420 sgarg
2416
           //if (useXMLIndex) {
2417 2249 jones
            pstmt = conn
2418
                    .prepareStatement("DELETE FROM xml_index WHERE docid = ?");
2419
            pstmt.setString(1, docid);
2420
            pstmt.execute();
2421
            pstmt.close();
2422
            conn.increaseUsageCount(1);
2423
            //}
2424 2092 tao
2425 2249 jones
            // Now delete it from xml_access table
2426
            pstmt = conn.prepareStatement(
2427
                    "DELETE FROM xml_access WHERE accessfileid = ?");
2428
            pstmt.setString(1, docid);
2429
            pstmt.execute();
2430
            pstmt.close();
2431
            conn.increaseUsageCount(1);
2432 396 jones
2433 2249 jones
            pstmt = conn.prepareStatement(
2434
                    "DELETE FROM xml_access WHERE docid = ?");
2435
            pstmt.setString(1, docid);
2436
            pstmt.execute();
2437
            pstmt.close();
2438
            conn.increaseUsageCount(1);
2439 2092 tao
2440 2420 sgarg
            // Delete enteries from xml_queryresult
2441
            pstmt = conn.prepareStatement(
2442
                    "DELETE FROM xml_queryresult WHERE docid = ?");
2443
            pstmt.setString(1, docid);
2444
            pstmt.execute();
2445
            pstmt.close();
2446
            conn.increaseUsageCount(1);
2447
2448 2249 jones
            // Delete it from relation table
2449
            pstmt = conn.prepareStatement(
2450
                    "DELETE FROM xml_relation WHERE docid = ?");
2451
            //increase usage count
2452
            conn.increaseUsageCount(1);
2453
            pstmt.setString(1, docid);
2454
            pstmt.execute();
2455
            pstmt.close();
2456 425 bojilova
2457 2249 jones
            // Delete it from xml_accesssubtree table
2458
            pstmt = conn.prepareStatement(
2459
                    "DELETE FROM xml_accesssubtree WHERE docid = ?");
2460
            //increase usage count
2461
            conn.increaseUsageCount(1);
2462
            pstmt.setString(1, docid);
2463
            pstmt.execute();
2464
            pstmt.close();
2465 396 jones
2466 2249 jones
            // Delete it from xml_documents table
2467
            pstmt = conn.prepareStatement(
2468
                    "DELETE FROM xml_documents WHERE docid = ?");
2469
            pstmt.setString(1, docid);
2470
            pstmt.execute();
2471
            pstmt.close();
2472
            //Usaga count increase 1
2473
            conn.increaseUsageCount(1);
2474 2092 tao
2475 2249 jones
            conn.commit();
2476
            conn.setAutoCommit(true);
2477 2420 sgarg
2478 2249 jones
        } catch (Exception e) {
2479
            MetaCatUtil.debugMessage("error in DocumentImpl.delete: "
2480
                    + e.getMessage(), 30);
2481
            throw e;
2482
        } finally {
2483 2092 tao
2484 2249 jones
            try {
2485
                // close preparedStatement
2486
                if (pstmt != null) {
2487
                    pstmt.close();
2488
                }
2489
            }
2490
            finally {
2491
                //check in DBonnection
2492
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2493
            }
2494
        }
2495 2298 tao
       // add force delete replcation document here.
2496
       ForceReplicationHandler frh = new ForceReplicationHandler(
2497
                        accnum, ForceReplicationHandler.DELETE, isXML, notifyServer);
2498 2249 jones
    }
2499 2245 sgarg
2500 2298 tao
    private static String getDocTypeFromDB(DBConnection conn, String docidWithoutRev)
2501
                                 throws SQLException
2502
    {
2503
      String type = null;
2504
      String sql = "SELECT DOCTYPE FROM xml_documents WHERE docid LIKE " + "'" +
2505
                    docidWithoutRev +"'";
2506
      Statement stmt = null;
2507
      stmt = conn.createStatement();
2508
      ResultSet result = stmt.executeQuery(sql);
2509
      boolean hasResult = result.next();
2510
      if (hasResult)
2511
      {
2512
        type = result.getString(1);
2513
      }
2514
      MetaCatUtil.debugMessage("The type of deleting docid " + docidWithoutRev +
2515
                               " is " + type, 2);
2516
      return type;
2517
    }
2518
2519 2249 jones
    /**
2520
     * Check for "WRITE" permission on @docid for @user and/or @groups
2521
     * from DB connection
2522
     */
2523
    private static boolean hasWritePermission(String user, String[] groups,
2524
            String docid) throws SQLException, Exception
2525
    {
2526
        // Check for WRITE permission on @docid for @user and/or @groups
2527
        PermissionController controller = new PermissionController(docid);
2528
        return controller.hasPermission(user, groups,
2529
                AccessControlInterface.WRITESTRING);
2530
    }
2531 2245 sgarg
2532 2249 jones
    /**
2533
     * Check for "READ" permission base on docid, user and group
2534
     *
2535
     * @param docid, the document
2536
     * @param user, user name
2537
     * @param groups, user's group
2538
     */
2539
    public static boolean hasReadPermission(String user, String[] groups,
2540
            String docId) throws SQLException, Exception
2541
    {
2542
        // Check for READ permission on @docid for @user and/or @groups
2543
        PermissionController controller = new PermissionController(docId);
2544
        return controller.hasPermission(user, groups,
2545
                AccessControlInterface.READSTRING);
2546
    }
2547 2092 tao
2548 2249 jones
    /**
2549
     * Check for "WRITE" permission on @docid for @user and/or @groups
2550
     * from DB connection
2551
     */
2552
    private static boolean hasAllPermission(String user, String[] groups,
2553
            String docid) throws SQLException, Exception
2554 1621 tao
    {
2555 2249 jones
        // Check for WRITE permission on @docid for @user and/or @groups
2556
        PermissionController controller = new PermissionController(docid);
2557
        return controller.hasPermission(user, groups,
2558
                AccessControlInterface.ALLSTRING);
2559 1621 tao
    }
2560 2249 jones
2561
    /**
2562
     * Set up the parser handlers for writing the document to the database
2563
     */
2564
    private static XMLReader initializeParser(DBConnection dbconn,
2565
            String action, String docid, String rev, String user,
2566
            String[] groups, String pub, int serverCode, Reader dtd,
2567
            String ruleBase, boolean needValidation) throws Exception
2568 1217 tao
    {
2569 2249 jones
        XMLReader parser = null;
2570
        try {
2571
            // handler
2572
            ContentHandler chandler;
2573
            EntityResolver eresolver;
2574
            DTDHandler dtdhandler;
2575
            // Get an instance of the parser
2576
            String parserName = MetaCatUtil.getOption("saxparser");
2577
            parser = XMLReaderFactory.createXMLReader(parserName);
2578
            if (ruleBase != null && ruleBase.equals(EML200)) {
2579
                MetaCatUtil.debugMessage("eml 2.0.0 parser", 20);
2580
                chandler = new Eml200SAXHandler(dbconn, action, docid, rev,
2581
                        user, groups, pub, serverCode);
2582
                parser.setContentHandler((ContentHandler) chandler);
2583
                parser.setErrorHandler((ErrorHandler) chandler);
2584
                parser.setProperty(DECLARATIONHANDLERPROPERTY, chandler);
2585
                parser.setProperty(LEXICALPROPERTY, chandler);
2586
                // turn on schema validation feature
2587
                parser.setFeature(VALIDATIONFEATURE, true);
2588
                parser.setFeature(NAMESPACEFEATURE, true);
2589
                //parser.setFeature(NAMESPACEPREFIXESFEATURE, true);
2590
                parser.setFeature(SCHEMAVALIDATIONFEATURE, true);
2591
                // From DB to find the register external schema location
2592
                String externalSchemaLocation = null;
2593
                SchemaLocationResolver resolver = new SchemaLocationResolver();
2594
                externalSchemaLocation = resolver
2595
                        .getNameSpaceAndLocationString();
2596
                // Set external schemalocation.
2597
                if (externalSchemaLocation != null
2598
                        && !(externalSchemaLocation.trim()).equals("")) {
2599
                    parser.setProperty(EXTERNALSCHEMALOCATIONPROPERTY,
2600
                            externalSchemaLocation);
2601
                }
2602
            } else if (ruleBase != null && ruleBase.equals(EML210)) {
2603
                MetaCatUtil.debugMessage("eml 2.1.0 parser", 20);
2604
                chandler = new Eml210SAXHandler(dbconn, action, docid, rev,
2605
                        user, groups, pub, serverCode);
2606
                parser.setContentHandler((ContentHandler) chandler);
2607
                parser.setErrorHandler((ErrorHandler) chandler);
2608
                parser.setProperty(DECLARATIONHANDLERPROPERTY, chandler);
2609
                parser.setProperty(LEXICALPROPERTY, chandler);
2610
                // turn on schema validation feature
2611
                parser.setFeature(VALIDATIONFEATURE, true);
2612
                parser.setFeature(NAMESPACEFEATURE, true);
2613
                //parser.setFeature(NAMESPACEPREFIXESFEATURE, true);
2614
                parser.setFeature(SCHEMAVALIDATIONFEATURE, true);
2615
                // From DB to find the register external schema location
2616
                String externalSchemaLocation = null;
2617
                SchemaLocationResolver resolver = new SchemaLocationResolver();
2618
                externalSchemaLocation = resolver
2619
                        .getNameSpaceAndLocationString();
2620
                // Set external schemalocation.
2621
                if (externalSchemaLocation != null
2622
                        && !(externalSchemaLocation.trim()).equals("")) {
2623
                    parser.setProperty(EXTERNALSCHEMALOCATIONPROPERTY,
2624
                            externalSchemaLocation);
2625
                }
2626
            } else {
2627
                //create a DBSAXHandler object which has the revision
2628
                // specification
2629
                chandler = new DBSAXHandler(dbconn, action, docid, rev, user,
2630
                        groups, pub, serverCode);
2631
                parser.setContentHandler((ContentHandler) chandler);
2632
                parser.setErrorHandler((ErrorHandler) chandler);
2633
                parser.setProperty(DECLARATIONHANDLERPROPERTY, chandler);
2634
                parser.setProperty(LEXICALPROPERTY, chandler);
2635 2092 tao
2636 2249 jones
                if (ruleBase != null && ruleBase.equals(SCHEMA)
2637
                        && needValidation) {
2638
                    MetaCatUtil.debugMessage("General schema parser", 20);
2639
                    // turn on schema validation feature
2640
                    parser.setFeature(VALIDATIONFEATURE, true);
2641
                    parser.setFeature(NAMESPACEFEATURE, true);
2642
                    //parser.setFeature(NAMESPACEPREFIXESFEATURE, true);
2643
                    parser.setFeature(SCHEMAVALIDATIONFEATURE, true);
2644
                    // From DB to find the register external schema location
2645
                    String externalSchemaLocation = null;
2646 2253 sgarg
                    SchemaLocationResolver resolver =
2647 2249 jones
                        new SchemaLocationResolver();
2648
                    externalSchemaLocation = resolver
2649
                            .getNameSpaceAndLocationString();
2650
                    // Set external schemalocation.
2651
                    if (externalSchemaLocation != null
2652
                            && !(externalSchemaLocation.trim()).equals("")) {
2653
                        parser.setProperty(EXTERNALSCHEMALOCATIONPROPERTY,
2654
                                externalSchemaLocation);
2655
                    }
2656
2657
                } else if (ruleBase != null && ruleBase.equals(DTD)
2658
                        && needValidation) {
2659
                    MetaCatUtil.debugMessage("dtd parser", 20);
2660
                    // turn on dtd validaton feature
2661
                    parser.setFeature(VALIDATIONFEATURE, true);
2662
                    eresolver = new DBEntityResolver(dbconn,
2663
                            (DBSAXHandler) chandler, dtd);
2664
                    dtdhandler = new DBDTDHandler(dbconn);
2665
                    parser.setEntityResolver((EntityResolver) eresolver);
2666
                    parser.setDTDHandler((DTDHandler) dtdhandler);
2667
                } else {
2668
                    MetaCatUtil.debugMessage("other parser", 20);
2669
                    // non validation
2670
                    parser.setFeature(VALIDATIONFEATURE, false);
2671
                    eresolver = new DBEntityResolver(dbconn,
2672
                            (DBSAXHandler) chandler, dtd);
2673
                    dtdhandler = new DBDTDHandler(dbconn);
2674
                    parser.setEntityResolver((EntityResolver) eresolver);
2675
                    parser.setDTDHandler((DTDHandler) dtdhandler);
2676
                }
2677
            }//else
2678
        } catch (Exception e) {
2679
            throw e;
2680 2246 sgarg
        }
2681 2249 jones
        return parser;
2682
    }
2683 2092 tao
2684 2249 jones
    /**
2685
     * Save a document entry in the xml_revisions table Connection use as a
2686
     * paramter is in order to rollback feature
2687
     */
2688
    private static void archiveDocRevision(DBConnection dbconn, String docid,
2689
            String user)
2690
    {
2691
        String sysdate = dbAdapter.getDateTimeFunction();
2692
        //DBConnection conn = null;
2693
        //int serialNumber = -1;
2694
        PreparedStatement pstmt = null;
2695 638 bojilova
2696 2249 jones
        // create a record in xml_revisions table
2697
        // for that document as selected from xml_documents
2698 425 bojilova
2699 2249 jones
        try {
2700
            //check out DBConnection
2701
            /*
2702
             * conn=DBConnectionPool.
2703
             * getDBConnection("DocumentImpl.archiveDocRevision");
2704
             * serialNumber=conn.getCheckOutSerialNumber();
2705
             */
2706
            pstmt = dbconn.prepareStatement("INSERT INTO xml_revisions "
2707
                    + "(docid, rootnodeid, docname, doctype, "
2708
                    + "user_owner, user_updated, date_created, date_updated, "
2709
                    + "server_location, rev, public_access, catalog_id) "
2710
                    + "SELECT ?, rootnodeid, docname, doctype, "
2711
                    + "user_owner, ?, " + sysdate + ", " + sysdate + ", "
2712
                    + "server_location, rev, public_access, catalog_id "
2713
                    + "FROM xml_documents " + "WHERE docid = ?");
2714
            // Increase dbconnection usage count
2715
            dbconn.increaseUsageCount(1);
2716
            // Bind the values to the query and execute it
2717
            pstmt.setString(1, docid);
2718
            pstmt.setString(2, user);
2719
            pstmt.setString(3, docid);
2720
            pstmt.execute();
2721
            pstmt.close();
2722
        } catch (SQLException e) {
2723
            MetaCatUtil.debugMessage(
2724
                    "Error in DocumentImpl.archiveDocRevision : "
2725
                            + e.getMessage(), 30);
2726
        } finally {
2727
            try {
2728
                pstmt.close();
2729
            } catch (SQLException ee) {
2730
                MetaCatUtil.debugMessage(
2731
                        "Error in DocumnetImpl.archiveDocRevision: "
2732
                                + ee.getMessage(), 50);
2733
            }
2734
        }
2735
    }
2736 946 tao
2737 2249 jones
    /** Save a document entry in the xml_revisions table */
2738
    private static void archiveDocRevision(String docid, String user)
2739 1383 tao
    {
2740 2249 jones
        String sysdate = dbAdapter.getDateTimeFunction();
2741
        DBConnection conn = null;
2742
        int serialNumber = -1;
2743
        PreparedStatement pstmt = null;
2744 2092 tao
2745 2249 jones
        // create a record in xml_revisions table
2746
        // for that document as selected from xml_documents
2747 2092 tao
2748 2249 jones
        try {
2749
            //check out DBConnection
2750
            conn = DBConnectionPool
2751
                    .getDBConnection("DocumentImpl.archiveDocRevision");
2752
            serialNumber = conn.getCheckOutSerialNumber();
2753
            pstmt = conn.prepareStatement("INSERT INTO xml_revisions "
2754
                    + "(docid, rootnodeid, docname, doctype, "
2755
                    + "user_owner, user_updated, date_created, date_updated, "
2756
                    + "server_location, rev, public_access, catalog_id) "
2757
                    + "SELECT ?, rootnodeid, docname, doctype, "
2758
                    + "user_owner, ?, " + sysdate + ", " + sysdate + ", "
2759
                    + "server_location, rev, public_access, catalog_id "
2760
                    + "FROM xml_documents " + "WHERE docid = ?");
2761
            // Bind the values to the query and execute it
2762
            pstmt.setString(1, docid);
2763
            pstmt.setString(2, user);
2764
            pstmt.setString(3, docid);
2765
            pstmt.execute();
2766
            pstmt.close();
2767
        } catch (SQLException e) {
2768
            MetaCatUtil.debugMessage(
2769
                    "Error in DocumentImpl.archiveDocRevision : "
2770
                            + e.getMessage(), 30);
2771
        } finally {
2772
            try {
2773
                pstmt.close();
2774
            } catch (SQLException ee) {
2775
                MetaCatUtil.debugMessage(
2776
                        "Error in DocumnetImpl.archiveDocRevision: "
2777
                                + ee.getMessage(), 50);
2778
            } finally {
2779
                //check in DBConnection
2780
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2781
            }
2782 1407 tao
        }
2783 2092 tao
    }
2784 2249 jones
2785
    /**
2786
     * delete a entry in xml_table for given docid
2787 2253 sgarg
     *
2788 2249 jones
     * @param docId,
2789
     *            the id of the document need to be delete
2790
     */
2791
    private static void deleteXMLDocuments(String docId) throws SQLException
2792 1383 tao
    {
2793 2249 jones
        DBConnection conn = null;
2794
        int serialNumber = -1;
2795
        PreparedStatement pStmt = null;
2796
        try {
2797
            //check out DBConnection
2798
            conn = DBConnectionPool
2799
                    .getDBConnection("DocumentImpl.deleteXMLDocuments");
2800
            serialNumber = conn.getCheckOutSerialNumber();
2801
            //delete a record
2802
            pStmt = conn.prepareStatement(
2803
                    "DELETE FROM xml_documents WHERE docid = '" + docId + "'");
2804
            pStmt.execute();
2805
        } finally {
2806
            try {
2807
                pStmt.close();
2808
            } catch (SQLException e) {
2809
                MetaCatUtil.debugMessage(
2810
                        "error in DocumentImpl.deleteXMLDocuments: "
2811
                                + e.getMessage(), 50);
2812
            } finally {
2813
                //return back DBconnection
2814
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2815
            }
2816
        }
2817 1383 tao
    }
2818
2819 2249 jones
    /**
2820
     * Get last revision number from database for a docid If couldn't find an
2821
     * entry, -1 will return The return value is integer because we want compare
2822
     * it to there new one
2823 2253 sgarg
     *
2824 2249 jones
     * @param docid
2825
     *            <sitecode>. <uniqueid>part of Accession Number
2826
     */
2827
    public static int getLatestRevisionNumber(String docId) throws SQLException
2828 1217 tao
    {
2829 2249 jones
        int rev = 1;
2830
        PreparedStatement pStmt = null;
2831
        DBConnection dbConn = null;
2832
        int serialNumber = -1;
2833
        // get rid of rev
2834
        docId = MetaCatUtil.getDocIdFromString(docId);
2835
        try {
2836
            //check out DBConnection
2837
            dbConn = DBConnectionPool
2838
                    .getDBConnection("DocumentImpl.getLatestRevisionNumber");
2839
            serialNumber = dbConn.getCheckOutSerialNumber();
2840 459 bojilova
2841 2249 jones
            pStmt = dbConn
2842
                    .prepareStatement("SELECT rev FROM xml_documents WHERE docid='"
2843
                            + docId + "'");
2844
            pStmt.execute();
2845 2092 tao
2846 2249 jones
            ResultSet rs = pStmt.getResultSet();
2847
            boolean hasRow = rs.next();
2848
            if (hasRow) {
2849
                rev = rs.getInt(1);
2850
                pStmt.close();
2851
            } else {
2852
                rev = -1;
2853
                pStmt.close();
2854
            }
2855
        }//try
2856
        finally {
2857
            try {
2858
                pStmt.close();
2859
            } catch (Exception ee) {
2860
                MetaCatUtil.debugMessage("Error in DocumentImpl."
2861
                        + "getLatestRevisionNumber: " + ee.getMessage(), 50);
2862
            } finally {
2863
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2864
            }
2865
        }//finally
2866 2092 tao
2867 2249 jones
        return rev;
2868
    }//getLatestRevisionNumber
2869 2092 tao
2870 2249 jones
    /**
2871
     * Get server location form database for a accNum
2872 2253 sgarg
     *
2873 2249 jones
     * @param accum
2874
     *            <sitecode>. <uniqueid>. <rev>
2875
     */
2876
    private static int getServerLocationNumber(String accNum)
2877
            throws SQLException
2878 965 tao
    {
2879 2249 jones
        //get rid of revNum part
2880
        String docId = MetaCatUtil.getDocIdFromString(accNum);
2881
        PreparedStatement pStmt = null;
2882
        int serverLocation = 1;
2883
        DBConnection conn = null;
2884
        int serialNumber = -1;
2885 2092 tao
2886 2249 jones
        try {
2887
            //check out DBConnection
2888
            conn = DBConnectionPool
2889
                    .getDBConnection("DocumentImpl.getServerLocationNumber");
2890
            serialNumber = conn.getCheckOutSerialNumber();
2891 2092 tao
2892 2249 jones
            pStmt = conn
2893
                    .prepareStatement("SELECT server_location FROM xml_documents WHERE docid='"
2894
                            + docId + "'");
2895
            pStmt.execute();
2896 2092 tao
2897 2249 jones
            ResultSet rs = pStmt.getResultSet();
2898
            boolean hasRow = rs.next();
2899
            //if there is entry in xml_documents, get the serverlocation
2900
            if (hasRow) {
2901
                serverLocation = rs.getInt(1);
2902
                pStmt.close();
2903
            } else {
2904
                //if htere is no entry in xml_documents, we consider it is new
2905
                // document
2906
                //the server location is local host and value is 1
2907
                serverLocation = 1;
2908
                pStmt.close();
2909
            }
2910
        }//try
2911
        finally {
2912
            try {
2913
                pStmt.close();
2914
            }//try
2915
            catch (Exception ee) {
2916
                MetaCatUtil.debugMessage(
2917
                        "Error in DocumentImpl.getServerLocationNu(): "
2918
                                + ee.getMessage(), 50);
2919
            }//catch
2920
            finally {
2921
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2922
            }//finally
2923
        }//finally
2924 2092 tao
2925 2249 jones
        return serverLocation;
2926
    }
2927 1012 tao
2928 2249 jones
    /**
2929
     * Given a server name, return its servercode in xml_replication table. If
2930
     * no server is found, -1 will return
2931 2253 sgarg
     *
2932 2249 jones
     * @param serverName,
2933
     */
2934
    private static int getServerCode(String serverName)
2935 1012 tao
    {
2936 2249 jones
        PreparedStatement pStmt = null;
2937
        int serverLocation = -2;
2938
        DBConnection dbConn = null;
2939
        int serialNumber = -1;
2940
        //MetaCatUtil util = new MetaCatUtil();
2941 2092 tao
2942 2249 jones
        //we should consider about local host too
2943
        if (serverName.equals(MetaCatUtil.getLocalReplicationServerName())) {
2944
            serverLocation = 1;
2945
            return serverLocation;
2946
        }
2947 2092 tao
2948 2249 jones
        try {
2949
            //check xml_replication table
2950
            //dbConn=util.openDBConnection();
2951
            //check out DBConnection
2952
            dbConn = DBConnectionPool
2953
                    .getDBConnection("DocumentImpl.getServerCode");
2954
            serialNumber = dbConn.getCheckOutSerialNumber();
2955
            pStmt = dbConn
2956
                    .prepareStatement("SELECT serverid FROM xml_replication WHERE server='"
2957
                            + serverName + "'");
2958
            pStmt.execute();
2959 2092 tao
2960 2249 jones
            ResultSet rs = pStmt.getResultSet();
2961
            boolean hasRow = rs.next();
2962
            //if there is entry in xml_replication, get the serverid
2963
            if (hasRow) {
2964
                serverLocation = rs.getInt(1);
2965
                pStmt.close();
2966
            } else {
2967
                // if htere is no entry in xml_replication, -1 will return
2968
                serverLocation = -1;
2969
                pStmt.close();
2970
            }
2971
        } catch (Exception e) {
2972
            MetaCatUtil.debugMessage("Error in DocumentImpl.getServerCode(): "
2973
                    + e.getMessage(), 30);
2974
        } finally {
2975
            try {
2976
                pStmt.close();
2977
            } catch (Exception ee) {
2978
                MetaCatUtil.debugMessage(
2979
                        "Error in DocumentImpl.getServerCode(): "
2980
                                + ee.getMessage(), 50);
2981
            } finally {
2982
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2983
            }
2984
        }
2985 2092 tao
2986 2249 jones
        return serverLocation;
2987 1055 tao
    }
2988 2092 tao
2989 2249 jones
    /**
2990
     * Insert a server into xml_replcation table
2991 2253 sgarg
     *
2992 2249 jones
     * @param server,
2993
     *            the name of server
2994
     */
2995
    private static synchronized void insertServerIntoReplicationTable(
2996
            String server)
2997 1055 tao
    {
2998 2249 jones
        PreparedStatement pStmt = null;
2999
        DBConnection dbConn = null;
3000
        int serialNumber = -1;
3001 1055 tao
3002 2249 jones
        // Initial value for the server
3003
        int replicate = 0;
3004
        int dataReplicate = 0;
3005
        int hub = 0;
3006 2092 tao
3007 2249 jones
        try {
3008
            // Get DBConnection
3009
            dbConn = DBConnectionPool
3010
                    .getDBConnection("DocumentImpl.insertServIntoReplicationTable");
3011
            serialNumber = dbConn.getCheckOutSerialNumber();
3012 2092 tao
3013 2249 jones
            // Compare the server to dabase
3014
            pStmt = dbConn
3015
                    .prepareStatement("SELECT serverid FROM xml_replication WHERE server='"
3016
                            + server + "'");
3017
            pStmt.execute();
3018
            ResultSet rs = pStmt.getResultSet();
3019
            boolean hasRow = rs.next();
3020
            // Close preparedstatement and result set
3021
            pStmt.close();
3022
            rs.close();
3023 2092 tao
3024 2249 jones
            // If the server is not in the table, and server is not local host,
3025
            // insert it
3026
            if (!hasRow
3027
                    && !server.equals(MetaCatUtil
3028
                            .getLocalReplicationServerName())) {
3029
                // Set auto commit false
3030
                dbConn.setAutoCommit(false);
3031
                /*
3032
                 * pStmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
3033
                 * "(server, last_checked, replicate, datareplicate, hub) " +
3034
                 * "VALUES ('" + server + "', to_date(" + "'01/01/00',
3035
                 * 'MM/DD/YY'), '" + replicate +"', '"+dataReplicate+"','"+ hub +
3036
                 * "')");
3037
                 */
3038
                pStmt = dbConn
3039
                        .prepareStatement("INSERT INTO xml_replication "
3040
                                + "(server, last_checked, replicate, datareplicate, hub) "
3041
                                + "VALUES ('" + server + "', "
3042
                                + dbAdapter.toDate("01/01/1980", "MM/DD/YYYY")
3043
                                + ", '" + replicate + "', '" + dataReplicate
3044
                                + "','" + hub + "')");
3045 2092 tao
3046 2249 jones
                pStmt.execute();
3047
                dbConn.commit();
3048
                // Increase usage number
3049
                dbConn.increaseUsageCount(1);
3050
                pStmt.close();
3051 2092 tao
3052 2249 jones
            }
3053
        }//try
3054
        catch (Exception e) {
3055
            MetaCatUtil.debugMessage(
3056
                    "Error in DocumentImpl.insertServerIntoRepli(): "
3057
                            + e.getMessage(), 30);
3058
        }//catch
3059
        finally {
3060 2092 tao
3061 2249 jones
            try {
3062
                // Set auto commit true
3063
                dbConn.setAutoCommit(true);
3064
                pStmt.close();
3065 2092 tao
3066 2249 jones
            }//try
3067
            catch (Exception ee) {
3068
                MetaCatUtil.debugMessage(
3069
                        "Error in DocumentImpl.insetServerIntoRepl(): "
3070
                                + ee.getMessage(), 50);
3071
            }//catch
3072
            finally {
3073
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
3074
            }
3075 2092 tao
3076 2249 jones
        }//finally
3077 2092 tao
3078 2249 jones
    }
3079 2092 tao
3080 2249 jones
    /**
3081
     * the main routine used to test the DBWriter utility.
3082
     * <p>
3083
     * Usage: java DocumentImpl <-f filename -a action -d docid>
3084 2253 sgarg
     *
3085 2249 jones
     * @param filename
3086
     *            the filename to be loaded into the database
3087
     * @param action
3088
     *            the action to perform (READ, INSERT, UPDATE, DELETE)
3089
     * @param docid
3090
     *            the id of the document to process
3091
     */
3092
    static public void main(String[] args)
3093 1055 tao
    {
3094 2249 jones
        DBConnection dbconn = null;
3095
        int serialNumber = -1;
3096
        try {
3097
            String filename = null;
3098
            String dtdfilename = null;
3099
            String action = null;
3100
            String docid = null;
3101
            boolean showRuntime = false;
3102
            boolean useOldReadAlgorithm = false;
3103 2092 tao
3104 2249 jones
            // Parse the command line arguments
3105
            for (int i = 0; i < args.length; ++i) {
3106
                if (args[i].equals("-f")) {
3107
                    filename = args[++i];
3108
                } else if (args[i].equals("-r")) {
3109
                    dtdfilename = args[++i];
3110
                } else if (args[i].equals("-a")) {
3111
                    action = args[++i];
3112
                } else if (args[i].equals("-d")) {
3113
                    docid = args[++i];
3114
                } else if (args[i].equals("-t")) {
3115
                    showRuntime = true;
3116
                } else if (args[i].equals("-old")) {
3117
                    useOldReadAlgorithm = true;
3118
                } else {
3119
                    System.err.println("   args[" + i + "] '" + args[i]
3120
                            + "' ignored.");
3121
                }
3122
            }
3123 2092 tao
3124 2249 jones
            // Check if the required arguments are provided
3125
            boolean argsAreValid = false;
3126
            if (action != null) {
3127
                if (action.equals("INSERT")) {
3128
                    if (filename != null) {
3129
                        argsAreValid = true;
3130
                    }
3131
                } else if (action.equals("UPDATE")) {
3132
                    if ((filename != null) && (docid != null)) {
3133
                        argsAreValid = true;
3134
                    }
3135
                } else if (action.equals("DELETE")) {
3136
                    if (docid != null) {
3137
                        argsAreValid = true;
3138
                    }
3139
                } else if (action.equals("READ")) {
3140
                    if (docid != null) {
3141
                        argsAreValid = true;
3142
                    }
3143
                }
3144
            }
3145 2092 tao
3146 2249 jones
            // Print usage message if the arguments are not valid
3147
            if (!argsAreValid) {
3148
                System.err.println("Wrong number of arguments!!!");
3149
                System.err
3150
                        .println("USAGE: java DocumentImpl [-t] <-a INSERT> [-d docid] <-f filename> "
3151
                                + "[-r dtdfilename]");
3152
                System.err
3153
                        .println("   OR: java DocumentImpl [-t] <-a UPDATE -d docid -f filename> "
3154
                                + "[-r dtdfilename]");
3155
                System.err
3156
                        .println("   OR: java DocumentImpl [-t] <-a DELETE -d docid>");
3157
                System.err
3158
                        .println("   OR: java DocumentImpl [-t] [-old] <-a READ -d docid>");
3159
                return;
3160
            }
3161 1055 tao
3162 2249 jones
            // Time the request if asked for
3163
            double startTime = System.currentTimeMillis();
3164 2092 tao
3165 2249 jones
            // Open a connection to the database
3166
            MetaCatUtil util = new MetaCatUtil();
3167 2092 tao
3168 2249 jones
            dbconn = DBConnectionPool.getDBConnection("DocumentImpl.main");
3169
            serialNumber = dbconn.getCheckOutSerialNumber();
3170 407 jones
3171 2249 jones
            double connTime = System.currentTimeMillis();
3172
            // Execute the action requested (READ, INSERT, UPDATE, DELETE)
3173
            if (action.equals("READ")) {
3174
                DocumentImpl xmldoc = new DocumentImpl(docid);
3175
                if (useOldReadAlgorithm) {
3176
                    System.out.println(xmldoc.readUsingSlowAlgorithm());
3177
                } else {
3178
                    xmldoc.toXml(new PrintWriter(System.out), null, null, true);
3179
                }
3180
            } else if (action.equals("DELETE")) {
3181 2298 tao
                DocumentImpl.delete(docid, null, null,null);
3182 2249 jones
                System.out.println("Document deleted: " + docid);
3183
            } else {
3184
                /*
3185
                 * String newdocid = DocumentImpl.write(dbconn, filename, null,
3186
                 * dtdfilename, action, docid, null, null); if ((docid != null) &&
3187
                 * (!docid.equals(newdocid))) { if (action.equals("INSERT")) {
3188
                 * System.out.println("New document ID generated!!! "); } else
3189
                 * if (action.equals("UPDATE")) { System.out.println("ERROR:
3190
                 * Couldn't update document!!! "); } } else if ((docid == null) &&
3191
                 * (action.equals("UPDATE"))) { System.out.println("ERROR:
3192
                 * Couldn't update document!!! "); }
3193
                 * System.out.println("Document processing finished for: " +
3194
                 * filename + " (" + newdocid + ")");
3195
                 */
3196
            }
3197 2092 tao
3198 2249 jones
            double stopTime = System.currentTimeMillis();
3199
            double dbOpenTime = (connTime - startTime) / 1000;
3200
            double insertTime = (stopTime - connTime) / 1000;
3201
            double executionTime = (stopTime - startTime) / 1000;
3202
            if (showRuntime) {
3203
                System.out.println("\n\nTotal Execution time was: "
3204
                        + executionTime + " seconds.");
3205
                System.out.println("Time to open DB connection was: "
3206
                        + dbOpenTime + " seconds.");
3207
                System.out.println("Time to insert document was: " + insertTime
3208
                        + " seconds.");
3209
            }
3210
            dbconn.close();
3211
        } catch (McdbException me) {
3212
            me.toXml(new PrintWriter(System.err));
3213
        } catch (AccessionNumberException ane) {
3214
            System.out.println(ane.getMessage());
3215
        } catch (Exception e) {
3216
            System.err.println("EXCEPTION HANDLING REQUIRED");
3217
            System.err.println(e.getMessage());
3218
            e.printStackTrace(System.err);
3219
        } finally {
3220
            // Return db connection
3221
            DBConnectionPool.returnDBConnection(dbconn, serialNumber);
3222 2092 tao
        }
3223 407 jones
    }
3224 393 jones
}