Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that handles the SAX XML events as they
4
 *             are generated from XML documents
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Matt Jones, Jivka Bojilova
8
 *
9
 *   '$Author: jones $'
10
 *     '$Date: 2006-11-10 10:25:38 -0800 (Fri, 10 Nov 2006) $'
11
 * '$Revision: 3077 $'
12
 *
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
 */
27

    
28
package edu.ucsb.nceas.metacat;
29

    
30
import java.sql.PreparedStatement;
31
import java.sql.ResultSet;
32
import java.sql.SQLException;
33
import java.sql.Statement;
34
import java.util.EmptyStackException;
35
import java.util.Enumeration;
36
import java.util.Hashtable;
37
import java.util.Stack;
38
import java.util.Vector;
39

    
40
import edu.ucsb.nceas.morpho.datapackage.Triple;
41
import edu.ucsb.nceas.morpho.datapackage.TripleCollection;
42

    
43
import org.apache.log4j.Logger;
44
import org.xml.sax.Attributes;
45
import org.xml.sax.SAXException;
46
import org.xml.sax.SAXParseException;
47
import org.xml.sax.ext.DeclHandler;
48
import org.xml.sax.ext.LexicalHandler;
49
import org.xml.sax.helpers.DefaultHandler;
50

    
51
/**
52
 * A database aware Class implementing callback bethods for the SAX parser to
53
 * call when processing the XML stream and generating events.
54
 */
55
public class DBSAXHandler extends DefaultHandler implements LexicalHandler,
56
        DeclHandler
