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: leinfelder $'
10
 *     '$Date: 2011-11-02 20:40:12 -0700 (Wed, 02 Nov 2011) $'
11
 * '$Revision: 6595 $'
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.ResultSet;
31
import java.sql.Statement;
32
import java.util.Date;
33
import java.util.EmptyStackException;
34
import java.util.Enumeration;
35
import java.util.Hashtable;
36
import java.util.Stack;
37
import java.util.Vector;
38

    
39
import edu.ucsb.nceas.metacat.database.DBConnection;
40
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
41
import edu.ucsb.nceas.metacat.properties.PropertyService;
42
import edu.ucsb.nceas.metacat.service.XMLSchema;
43
import edu.ucsb.nceas.metacat.util.MetacatUtil;
44
import edu.ucsb.nceas.morpho.datapackage.Triple;
45
import edu.ucsb.nceas.morpho.datapackage.TripleCollection;
46
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
47
import edu.ucsb.nceas.utilities.StringUtil;
48

    
49
import org.apache.log4j.Logger;
50
import org.xml.sax.Attributes;
51
import org.xml.sax.SAXException;
52
import org.xml.sax.SAXParseException;
53
import org.xml.sax.ext.DeclHandler;
54
import org.xml.sax.ext.LexicalHandler;
55
import org.xml.sax.helpers.DefaultHandler;
56

    
57
/**
58
 * A database aware Class implementing callback bethods for the SAX parser to
59
 * call when processing the XML stream and generating events.
60
 */
61
public class DBSAXHandler extends DefaultHandler implements LexicalHandler,
62
        DeclHandler