57
{
58

    
59
    protected boolean atFirstElement;
60

    
61
    protected boolean processingDTD;
62

    
63
    protected String docname = null;
64

    
65
    protected String doctype;
66
    
67
    protected String catalogid = null;
68

    
69
    protected String systemid;
70

    
71
    private boolean stackCreated = false;
72

    
73
    protected Stack nodeStack;
74

    
75
    protected Vector nodeIndex;
76

    
77
    protected DBConnection connection = null;
78

    
79
    protected DocumentImpl currentDocument;
80
    
81
    protected String createDate = null;
82
    
83
    protected String updateDate = null;
84

    
85
    protected DBSAXNode rootNode;
86

    
87
    protected String action = null;
88

    
89
    protected String docid = null;
90

    
91
    protected String revision = null;
92

    
93
    protected String user = null;
94

    
95
    protected String[] groups = null;
96

    
97
    protected String pub = null;
98

    
99
    private boolean endDocument = false;
100

    
101
    protected int serverCode = 1;
102

    
103
    protected Hashtable namespaces = new Hashtable();
104

    
105
    protected boolean hitTextNode = false; // a flag to hit text node
106

    
107
    // a buffer to keep all text nodes for same element
108
    // it is for element was splited
109
    protected StringBuffer textBuffer = new StringBuffer();
110

    
111
    protected Stack textBufferStack = new Stack();
112

    
113
    protected static final int MAXDATACHARS = 4000;
114

    
115
    //protected static final int MAXDATACHARS = 50;
116

    
117
    // methods writeChildNodeToDB, setAttribute, setNamespace,
118
    // writeTextForDBSAXNode will increase endNodeId.
119
    protected long endNodeId = -1; // The end node id for a substree
120
    // DOCTITLE attr cleared from the db
121
    //   private static final int MAXTITLELEN = 1000;
122
    
123
    private boolean isRevisionDoc  = false;
124

    
125
    //HandlerTriple stuff
126
    TripleCollection tripleList = new TripleCollection();
127

    
128
    Triple currentTriple = new Triple();
129

    
130
    boolean startParseTriple = false;
131

    
132
    boolean hasTriple = false;
133

    
134
    public static final String ECOGRID = "ecogrid://";
135

    
136
    private Logger logMetacat = Logger.getLogger(DBSAXHandler.class);
137

    
138
    /**
139
     * Construct an instance of the handler class
140
     *
141
     * @param conn the JDBC connection to which information is written
142
     */
143
    private DBSAXHandler(DBConnection conn, String createDate, String updateDate)
144
    {
145
        this.connection = conn;
146
        this.atFirstElement = true;
147
        this.processingDTD = false;
148
        this.createDate = createDate;
149
        this.updateDate = updateDate;
150

    
151
        // Create the stack for keeping track of node context
152
        // if it doesn't already exist
153
        if (!stackCreated) {
154
            nodeStack = new Stack();
155
            nodeIndex = new Vector();
156
            stackCreated = true;
157
        }
158
    }
159

    
160
    /**
161
     * Construct an instance of the handler class
162
     *
163
     * @param conn the JDBC connection to which information is written
164
     * @param action - "INSERT" or "UPDATE"
165
     * @param docid to be inserted or updated into JDBC connection
166
     * @param user the user connected to MetaCat servlet and owns the document
167
     * @param groups the groups to which user belongs
168
     * @param pub flag for public "read" access on document
169
     * @param serverCode the serverid from xml_replication on which this
170
     *            document resides.
171
     *
172
     */
173
/* TODO excise this constructor because not used anywhere in project
174
    public DBSAXHandler(DBConnection conn, String action, String docid,
175
            String user, String[] groups, String pub, int serverCode)
176
    {
177
        this(conn);
178
        this.action = action;
179
        this.docid = docid;
180
        this.user = user;
181
        this.groups = groups;
182
        this.pub = pub;
183
        this.serverCode = serverCode;
184
        this.xmlIndex = new Thread(this);
185
    }
186
*/
187
    /**
188
     * Construct an instance of the handler class In this constructor, user can
189
     * specify the version need to upadate
190
     *
191
     * @param conn the JDBC connection to which information is written
192
     * @param action - "INSERT" or "UPDATE"
193
     * @param docid to be inserted or updated into JDBC connection
194
     * @param revision, the user specified the revision need to be update
195
     * @param user the user connected to MetaCat servlet and owns the document
196
     * @param groups the groups to which user belongs
197
     * @param pub flag for public "read" access on document
198
     * @param serverCode the serverid from xml_replication on which this
199
     *            document resides.
200
     *
201
     */
202
    public DBSAXHandler(DBConnection conn, String action, String docid,
203
            String revision, String user, String[] groups, String pub,
204
            int serverCode, String createDate, String updateDate)
205
    {
206
        this(conn, createDate, updateDate);
207
        this.action = action;
208
        this.docid = docid;
209
        this.revision = revision;
210
        this.user = user;
211
        this.groups = groups;
212
        this.pub = pub;
213
        this.serverCode = serverCode;
214
    }
215

    
216
    /** SAX Handler that receives notification of beginning of the document */
217
    public void startDocument() throws SAXException
218
    {
219
        logMetacat.info("start Document");
220

    
221
        // Create the document node representation as root
222
        rootNode = new DBSAXNode(connection, this.docid);
223
        // Add the node to the stack, so that any text data can be
224
        // added as it is encountered
225
        nodeStack.push(rootNode);
226
    }
227

    
228
    /** SAX Handler that receives notification of end of the document */
229
    public void endDocument() throws SAXException
230
    {
231
        logMetacat.info("end Document");
232
        // Starting new thread for writing XML Index.
233
        // It calls the run method of the thread.
234

    
235
        //if it is data package insert triple into relationtion table;
236
        if (doctype != null
237
                && MetaCatUtil.getOptionList(
238
                        MetaCatUtil.getOption("packagedoctype")).contains(
239
                        doctype) && hasTriple && !isRevisionDoc) {
240
            try {
241
                //initial handler and write into relationdb only for xml-documents
242
                if (!isRevisionDoc)
243
                {
244
                  RelationHandler handler = new RelationHandler(docid, doctype,
245
                        connection, tripleList);
246
                }
247
            } catch (Exception e) {
248
                logMetacat.error(
249
                        "Failed to write triples into relation table"
250
                                + e.getMessage());
251
                throw new SAXException(
252
                        "Failed to write triples into relation table "
253
                                + e.getMessage());
254
            }
255
        }
256
    }
257

    
258
    /** SAX Handler that is called at the start of Namespace */
259
    public void startPrefixMapping(String prefix, String uri)
260
            throws SAXException
261
    {
262
        logMetacat.info("NAMESPACE");
263

    
264
        namespaces.put(prefix, uri);
265
    }
266

    
267
    /** SAX Handler that is called at the start of each XML element */
268
    public void startElement(String uri, String localName, String qName,
269
            Attributes atts) throws SAXException
270
    {
271
        // for element <eml:eml...> qname is "eml:eml", local name is "eml"
272
        // for element <acl....> both qname and local name is "eml"
273
        // uri is namesapce
274
        logMetacat.info("Start ELEMENT(qName) " + qName);
275
        logMetacat.info("Start ELEMENT(localName) " + localName);
276
        logMetacat.info("Start ELEMENT(uri) " + uri);
277

    
278
        DBSAXNode parentNode = null;
279
        DBSAXNode currentNode = null;
280

    
281
        // Get a reference to the parent node for the id
282
        try {
283
            
284
            parentNode = (DBSAXNode) nodeStack.peek();
285
        } catch (EmptyStackException e) {
286
            parentNode = null;
287
        }
288

    
289
        // If hit a text node, we need write this text for current's parent
290
        // node
291
        // This will happend if the element is mixted
292
        if (hitTextNode && parentNode != null) {
293
            // write the textbuffer into db for parent node.
294
            endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer, parentNode);
295
            // rest hitTextNode
296
            hitTextNode = false;
297
            // reset textbuffer
298
            textBuffer = null;
299
            textBuffer = new StringBuffer();
300
           
301
        }
302
        
303
        // Document representation that points to the root document node
304
        if (atFirstElement) {
305
            atFirstElement = false;
306
            // If no DOCTYPE declaration: docname = root element
307
            // doctype = root element name or name space
308
            if (docname == null) {
309
                docname = localName;
310
                // if uri isn't null doctype = uri(namespace)
311
                // othewise root element
312
                if (uri != null && !(uri.trim()).equals("")) {
313
                    doctype = uri;
314
                } else {
315
                    doctype = docname;
316
                }
317
                logMetacat.info("DOCNAME-a: " + docname);
318
                logMetacat.info("DOCTYPE-a: " + doctype);
319
            } else if (doctype == null) {
320
                // because docname is not null and it is declared in dtd
321
                // so could not be in schema, no namespace
322
                doctype = docname;
323
                logMetacat.info("DOCTYPE-b: " + doctype);
324
            }
325
           
326
            rootNode.writeNodename(docname);
327
          
328
            try {
329
                // for validated XML Documents store a reference to XML DB
330
                // Catalog
331
                // Because this is select statement and it needn't to roll back
332
                // if
333
                // insert document action fialed.
334
                // In order to decrease DBConnection usage count, we get a new
335
                // dbconnection from pool
336
               
337
                DBConnection dbConn = null;
338
                int serialNumber = -1;
339
               
340
                if (systemid != null) {
341
                    try {
342
                        // Get dbconnection
343
                        dbConn = DBConnectionPool
344
                                .getDBConnection("DBSAXHandler.startElement");
345
                        serialNumber = dbConn.getCheckOutSerialNumber();
346

    
347
                        Statement stmt = dbConn.createStatement();
348
                        ResultSet rs = stmt
349
                                .executeQuery("SELECT catalog_id FROM xml_catalog "
350
                                        + "WHERE entry_type = 'DTD' "
351
                                        + "AND public_id = '" + doctype + "'");
352
                        boolean hasRow = rs.next();
353
                        if (hasRow) {
354
                            catalogid = rs.getString(1);
355
                        }
356
                        stmt.close();
357
                    }//try
358
                    finally {
359
                        // Return dbconnection
360
                        DBConnectionPool.returnDBConnection(dbConn,
361
                                serialNumber);
362
                    }//finally
363
                }
364

    
365
                //create documentImpl object by the constructor which can
366
                // specify
367
                //the revision
368
              
369
                if (!isRevisionDoc)
370
                {
371
                  //System.out.println("here!!!!!!!!!!!3");
372
                  currentDocument = new DocumentImpl(connection, rootNode
373
                        .getNodeID(), docname, doctype, docid, revision,
374
                        action, user, this.pub, catalogid, this.serverCode, 
375
                        createDate, updateDate);
376
                  //System.out.println("here!!!!!!!!!!!4");
377
                }
378
               
379

    
380
            } catch (Exception ane) {
381
                ane.printStackTrace();
382
                throw (new SAXException("Error in DBSaxHandler.startElement "
383
                        + action, ane));
384
            }
385
        }
386

    
387
        // Create the current node representation
388
        currentNode = new DBSAXNode(connection, qName, localName,
389
                parentNode, rootNode.getNodeID(), docid, doctype);
390

    
391
        // Add all of the namespaces
392
        String prefix;
393
        String nsuri;
394
        Enumeration prefixes = namespaces.keys();
395
        while (prefixes.hasMoreElements()) {
396
            prefix = (String) prefixes.nextElement();
397
            nsuri = (String) namespaces.get(prefix);
398
            currentNode.setNamespace(prefix, nsuri, docid);
399
        }
400
        namespaces = null;
401
        namespaces = new Hashtable();
402

    
403
        // Add all of the attributes
404
        for (int i = 0; i < atts.getLength(); i++) {
405
            String attributeName = atts.getQName(i);
406
            String attributeValue = atts.getValue(i);
407
            endNodeId = currentNode.setAttribute(attributeName, attributeValue,
408
                    docid);
409

    
410
            // To handle name space and schema location if the attribute name
411
            // is
412
            // xsi:schemaLocation. If the name space is in not in catalog table
413
            // it will be regeistered.
414
            if (attributeName != null
415
                    && attributeName
416
                            .indexOf(MetaCatServlet.SCHEMALOCATIONKEYWORD) != -1) {
417
                SchemaLocationResolver resolver = new SchemaLocationResolver(
418
                        attributeValue);
419
                resolver.resolveNameSpace();
420

    
421
            }
422
        }
423

    
424
        // Add the node to the stack, so that any text data can be
425
        // added as it is encountered
426
        nodeStack.push(currentNode);
427
        // Add the node to the vector used by thread for writing XML Index
428
        nodeIndex.addElement(currentNode);
429
        // start parsing triple
430
        if (doctype != null
431
                && MetaCatUtil.getOptionList(
432
                        MetaCatUtil.getOption("packagedoctype")).contains(
433
                        doctype) && localName.equals("triple")) {
434
            startParseTriple = true;
435
            hasTriple = true;
436
            currentTriple = new Triple();
437
        }
438
    }    
439

    
440
    /** SAX Handler that is called for each XML text node */
441
    public void characters(char[] cbuf, int start, int len) throws SAXException
442
    {
443
        logMetacat.info("CHARACTERS");
444
        // buffer all text nodes for same element. This is for text was splited
445
        // into different nodes
446
        textBuffer.append(new String(cbuf, start, len));
447
        // set hittextnode true
448
        hitTextNode = true;
449
        // if text buffer .size is greater than max, write it to db.
450
        // so we can save memory
451
        if (textBuffer.length() > MAXDATACHARS) {
452
            logMetacat.info("Write text into DB in charaters"
453
                    + " when text buffer size is greater than maxmum number");
454
            DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
455
            endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer,
456
                    currentNode);
457
            textBuffer = null;
458
            textBuffer = new StringBuffer();
459
        }
460
    }
461

    
462
    /**
463
     * SAX Handler that is called for each XML text node that is Ignorable
464
     * white space
465
     */
466
    public void ignorableWhitespace(char[] cbuf, int start, int len)
467
            throws SAXException
468
    {
469
        // When validation is turned "on", white spaces are reported here
470
        // When validation is turned "off" white spaces are not reported here,
471
        // but through characters() callback
472
        logMetacat.info("IGNORABLEWHITESPACE");
473

    
474
        DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
475
        String data = null;
476
        int leftover = len;
477
        int offset = start;
478
        boolean moredata = true;
479

    
480
        // This loop deals with the case where there are more characters
481
        // than can fit in a single database text field (limit is
482
        // MAXDATACHARS). If the text to be inserted exceeds MAXDATACHARS,
483
        // write a series of nodes that are MAXDATACHARS long, and then the
484
        // final node contains the remainder
485
        while (moredata) {
486
            if (leftover > MAXDATACHARS) {
487
                data = new String(cbuf, offset, MAXDATACHARS);
488
                leftover -= MAXDATACHARS;
489
                offset += MAXDATACHARS;
490
            } else {
491
                data = new String(cbuf, offset, leftover);
492
                moredata = false;
493
            }
494

    
495
            // Write the content of the node to the database
496
            endNodeId = currentNode.writeChildNodeToDB("TEXT", null, data,
497
                    docid);
498
        }
499
    }