63
{
64

    
65
    protected boolean atFirstElement;
66

    
67
    protected boolean processingDTD;
68

    
69
    protected String docname = null;
70

    
71
    protected String doctype;
72
    
73
    protected String catalogid = null;
74

    
75
    protected String systemid;
76

    
77
    private boolean stackCreated = false;
78

    
79
    protected Stack<DBSAXNode> nodeStack;
80

    
81
    protected Vector<DBSAXNode> nodeIndex;
82

    
83
    protected DBConnection connection = null;
84

    
85
    protected DocumentImpl currentDocument;
86
    
87
    protected Date createDate = null;
88
    
89
    protected Date updateDate = null;
90

    
91
    protected DBSAXNode rootNode;
92

    
93
    protected String action = null;
94

    
95
    protected String docid = null;
96

    
97
    protected String revision = null;
98

    
99
    protected String user = null;
100

    
101
    protected String[] groups = null;
102

    
103
    protected String pub = null;
104
    
105
	protected String encoding = null;
106

    
107
//    private boolean endDocument = false;
108

    
109
    protected int serverCode = 1;
110

    
111
    protected Hashtable<String,String> namespaces = new Hashtable<String,String>();
112

    
113
    protected boolean hitTextNode = false; // a flag to hit text node
114

    
115
    // a buffer to keep all text nodes for same element
116
    // it is for if element was split
117
    protected StringBuffer textBuffer = new StringBuffer();
118

    
119
//    protected Stack textBufferStack = new Stack();
120

    
121
    public static final int MAXDATACHARS = 4000;
122

    
123
    //protected static final int MAXDATACHARS = 50;
124

    
125
    // methods writeChildNodeToDB, setAttribute, setNamespace,
126
    // writeTextForDBSAXNode will increase endNodeId.
127
    protected long endNodeId = -1; // The end node id for a substree
128
    // DOCTITLE attr cleared from the db
129
    //   private static final int MAXTITLELEN = 1000;
130
    
131
    private boolean isRevisionDoc  = false;
132
    
133
    protected Vector<XMLSchema> schemaList = new Vector<XMLSchema>();
134

    
135
    //HandlerTriple stuff
136
    TripleCollection tripleList = new TripleCollection();
137

    
138
    Triple currentTriple = new Triple();
139

    
140
    boolean startParseTriple = false;
141

    
142
    boolean hasTriple = false;
143

    
144
    public static final String ECOGRID = "ecogrid://";
145

    
146
    private Logger logMetacat = Logger.getLogger(DBSAXHandler.class);
147

    
148
    /**
149
     * Construct an instance of the handler class
150
     *
151
     * @param conn the JDBC connection to which information is written
152
     */
153
    private DBSAXHandler(DBConnection conn, Date createDate, Date updateDate)
154
    {
155
        this.connection = conn;
156
        this.atFirstElement = true;
157
        this.processingDTD = false;
158
        this.createDate = createDate;
159
        this.updateDate = updateDate;
160

    
161
        // Create the stack for keeping track of node context
162
        // if it doesn't already exist
163
        if (!stackCreated) {
164
            nodeStack = new Stack<DBSAXNode>();
165
            nodeIndex = new Vector<DBSAXNode>();
166
            stackCreated = true;
167
        }
168
    }
169

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

    
226
    /** SAX Handler that receives notification of beginning of the document */
227
    public void startDocument() throws SAXException
228
    {
229
        logMetacat.debug("DBSaxHandler.startDocument - starting document");
230

    
231
        // Create the document node representation as root
232
        rootNode = new DBSAXNode(connection, this.docid);
233
        // Add the node to the stack, so that any text data can be
234
        // added as it is encountered
235
        nodeStack.push(rootNode);
236
    }
237

    
238
    /** SAX Handler that receives notification of end of the document */
239
	public void endDocument() throws SAXException {
240
		logMetacat.debug("DBSaxHandler.endDocument - ending document");
241
		// Starting new thread for writing XML Index.
242
		// It calls the run method of the thread.
243

    
244
		try {
245
			// if it is data package insert triple into relation table;
246
			if (doctype != null
247
					&& MetacatUtil.getOptionList(
248
							PropertyService.getProperty("xml.packagedoctype")).contains(
249
							doctype) && hasTriple && !isRevisionDoc) {
250

    
251
				// initial handler and write into relation db only for
252
				// xml-documents
253
				if (!isRevisionDoc) {
254
					RelationHandler handler = new RelationHandler(docid, doctype,
255
							connection, tripleList);
256
				}
257
			}
258
		} catch (Exception e) {
259
			logMetacat.error("DBSaxHandler.endDocument - Failed to write triples into relation table"
260
					+ e.getMessage());
261
			throw new SAXException("Failed to write triples into relation table "
262
					+ e.getMessage());
263
		}
264
		
265
		// If we get here, the document and schema parsed okay.  If there are
266
		// any schemas in the schema list, they are new and need to be registered.
267
    	for (XMLSchema xmlSchema : schemaList) {
268
    		String externalFileUri = xmlSchema.getExternalFileUri();
269
    		String fileNamespace = xmlSchema.getFileNamespace();
270
    		SchemaLocationResolver resolver = 
271
    			new SchemaLocationResolver(fileNamespace, externalFileUri);
272
    		resolver.resolveNameSpace();
273
    	}
274
	}
275

    
276
    /** SAX Handler that is called at the start of Namespace */
277
    public void startPrefixMapping(String prefix, String uri)
278
            throws SAXException
279
    {
280
        logMetacat.debug("DBSaxHandler.startPrefixMapping - Starting namespace");
281

    
282
        namespaces.put(prefix, uri);
283
    }
284

    
285
    /** SAX Handler that is called at the start of each XML element */
286
    public void startElement(String uri, String localName, String qName,
287
            Attributes atts) throws SAXException
288
    {
289
        // for element <eml:eml...> qname is "eml:eml", local name is "eml"
290
        // for element <acl....> both qname and local name is "eml"
291
        // uri is namespace
292
        logMetacat.debug("DBSaxHandler.startElement - Start ELEMENT(qName) " + qName);
293
        logMetacat.debug("DBSaxHandler.startElement - Start ELEMENT(localName) " + localName);
294
        logMetacat.debug("DBSaxHandler.startElement - Start ELEMENT(uri) " + uri);
295

    
296
        DBSAXNode parentNode = null;
297
        DBSAXNode currentNode = null;
298

    
299
        // Get a reference to the parent node for the id
300
        try {
301
            
302
            parentNode = (DBSAXNode) nodeStack.peek();
303
        } catch (EmptyStackException e) {
304
            parentNode = null;
305
        }
306

    
307
        // If hit a text node, we need write this text for current's parent
308
        // node This will happen if the element is mixed
309
        if (hitTextNode && parentNode != null) {
310
            // write the textbuffer into db for parent node.
311
            endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer, parentNode);
312
            // rest hitTextNode
313
            hitTextNode = false;
314
            // reset textbuffer
315
            textBuffer = null;
316
            textBuffer = new StringBuffer();
317
           
318
        }
319
        
320
        // Document representation that points to the root document node
321
        if (atFirstElement) {
322
            atFirstElement = false;
323
            // If no DOCTYPE declaration: docname = root element
324
            // doctype = root element name or name space
325
            if (docname == null) {
326
                docname = localName;
327
                // if uri isn't null doctype = uri(namespace)
328
                // otherwise root element
329
                if (uri != null && !(uri.trim()).equals("")) {
330
                    doctype = uri;
331
                } else {
332
                    doctype = docname;
333
                }
334
                logMetacat.debug("DBSaxHandler.startElement - DOCNAME-a: " + docname);
335
                logMetacat.debug("DBSaxHandler.startElement - DOCTYPE-a: " + doctype);
336
            } else if (doctype == null) {
337
                // because docname is not null and it is declared in dtd
338
                // so could not be in schema, no namespace
339
                doctype = docname;
340
                logMetacat.debug("DBSaxHandler.startElement - DOCTYPE-b: " + doctype);
341
            }
342
           
343
            rootNode.writeNodename(docname);
344
          
345
            try {
346
                // for validated XML Documents store a reference to XML DB
347
                // Catalog
348
                // Because this is select statement and it needn't to roll back
349
                // if
350
                // insert document action failed.
351
                // In order to decrease DBConnection usage count, we get a new
352
                // dbconnection from pool
353
               
354
                DBConnection dbConn = null;
355
                int serialNumber = -1;
356
               
357
                if (systemid != null) {
358
                    try {
359
                        // Get dbconnection
360
                        dbConn = DBConnectionPool
361
                                .getDBConnection("DBSAXHandler.startElement");
362
                        serialNumber = dbConn.getCheckOutSerialNumber();
363

    
364
                        Statement stmt = dbConn.createStatement();
365
                        ResultSet rs = stmt
366
                                .executeQuery("SELECT catalog_id FROM xml_catalog "
367
                                        + "WHERE entry_type = 'DTD' "
368
                                        + "AND public_id = '" + doctype + "'");
369
                        boolean hasRow = rs.next();
370
                        if (hasRow) {
371
                            catalogid = rs.getString(1);
372
                        }
373
                        stmt.close();
374
                    }//try
375
                    finally {
376
                        // Return dbconnection
377
                        DBConnectionPool.returnDBConnection(dbConn,
378
                                serialNumber);
379
                    }//finally
380
                }
381

    
382
                //create documentImpl object by the constructor which can
383
                // specify
384
                //the revision
385
              
386
                if (!isRevisionDoc)
387
                {
388
                  currentDocument = new DocumentImpl(connection, rootNode
389
                        .getNodeID(), docname, doctype, docid, revision,
390
                        action, user, this.pub, catalogid, this.serverCode, 
391
                        createDate, updateDate);
392
                }               
393
            } catch (Exception ane) {
394
                ane.printStackTrace(System.out);
395
                ane.printStackTrace(System.err);
396
                throw (new SAXException("Error in DBSaxHandler.startElement for action "
397
                        + action + " : " + ane.getMessage(), ane));
398
            }
399
        }
400

    
401
        // Create the current node representation
402
        currentNode = new DBSAXNode(connection, qName, localName,
403
                parentNode, rootNode.getNodeID(), docid, doctype);
404

    
405
        // Add all of the namespaces
406
        String prefix;
407
        String nsuri;
408
        Enumeration<String> prefixes = namespaces.keys();
409
        while (prefixes.hasMoreElements()) {
410
            prefix = (String) prefixes.nextElement();
411
            nsuri = (String) namespaces.get(prefix);
412
            currentNode.setNamespace(prefix, nsuri, docid);
413
        }
414
        namespaces = null;
415
        namespaces = new Hashtable<String,String>();
416

    
417
        // Add all of the attributes
418
        for (int i = 0; i < atts.getLength(); i++) {
419
            String attributeName = atts.getQName(i);
420
            String attributeValue = atts.getValue(i);
421
            endNodeId = currentNode.setAttribute(attributeName, attributeValue,
422
                    docid);
423

    
424
            // To handle name space and schema location if the attribute name
425
            // is xsi:schemaLocation. If the name space is in not in catalog 
426
            // table it will be registered.
427
            if (attributeName != null
428
                    && attributeName
429
                            .indexOf(MetaCatServlet.SCHEMALOCATIONKEYWORD) != -1) {
430
            	// These schemas will be registered in the end endDocument() method
431
            	// assuming parsing is successful.
432
        		// each namespace could have several schema locations.  parsedUri will
433
        		// hold a list of uri and files.
434
            	attributeValue = StringUtil.replaceTabsNewLines(attributeValue);
435
            	attributeValue = StringUtil.replaceDuplicateSpaces(attributeValue);
436
        		Vector<String> parsedUri = StringUtil.toVector(attributeValue, ' ');
437
        		for (int j = 0; j < parsedUri.size(); j = j + 2 ) {
438
        			if (j + 1 >= parsedUri.size()) {
439
        				throw new SAXException("Odd number of elements found when parsing schema location: " + 	
440
        						attributeValue + ". There should be an even number of uri/files in location.");
441
        			}
442
        			XMLSchema xmlSchema = 
443
        				new XMLSchema(parsedUri.get(j), parsedUri.get(j + 1));
444
        			schemaList.add(xmlSchema);
445
        		}
446
            }
447
        }
448

    
449
        // Add the node to the stack, so that any text data can be
450
		// added as it is encountered
451
		nodeStack.push(currentNode);
452
		// Add the node to the vector used by thread for writing XML Index
453
		nodeIndex.addElement(currentNode);
454
		// start parsing triple
455
		try {
456
			if (doctype != null
457
					&& MetacatUtil.getOptionList(
458
							PropertyService.getProperty("xml.packagedoctype")).contains(doctype)
459
					&& localName.equals("triple")) {
460
				startParseTriple = true;
461
				hasTriple = true;
462
				currentTriple = new Triple();
463
			}
464
		} catch (PropertyNotFoundException pnfe) {
465
			pnfe.printStackTrace(System.out);
466
			pnfe.printStackTrace(System.err);
467
			throw (new SAXException("Error in DBSaxHandler.startElement for action " + action +
468
			        " : " + pnfe.getMessage(), pnfe));
469
		}
470
	}               