500

    
501
    /**
502
     * SAX Handler called once for each processing instruction found: node that
503
     * PI may occur before or after the root element.
504
     */
505
    public void processingInstruction(String target, String data)
506
            throws SAXException
507
    {
508
        logMetacat.info("PI");
509
        DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
510
        endNodeId = currentNode.writeChildNodeToDB("PI", target, data, docid);
511
    }
512

    
513
    /** SAX Handler that is called at the end of each XML element */
514
    public void endElement(String uri, String localName, String qName)
515
            throws SAXException
516
    {
517
        logMetacat.info("End ELEMENT " + qName);
518

    
519
        // write buffered text nodes into db (so no splited)
520
        DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
521

    
522
        // If before the end element, the parser hit text nodes and store them
523
        // into the buffer, write the buffer to data base. The reason we put
524
        // write database here is for xerces some time split text node
525
        if (hitTextNode) {
526
            logMetacat.info("Write text into DB in End Element");
527
            endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer,
528
                    currentNode);
529

    
530
            //if it is triple parsing process
531
            if (startParseTriple) {
532

    
533
                String content = textBuffer.toString().trim();
534
                if (localName.equals("subject")) { //get the subject content
535
                    currentTriple.setSubject(content);
536
                } else if (localName.equals("relationship")) { //get the
537
                                                               // relationship
538
                                                               // content
539
                    currentTriple.setRelationship(content);
540
                } else if (localName.equals("object")) { //get the object
541
                                                         // content
542
                    currentTriple.setObject(content);
543
                }
544
            }
545

    
546
        }//if