471
    
472

    
473
    /** SAX Handler that is called for each XML text node */
474
    public void characters(char[] cbuf, int start, int len) throws SAXException
475
    {
476
        logMetacat.debug("DBSaxHandler.characters - starting characters");
477
        // buffer all text nodes for same element. This is for if text was split
478
        // into different nodes
479
        textBuffer.append(new String(cbuf, start, len));
480
        // set hittextnode true
481
        hitTextNode = true;
482
        // if text buffer .size is greater than max, write it to db.
483
        // so we can save memory
484
        if (textBuffer.length() > MAXDATACHARS) {
485
            logMetacat.debug("DBSaxHandler.characters - Write text into DB in charaters"
486
                    + " when text buffer size is greater than maxmum number");
487
            DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
488
            endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer,
489
                    currentNode);
490
            textBuffer = null;
491
            textBuffer = new StringBuffer();
492
        }
493
    }
494

    
495
    /**
496
     * SAX Handler that is called for each XML text node that is Ignorable
497
     * white space
498
     */
499
    public void ignorableWhitespace(char[] cbuf, int start, int len)
500
            throws SAXException
501
    {
502
        // When validation is turned "on", white spaces are reported here
503
        // When validation is turned "off" white spaces are not reported here,
504
        // but through characters() callback
505
        logMetacat.debug("DBSaxHandler.ignorableWhitespace - in ignorableWhitespace");
506

    
507
        DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
508

    
509
            // Write the content of the node to the database
510
            endNodeId = currentNode.writeChildNodeToDB("TEXT", null, new String(cbuf, start, len),
511
                    docid);
512
    }
513

    
514
    /**
515
     * SAX Handler called once for each processing instruction found: node that
516
     * PI may occur before or after the root element.
517
     */
518
    public void processingInstruction(String target, String data)
519
            throws SAXException
520
    {
521
        logMetacat.debug("DBSaxHandler.processingInstruction - in processing instructions");
522
        DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
523
        endNodeId = currentNode.writeChildNodeToDB("PI", target, data, docid);
524
    }
525

    
526
    /** SAX Handler that is called at the end of each XML element */
527
    public void endElement(String uri, String localName, String qName)
528
            throws SAXException
529
    {
530
        logMetacat.debug("DBSaxHandler.endElement - End element " + qName);
531

    
532
        // write buffered text nodes into db (so no splited)
533
        DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
534

    
535
        // If before the end element, the parser hit text nodes and store them
536
        // into the buffer, write the buffer to data base. The reason we put
537
        // write database here is for xerces some time split text node
538
        if (hitTextNode) {
539
            logMetacat.debug("DBSaxHandler.endElement - Write text into DB in End Element");
540
            endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer,
541
                    currentNode);
542

    
543
            //if it is triple parsing process
544
            if (startParseTriple) {
545

    
546
                String content = textBuffer.toString().trim();
547
                if (localName.equals("subject")) { //get the subject content
548
                    currentTriple.setSubject(content);
549
                } else if (localName.equals("relationship")) { //get the
550
                                                               // relationship
551
                                                               // content
552
                    currentTriple.setRelationship(content);
553
                } else if (localName.equals("object")) { //get the object
554
                                                         // content
555
                    currentTriple.setObject(content);
556
                }
557
            }
558

    
559
        }//if