547

    
548
        //set hitText false
549
        hitTextNode = false;
550
        // reset textbuff
551
        textBuffer = null;
552
        textBuffer = new StringBuffer();
553

    
554
        // Get the node from the stack
555
        currentNode = (DBSAXNode) nodeStack.pop();
556
        //finishing parsing single triple
557
        if (startParseTriple && localName.equals("triple")) {
558
            // add trip to triple collection
559
            tripleList.addTriple(currentTriple);
560
            //rest variable
561
            currentTriple = null;
562
            startParseTriple = false;
563
        }
564
    }
565

    
566
    //
567
    // the next section implements the LexicalHandler interface
568
    //
569

    
570
    /** SAX Handler that receives notification of DOCTYPE. Sets the DTD */
571
    public void startDTD(String name, String publicId, String systemId)
572
            throws SAXException
573
    {
574
        docname = name;
575
        doctype = publicId;
576
        systemid = systemId;
577

    
578
        processingDTD = true;
579
        DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
580
        //create a DTD node and write docname,publicid and system id into db
581
        // we don't put the dtd node into node stack
582
        DBSAXNode dtdNode = new DBSAXNode(connection, name, publicId, systemId,
583
                currentNode, currentNode.getRootNodeID(), docid);
584
        logMetacat.info("Start DTD");
585
        logMetacat.info("Setting processingDTD to true");
586
        logMetacat.info("DOCNAME: " + docname);
587
        logMetacat.info("DOCTYPE: " + doctype);
588
        logMetacat.info("  SYSID: " + systemid);
589
    }