560

    
561
        //set hitText false
562
        hitTextNode = false;
563
        // reset textbuff
564
        textBuffer = null;
565
        textBuffer = new StringBuffer();
566

    
567
        // Get the node from the stack
568
        currentNode = (DBSAXNode) nodeStack.pop();
569
        //finishing parsing single triple
570
        if (startParseTriple && localName.equals("triple")) {
571
            // add trip to triple collection
572
            tripleList.addTriple(currentTriple);
573
            //rest variable
574
            currentTriple = null;
575
            startParseTriple = false;
576
        }
577
    }
578

    
579
    //
580
    // the next section implements the LexicalHandler interface
581
    //
582

    
583
    /** SAX Handler that receives notification of DOCTYPE. Sets the DTD */
584
    public void startDTD(String name, String publicId, String systemId)
585
            throws SAXException
586
    {
587
        docname = name;
588
        doctype = publicId;
589
        systemid = systemId;
590

    
591
        processingDTD = true;
592
        DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
593
        //create a DTD node and write docname,publicid and system id into db
594
        // we don't put the dtd node into node stack
595
        DBSAXNode dtdNode = new DBSAXNode(connection, name, publicId, systemId,
596
                currentNode, currentNode.getRootNodeID(), docid);
597
        logMetacat.debug("DBSaxHandler.startDTD - Start DTD");
598
        logMetacat.debug("DBSaxHandler.startDTD - Setting processingDTD to true");
599
        logMetacat.debug("DBSaxHandler.startDTD - DOCNAME: " + docname);
600
        logMetacat.debug("DBSaxHandler.startDTD - DOCTYPE: " + doctype);
601
        logMetacat.debug("DBSaxHandler.startDTD - SYSID: " + systemid);
602
    }
603

    
604
    /**
605
     * SAX Handler that receives notification of end of DTD
606
     */
607
    public void endDTD() throws SAXException
608
    {
609

    
610
        processingDTD = false;
611
        logMetacat.debug("DBSaxHandler.endDTD - Setting processingDTD to false");
612
        logMetacat.debug("DBSaxHandler.endDTD - end DTD");
613
    }
614

    
615
    /**
616
     * SAX Handler that receives notification of comments in the DTD
617
     */
618
    public void comment(char[] ch, int start, int length) throws SAXException
619
    {
620
        logMetacat.debug("DBSaxHandler.comment - starting comment");
621
        if (!processingDTD) {
622
            DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
623
            endNodeId = currentNode.writeChildNodeToDB("COMMENT", null,
624
                    new String(ch, start, length), docid);
625
        }
626
    }
627

    
628
    /**
629
     * SAX Handler that receives notification of the start of CDATA sections
630
     */
631
    public void startCDATA() throws SAXException
632
    {
633
        logMetacat.debug("DBSaxHandler.startCDATA - starting CDATA");
634
    }
635

    
636
    /**
637
     * SAX Handler that receives notification of the end of CDATA sections
638
     */
639
    public void endCDATA() throws SAXException
640
    {
641
        logMetacat.debug("DBSaxHandler.endCDATA - end CDATA");
642
    }
643

    
644
    /**
645
     * SAX Handler that receives notification of the start of entities
646
     */
647
    public void startEntity(String name) throws SAXException
648
    {
649
        logMetacat.debug("DBSaxHandler.startEntity - starting entity: " + name);
650
        //System.out.println("start ENTITY: " + name);
651
        if (name.equals("[dtd]")) {
652
            processingDTD = true;
653
        }
654
    }
655

    
656
    /**
657
     * SAX Handler that receives notification of the end of entities
658
     */
659
    public void endEntity(String name) throws SAXException
660
    {
661
        logMetacat.debug("DBSaxHandler.endEntity - ending entity: " + name);
662
        //System.out.println("end ENTITY: " + name);
663
        if (name.equals("[dtd]")) {
664
            processingDTD = false;
665
        }
666
    }
667

    
668
    /**
669
     * SAX Handler that receives notification of element declarations
670
     */
671
    public void elementDecl(String name, String model)
672
            throws org.xml.sax.SAXException
673
    {
674
        //System.out.println("ELEMENTDECL: " + name + " " + model);
675
        logMetacat.debug("DBSaxHandler.elementDecl - element declaration: " + name + " " + model);
676
    }
677

    
678
    /**
679
     * SAX Handler that receives notification of attribute declarations
680
     */
681
    public void attributeDecl(String eName, String aName, String type,
682
            String valueDefault, String value) throws org.xml.sax.SAXException
683
    {
684

    
685
        //System.out.println("ATTRIBUTEDECL: " + eName + " "
686
        //                        + aName + " " + type + " " + valueDefault + " "
687
        //                        + value);
688
        logMetacat.debug("DBSaxHandler.attributeDecl - attribute declaration: " + eName + " " + aName + " "
689
                + type + " " + valueDefault + " " + value);
690
    }
691

    
692
    /**
693
     * SAX Handler that receives notification of internal entity declarations
694
     */
695
    public void internalEntityDecl(String name, String value)
696
            throws org.xml.sax.SAXException
697
    {
698
        //System.out.println("INTERNENTITYDECL: " + name + " " + value);
699
        logMetacat.debug("DBSaxHandler.internalEntityDecl - internal entity declaration: " + name + " " + value);
700
    }
701

    
702
    /**
703
     * SAX Handler that receives notification of external entity declarations
704
     */
705
    public void externalEntityDecl(String name, String publicId, String systemId)
706
            throws org.xml.sax.SAXException
707
    {
708
        //System.out.println("EXTERNENTITYDECL: " + name + " " + publicId
709
        //                              + " " + systemId);
710
        logMetacat.debug("DBSaxHandler.externalEntityDecl - external entity declaration: " + name + " " + publicId
711
                + " " + systemId);
712
        // it processes other external entity, not the DTD;
713
        // it doesn't signal for the DTD here
714
        processingDTD = false;
715
    }