590

    
591
    /**
592
     * SAX Handler that receives notification of end of DTD
593
     */
594
    public void endDTD() throws SAXException
595
    {
596

    
597
        processingDTD = false;
598
        logMetacat.info("Setting processingDTD to false");
599
        logMetacat.info("end DTD");
600
    }
601

    
602
    /**
603
     * SAX Handler that receives notification of comments in the DTD
604
     */
605
    public void comment(char[] ch, int start, int length) throws SAXException
606
    {
607
        logMetacat.info("COMMENT");
608
        if (!processingDTD) {
609
            DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
610
            endNodeId = currentNode.writeChildNodeToDB("COMMENT", null,
611
                    new String(ch, start, length), docid);
612
        }
613
    }
614

    
615
    /**
616
     * SAX Handler that receives notification of the start of CDATA sections
617
     */
618
    public void startCDATA() throws SAXException
619
    {
620
        logMetacat.info("start CDATA");
621
    }
622

    
623
    /**
624
     * SAX Handler that receives notification of the end of CDATA sections
625
     */
626
    public void endCDATA() throws SAXException
627
    {
628
        logMetacat.info("end CDATA");
629
    }
630

    
631
    /**
632
     * SAX Handler that receives notification of the start of entities
633
     */
634
    public void startEntity(String name) throws SAXException
635
    {
636
        logMetacat.info("start ENTITY: " + name);
637
        //System.out.println("start ENTITY: " + name);
638
        if (name.equals("[dtd]")) {
639
            processingDTD = true;
640
        }
641
    }
642

    
643
    /**
644
     * SAX Handler that receives notification of the end of entities
645
     */
646
    public void endEntity(String name) throws SAXException
647
    {
648
        logMetacat.info("end ENTITY: " + name);
649
        //System.out.println("end ENTITY: " + name);
650
        if (name.equals("[dtd]")) {
651
            processingDTD = false;
652
        }
653
    }
654

    
655
    /**
656
     * SAX Handler that receives notification of element declarations
657
     */
658
    public void elementDecl(String name, String model)
659
            throws org.xml.sax.SAXException
660
    {
661
        //System.out.println("ELEMENTDECL: " + name + " " + model);
662
        logMetacat.info("ELEMENTDECL: " + name + " " + model);
663
    }
664

    
665
    /**
666
     * SAX Handler that receives notification of attribute declarations
667
     */
668
    public void attributeDecl(String eName, String aName, String type,
669
            String valueDefault, String value) throws org.xml.sax.SAXException
670
    {
671

    
672
        //System.out.println("ATTRIBUTEDECL: " + eName + " "
673
        //                        + aName + " " + type + " " + valueDefault + " "
674
        //                        + value);
675
        logMetacat.info("ATTRIBUTEDECL: " + eName + " " + aName + " "
676
                + type + " " + valueDefault + " " + value);
677
    }
678

    
679
    /**
680
     * SAX Handler that receives notification of internal entity declarations
681
     */
682
    public void internalEntityDecl(String name, String value)
683
            throws org.xml.sax.SAXException
684
    {
685
        //System.out.println("INTERNENTITYDECL: " + name + " " + value);
686
        logMetacat.info("INTERNENTITYDECL: " + name + " " + value);
687
    }
688

    
689
    /**
690
     * SAX Handler that receives notification of external entity declarations
691
     */
692
    public void externalEntityDecl(String name, String publicId, String systemId)
693
            throws org.xml.sax.SAXException
694
    {
695
        //System.out.println("EXTERNENTITYDECL: " + name + " " + publicId
696
        //                              + " " + systemId);
697
        logMetacat.info("EXTERNENTITYDECL: " + name + " " + publicId
698
                + " " + systemId);
699
        // it processes other external entity, not the DTD;
700
        // it doesn't signal for the DTD here
701
        processingDTD = false;
702
    }
703

    
704
    //
705
    // the next section implements the ErrorHandler interface
706
    //
707

    
708
    /**
709
     * SAX Handler that receives notification of fatal parsing errors
710
     */
711
    public void fatalError(SAXParseException exception) throws SAXException
712
    {
713
        logMetacat.fatal("FATALERROR: " + exception.getMessage());
714
        throw (new SAXException("Fatal processing error.", exception));
715
    }
716

    
717
    /**
718
     * SAX Handler that receives notification of recoverable parsing errors
719
     */
720
    public void error(SAXParseException exception) throws SAXException
721
    {
722
        logMetacat.error("ERROR: " + exception.getMessage());
723
        throw (new SAXException("Error in processing EML.", exception));
724
    }
725

    
726
    /**
727
     * SAX Handler that receives notification of warnings
728
     */
729
    public void warning(SAXParseException exception) throws SAXException
730
    {
731
        logMetacat.warn("WARNING: " + exception.getMessage());
732
        throw (new SAXException("Warning.", exception));
733
    }
734

    
735
    //
736
    // Helper, getter and setter methods
737
    //
738

    
739
    /**
740
     * get the document name
741
     */
742
    public String getDocname()
743
    {
744
        return docname;
745
    }
746

    
747
    /**
748
     * get the document processing state
749
     */
750
    public boolean processingDTD()
751
    {
752
        return processingDTD;
753
    }
754
    
755
    
756
    /**
757
     * get the the is revision doc
758
     * @return
759
     */
760
    public boolean getIsRevisionDoc()
761
    {
762
        return isRevisionDoc;
763
    }
764
    
765
    /**
766
     * Set the the handler is for revisionDoc
767
     * @param isRevisionDoc
768
     */
769
    public void setIsRevisionDoc(boolean isRevisionDoc)
770
    {
771
       this.isRevisionDoc = isRevisionDoc;   
772
    }
773

    
774
    /* Method to write a text buffer for DBSAXNode */
775
    protected long writeTextForDBSAXNode(long previousEndNodeId,
776
            StringBuffer strBuffer, DBSAXNode node) throws SAXException
777
    {
778
        long nodeId = previousEndNodeId;
779
        // Check parameter
780
        if (strBuffer == null || node == null) { return nodeId; }
781
        boolean moredata = true;
782
        String data = null;
783

    
784
        String normalizedData = strBuffer.toString();
785
        strBuffer = new StringBuffer(MetaCatUtil.normalize(normalizedData));
786

    
787
        int bufferSize = strBuffer.length();
788
        int start = 0;
789

    
790
        // if there are some cotent in buffer, write it
791
        if (bufferSize > 0) {
792
            logMetacat.info("Write text into DB");
793
            // This loop deals with the case where there are more characters
794
            // than can fit in a single database text field (limit is
795
            // MAXDATACHARS). If the text to be inserted exceeds MAXDATACHARS,
796
            // write a series of nodes that are MAXDATACHARS long, and then the
797
            // final node contains the remainder
798
            while (moredata) {
799
                bufferSize = strBuffer.length();
800
                if (bufferSize > MAXDATACHARS) {
801
                    data = strBuffer.substring(start, MAXDATACHARS);
802
                    // cut the stringbuffer part that already written into db
803
                    strBuffer = strBuffer.delete(start, MAXDATACHARS);
804
                } else {
805
                    data = strBuffer.substring(start, bufferSize);
806
                    moredata = false;
807
                }
808

    
809
                // Write the content of the node to the database
810
                nodeId = node.writeChildNodeToDB("TEXT", null, data, docid);
811
            }//while
812
        }//if
813
        return nodeId;
814
    }
815
    
816
    public long getRootNodeId()
817
    {
818
        return rootNode.getNodeID();
819
    }
820
    
821
    public String getDocumentType()
822
    {
823
        return doctype;
824
    }
825
    
826
    public String getDocumentName()
827
    {
828
        return docname;
829
    }
830
    
831
    public String getCatalogId()
832
    {
833
        return catalogid;
834
    }
835
}
(22-22/65)