716

    
717
    //
718
    // the next section implements the ErrorHandler interface
719
    //
720

    
721
    /**
722
     * SAX Handler that receives notification of fatal parsing errors
723
     */
724
    public void fatalError(SAXParseException exception) throws SAXException
725
    {
726
        logMetacat.fatal("DBSaxHandler.fatalError - " + exception.getMessage());
727
        throw (new SAXException("Fatal processing error.", exception));
728
    }
729

    
730
    /**
731
     * SAX Handler that receives notification of recoverable parsing errors
732
     */
733
    public void error(SAXParseException exception) throws SAXException
734
    {
735
        logMetacat.error("DBSaxHandler.error - " + exception.getMessage());
736
        throw (new SAXException(exception.getMessage(), exception));
737
    }
738

    
739
    /**
740
     * SAX Handler that receives notification of warnings
741
     */
742
    public void warning(SAXParseException exception) throws SAXException
743
    {
744
        logMetacat.warn("DBSaxHandler.warning - " + exception.getMessage());
745
        throw (new SAXException(exception.getMessage(), exception));
746
    }
747

    
748
    //
749
    // Helper, getter and setter methods
750
    //
751

    
752
    /**
753
     * get the document name
754
     */
755
    public String getDocname()
756
    {
757
        return docname;
758
    }
759

    
760
    /**
761
     * get the document processing state
762
     */
763
    public boolean processingDTD()
764
    {
765
        return processingDTD;
766
    }
767
    
768
    
769
    /**
770
     * get the the is revision doc
771
     * @return
772
     */
773
    public boolean getIsRevisionDoc()
774
    {
775
        return isRevisionDoc;
776
    }
777
    
778
    /**
779
     * Set the the handler is for revisionDoc
780
     * @param isRevisionDoc
781
     */
782
    public void setIsRevisionDoc(boolean isRevisionDoc)
783
    {
784
       this.isRevisionDoc = isRevisionDoc;   
785
    }
786

    
787
    public String getEncoding() {
788
		return encoding;
789
	}
790

    
791
	public void setEncoding(String encoding) {
792
		this.encoding = encoding;
793
	}
794

    
795
	/* Method to write a text buffer for DBSAXNode */
796
    protected long writeTextForDBSAXNode(long previousEndNodeId,
797
            StringBuffer strBuffer, DBSAXNode node) throws SAXException
798
    {
799
        long nodeId = previousEndNodeId;
800
        // Check parameter
801
        if (strBuffer == null || node == null) { return nodeId; }
802
        boolean moredata = true;
803

    
804
        String normalizedData = strBuffer.toString();
805
        logMetacat.debug("DBSAXHandler.writeTextForDBSAXNode - Before normalize in write process: " + normalizedData);
806
        String afterNormalize = MetacatUtil.normalize(normalizedData);
807
        logMetacat.debug("DBSAXHandler.writeTextForDBSAXNode - After normalize in write process: " + afterNormalize);
808
        strBuffer = new StringBuffer(afterNormalize);;
809

    
810
        int bufferSize = strBuffer.length();
811
        int start = 0;
812

    
813
        // if there are some cotent in buffer, write it
814
        if (bufferSize > 0) {
815
            logMetacat.debug("DBSAXHandler.writeTextForDBSAXNode - Write text into DB");
816

    
817
                // Write the content of the node to the database
818
                nodeId = node.writeChildNodeToDB("TEXT", null, new String(strBuffer), docid);
819
        }//if
820
        return nodeId;
821
    }
822
    
823
    public long getRootNodeId()
824
    {
825
        return rootNode.getNodeID();
826
    }
827
    
828
    public String getDocumentType()
829
    {
830
        return doctype;
831
    }
832
    
833
    public String getDocumentName()
834
    {
835
        return docname;
836
    }
837
    
838
    public String getCatalogId()
839
    {
840
        return catalogid;
841
    }
842
}
(18-18/65)