Project

General

Profile

1 17 jones
/**
2 203 jones
 *  '$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 17 jones
 *
9 203 jones
 *   '$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 17 jones
 */
27
28 75 jones
package edu.ucsb.nceas.metacat;
29 51 jones
30 2076 jones
import java.sql.ResultSet;
31
import java.sql.Statement;
32
import java.util.EmptyStackException;
33
import java.util.Enumeration;
34
import java.util.Hashtable;
35
import java.util.Stack;
36
import java.util.Vector;
37
38 4080 daigle
import edu.ucsb.nceas.metacat.service.PropertyService;
39 4425 daigle
import edu.ucsb.nceas.metacat.service.XMLSchema;
40 4080 daigle
import edu.ucsb.nceas.metacat.util.MetaCatUtil;
41 1590 tao
import edu.ucsb.nceas.morpho.datapackage.Triple;
42
import edu.ucsb.nceas.morpho.datapackage.TripleCollection;
43 4080 daigle
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
44 4425 daigle
import edu.ucsb.nceas.utilities.StringUtil;
45 1590 tao
46 2663 sgarg
import org.apache.log4j.Logger;
47 185 jones
import org.xml.sax.Attributes;
48
import org.xml.sax.SAXException;
49 204 jones
import org.xml.sax.SAXParseException;
50 186 jones
import org.xml.sax.ext.DeclHandler;
51 185 jones
import org.xml.sax.ext.LexicalHandler;
52
import org.xml.sax.helpers.DefaultHandler;
53 17 jones
54 1359 tao
/**
55 31 jones
 * A database aware Class implementing callback bethods for the SAX parser to
56 2076 jones
 * call when processing the XML stream and generating events.
57 31 jones
 */
58 2076 jones
public class DBSAXHandler extends DefaultHandler implements LexicalHandler,
59 2730 sgarg
        DeclHandler
60 2076 jones
{
61 17 jones
62 2076 jones
    protected boolean atFirstElement;
63 17 jones
64 2076 jones
    protected boolean processingDTD;
65 220 jones
66 2076 jones
    protected String docname = null;
67 17 jones
68 2076 jones
    protected String doctype;
69 2620 tao
70
    protected String catalogid = null;
71 1359 tao
72 2076 jones
    protected String systemid;
73 1359 tao
74 2076 jones
    private boolean stackCreated = false;
75 1359 tao
76 4470 daigle
    protected Stack<DBSAXNode> nodeStack;
77 203 jones
78 4470 daigle
    protected Vector<DBSAXNode> nodeIndex;
79 72 bojilova
80 2076 jones
    protected DBConnection connection = null;
81
82
    protected DocumentImpl currentDocument;
83 2620 tao
84
    protected String createDate = null;
85
86
    protected String updateDate = null;
87 2076 jones
88
    protected DBSAXNode rootNode;
89
90
    protected String action = null;
91
92
    protected String docid = null;
93
94
    protected String revision = null;
95
96
    protected String user = null;
97
98
    protected String[] groups = null;
99
100
    protected String pub = null;
101
102 4470 daigle
//    private boolean endDocument = false;
103 2076 jones
104
    protected int serverCode = 1;
105
106 4470 daigle
    protected Hashtable<String,String> namespaces = new Hashtable<String,String>();
107 2076 jones
108
    protected boolean hitTextNode = false; // a flag to hit text node
109
110
    // a buffer to keep all text nodes for same element
111 4470 daigle
    // it is for if element was split
112 2076 jones
    protected StringBuffer textBuffer = new StringBuffer();
113
114 4470 daigle
//    protected Stack textBufferStack = new Stack();
115 2076 jones
116
    protected static final int MAXDATACHARS = 4000;
117
118
    //protected static final int MAXDATACHARS = 50;
119
120
    // methods writeChildNodeToDB, setAttribute, setNamespace,
121
    // writeTextForDBSAXNode will increase endNodeId.
122
    protected long endNodeId = -1; // The end node id for a substree
123
    // DOCTITLE attr cleared from the db
124
    //   private static final int MAXTITLELEN = 1000;
125 2590 tao
126
    private boolean isRevisionDoc  = false;
127 4425 daigle
128
    protected Vector<XMLSchema> schemaList = new Vector<XMLSchema>();
129 2076 jones
130
    //HandlerTriple stuff
131
    TripleCollection tripleList = new TripleCollection();
132
133
    Triple currentTriple = new Triple();
134
135
    boolean startParseTriple = false;
136
137
    boolean hasTriple = false;
138
139 2165 tao
    public static final String ECOGRID = "ecogrid://";
140
141 2663 sgarg
    private Logger logMetacat = Logger.getLogger(DBSAXHandler.class);
142
143 2076 jones
    /**
144
     * Construct an instance of the handler class
145 2165 tao
     *
146 2076 jones
     * @param conn the JDBC connection to which information is written
147
     */
148 2620 tao
    private DBSAXHandler(DBConnection conn, String createDate, String updateDate)
149 2076 jones
    {
150
        this.connection = conn;
151
        this.atFirstElement = true;
152
        this.processingDTD = false;
153 2620 tao
        this.createDate = createDate;
154
        this.updateDate = updateDate;
155 2076 jones
156
        // Create the stack for keeping track of node context
157
        // if it doesn't already exist
158
        if (!stackCreated) {
159 4470 daigle
            nodeStack = new Stack<DBSAXNode>();
160
            nodeIndex = new Vector<DBSAXNode>();
161 2076 jones
            stackCreated = true;
162 1590 tao
        }
163 2076 jones
    }
164
165
    /**
166
     * Construct an instance of the handler class
167 2165 tao
     *
168 2076 jones
     * @param conn the JDBC connection to which information is written
169
     * @param action - "INSERT" or "UPDATE"
170
     * @param docid to be inserted or updated into JDBC connection
171
     * @param user the user connected to MetaCat servlet and owns the document
172
     * @param groups the groups to which user belongs
173
     * @param pub flag for public "read" access on document
174
     * @param serverCode the serverid from xml_replication on which this
175
     *            document resides.
176 2165 tao
     *
177 2076 jones
     */
178 2165 tao
/* TODO excise this constructor because not used anywhere in project
179 2076 jones
    public DBSAXHandler(DBConnection conn, String action, String docid,
180
            String user, String[] groups, String pub, int serverCode)
181
    {
182
        this(conn);
183
        this.action = action;
184
        this.docid = docid;
185
        this.user = user;
186
        this.groups = groups;
187
        this.pub = pub;
188
        this.serverCode = serverCode;
189
        this.xmlIndex = new Thread(this);
190
    }
191
*/
192
    /**
193
     * Construct an instance of the handler class In this constructor, user can
194
     * specify the version need to upadate
195 2165 tao
     *
196 2076 jones
     * @param conn the JDBC connection to which information is written
197
     * @param action - "INSERT" or "UPDATE"
198
     * @param docid to be inserted or updated into JDBC connection
199
     * @param revision, the user specified the revision need to be update
200
     * @param user the user connected to MetaCat servlet and owns the document
201
     * @param groups the groups to which user belongs
202
     * @param pub flag for public "read" access on document
203
     * @param serverCode the serverid from xml_replication on which this
204
     *            document resides.
205 2165 tao
     *
206 2076 jones
     */
207
    public DBSAXHandler(DBConnection conn, String action, String docid,
208
            String revision, String user, String[] groups, String pub,
209 2620 tao
            int serverCode, String createDate, String updateDate)
210 2076 jones
    {
211 2620 tao
        this(conn, createDate, updateDate);
212 2076 jones
        this.action = action;
213
        this.docid = docid;
214
        this.revision = revision;
215
        this.user = user;
216
        this.groups = groups;
217
        this.pub = pub;
218
        this.serverCode = serverCode;
219
    }
220
221
    /** SAX Handler that receives notification of beginning of the document */
222
    public void startDocument() throws SAXException
223
    {
224 2663 sgarg
        logMetacat.info("start Document");
225 2076 jones
226
        // Create the document node representation as root
227
        rootNode = new DBSAXNode(connection, this.docid);
228
        // Add the node to the stack, so that any text data can be
229
        // added as it is encountered
230
        nodeStack.push(rootNode);
231
    }
232
233
    /** SAX Handler that receives notification of end of the document */
234 4080 daigle
	public void endDocument() throws SAXException {
235
		logMetacat.info("end Document");
236
		// Starting new thread for writing XML Index.
237
		// It calls the run method of the thread.
238 2076 jones
239 4080 daigle
		try {
240 4470 daigle
			// if it is data package insert triple into relation table;
241 4080 daigle
			if (doctype != null
242
					&& MetaCatUtil.getOptionList(
243 4213 daigle
							PropertyService.getProperty("xml.packagedoctype")).contains(
244 4080 daigle
							doctype) && hasTriple && !isRevisionDoc) {
245 72 bojilova
246 4470 daigle
				// initial handler and write into relation db only for
247 4080 daigle
				// xml-documents
248
				if (!isRevisionDoc) {
249
					RelationHandler handler = new RelationHandler(docid, doctype,
250
							connection, tripleList);
251
				}
252
			}
253
		} catch (Exception e) {
254
			logMetacat.error("Failed to write triples into relation table"
255
					+ e.getMessage());
256
			throw new SAXException("Failed to write triples into relation table "
257
					+ e.getMessage());
258
		}
259 4425 daigle
260
		// If we get here, the document and schema parsed okay.  If there are
261
		// any schemas in the schema list, they are new and need to be registered.
262
    	for (XMLSchema xmlSchema : schemaList) {
263
    		String externalFileUri = xmlSchema.getExternalFileUri();
264
    		String fileNamespace = xmlSchema.getFileNamespace();
265
    		SchemaLocationResolver resolver =
266
    			new SchemaLocationResolver(fileNamespace, externalFileUri);
267
    		resolver.resolveNameSpace();
268
    	}
269 4080 daigle
	}
270
271 2076 jones
    /** SAX Handler that is called at the start of Namespace */
272
    public void startPrefixMapping(String prefix, String uri)
273
            throws SAXException
274
    {
275 2663 sgarg
        logMetacat.info("NAMESPACE");
276 821 bojilova
277 2076 jones
        namespaces.put(prefix, uri);
278
    }
279 1359 tao
280 2076 jones
    /** SAX Handler that is called at the start of each XML element */
281
    public void startElement(String uri, String localName, String qName,
282
            Attributes atts) throws SAXException
283
    {
284
        // for element <eml:eml...> qname is "eml:eml", local name is "eml"
285
        // for element <acl....> both qname and local name is "eml"
286 4470 daigle
        // uri is namespace
287 2663 sgarg
        logMetacat.info("Start ELEMENT(qName) " + qName);
288
        logMetacat.info("Start ELEMENT(localName) " + localName);
289
        logMetacat.info("Start ELEMENT(uri) " + uri);
290 17 jones
291 2076 jones
        DBSAXNode parentNode = null;
292
        DBSAXNode currentNode = null;
293 18 jones
294 2076 jones
        // Get a reference to the parent node for the id
295
        try {
296 2605 tao
297 2076 jones
            parentNode = (DBSAXNode) nodeStack.peek();
298
        } catch (EmptyStackException e) {
299
            parentNode = null;
300
        }
301 1359 tao
302 2076 jones
        // If hit a text node, we need write this text for current's parent
303 4470 daigle
        // node This will happen if the element is mixed
304 2076 jones
        if (hitTextNode && parentNode != null) {
305
            // write the textbuffer into db for parent node.
306
            endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer, parentNode);
307
            // rest hitTextNode
308
            hitTextNode = false;
309
            // reset textbuffer
310
            textBuffer = null;
311
            textBuffer = new StringBuffer();
312 2605 tao
313 2076 jones
        }
314 2605 tao
315 2076 jones
        // Document representation that points to the root document node
316
        if (atFirstElement) {
317
            atFirstElement = false;
318
            // If no DOCTYPE declaration: docname = root element
319
            // doctype = root element name or name space
320
            if (docname == null) {
321
                docname = localName;
322
                // if uri isn't null doctype = uri(namespace)
323 4470 daigle
                // otherwise root element
324 2076 jones
                if (uri != null && !(uri.trim()).equals("")) {
325
                    doctype = uri;
326
                } else {
327
                    doctype = docname;
328
                }
329 2663 sgarg
                logMetacat.info("DOCNAME-a: " + docname);
330
                logMetacat.info("DOCTYPE-a: " + doctype);
331 2076 jones
            } else if (doctype == null) {
332
                // because docname is not null and it is declared in dtd
333
                // so could not be in schema, no namespace
334
                doctype = docname;
335 2663 sgarg
                logMetacat.info("DOCTYPE-b: " + doctype);
336 1217 tao
            }
337 2605 tao
338 2076 jones
            rootNode.writeNodename(docname);
339 2605 tao
340 2076 jones
            try {
341
                // for validated XML Documents store a reference to XML DB
342
                // Catalog
343
                // Because this is select statement and it needn't to roll back
344
                // if
345 4470 daigle
                // insert document action failed.
346 2076 jones
                // In order to decrease DBConnection usage count, we get a new
347
                // dbconnection from pool
348 2620 tao
349 2076 jones
                DBConnection dbConn = null;
350
                int serialNumber = -1;
351 2605 tao
352 2076 jones
                if (systemid != null) {
353
                    try {
354
                        // Get dbconnection
355
                        dbConn = DBConnectionPool
356
                                .getDBConnection("DBSAXHandler.startElement");
357
                        serialNumber = dbConn.getCheckOutSerialNumber();
358 1359 tao
359 2076 jones
                        Statement stmt = dbConn.createStatement();
360
                        ResultSet rs = stmt
361
                                .executeQuery("SELECT catalog_id FROM xml_catalog "
362
                                        + "WHERE entry_type = 'DTD' "
363
                                        + "AND public_id = '" + doctype + "'");
364
                        boolean hasRow = rs.next();
365
                        if (hasRow) {
366
                            catalogid = rs.getString(1);
367
                        }
368
                        stmt.close();
369
                    }//try
370
                    finally {
371
                        // Return dbconnection
372
                        DBConnectionPool.returnDBConnection(dbConn,
373
                                serialNumber);
374
                    }//finally
375
                }
376 1359 tao
377 2076 jones
                //create documentImpl object by the constructor which can
378
                // specify
379
                //the revision
380 2605 tao
381
                if (!isRevisionDoc)
382
                {
383
                  currentDocument = new DocumentImpl(connection, rootNode
384 2076 jones
                        .getNodeID(), docname, doctype, docid, revision,
385 2620 tao
                        action, user, this.pub, catalogid, this.serverCode,
386
                        createDate, updateDate);
387 3221 berkley
                }
388 2076 jones
            } catch (Exception ane) {
389 2605 tao
                ane.printStackTrace();
390 2076 jones
                throw (new SAXException("Error in DBSaxHandler.startElement "
391
                        + action, ane));
392
            }
393
        }
394 1359 tao
395 2076 jones
        // Create the current node representation
396 2627 tao
        currentNode = new DBSAXNode(connection, qName, localName,
397
                parentNode, rootNode.getNodeID(), docid, doctype);
398 821 bojilova
399 2076 jones
        // Add all of the namespaces
400
        String prefix;
401
        String nsuri;
402 4470 daigle
        Enumeration<String> prefixes = namespaces.keys();
403 2076 jones
        while (prefixes.hasMoreElements()) {
404
            prefix = (String) prefixes.nextElement();
405
            nsuri = (String) namespaces.get(prefix);
406
            currentNode.setNamespace(prefix, nsuri, docid);
407
        }
408
        namespaces = null;
409 4470 daigle
        namespaces = new Hashtable<String,String>();
410 17 jones
411 2076 jones
        // Add all of the attributes
412
        for (int i = 0; i < atts.getLength(); i++) {
413
            String attributeName = atts.getQName(i);
414
            String attributeValue = atts.getValue(i);
415
            endNodeId = currentNode.setAttribute(attributeName, attributeValue,
416
                    docid);
417 1359 tao
418 2076 jones
            // To handle name space and schema location if the attribute name
419 4425 daigle
            // is xsi:schemaLocation. If the name space is in not in catalog
420
            // table it will be registered.
421 2076 jones
            if (attributeName != null
422
                    && attributeName
423
                            .indexOf(MetaCatServlet.SCHEMALOCATIONKEYWORD) != -1) {
424 4425 daigle
            	// These schemas will be registered in the end endDocument() method
425
            	// assuming parsing is successful.
426
        		// each namespace could have several schema locations.  parsedUri will
427
        		// hold a list of uri and files.
428
            	attributeValue = StringUtil.replaceTabsNewLines(attributeValue);
429
            	attributeValue = StringUtil.replaceDuplicateSpaces(attributeValue);
430
        		Vector<String> parsedUri = StringUtil.toVector(attributeValue, ' ');
431
        		for (int j = 0; j < parsedUri.size(); j = j + 2 ) {
432
        			if (j + 1 >= parsedUri.size()) {
433
        				throw new SAXException("Odd number of elements found when parsing schema location: " +
434
        						attributeValue + ". There should be an even number of uri/files in location.");
435
        			}
436
        			XMLSchema xmlSchema =
437
        				new XMLSchema(parsedUri.get(j), parsedUri.get(j + 1));
438
        			schemaList.add(xmlSchema);
439
        		}
440 2076 jones
            }
441
        }
442
443
        // Add the node to the stack, so that any text data can be
444 4080 daigle
		// added as it is encountered
445
		nodeStack.push(currentNode);
446
		// Add the node to the vector used by thread for writing XML Index
447
		nodeIndex.addElement(currentNode);
448
		// start parsing triple
449
		try {
450
			if (doctype != null
451
					&& MetaCatUtil.getOptionList(
452 4213 daigle
							PropertyService.getProperty("xml.packagedoctype")).contains(doctype)
453 4080 daigle
					&& localName.equals("triple")) {
454
				startParseTriple = true;
455
				hasTriple = true;
456
				currentTriple = new Triple();
457
			}
458
		} catch (PropertyNotFoundException pnfe) {
459
			pnfe.printStackTrace();
460
			throw (new SAXException("Error in DBSaxHandler.startElement " + action, pnfe));
461
		}
462
	}
463
464 2076 jones
465
    /** SAX Handler that is called for each XML text node */
466
    public void characters(char[] cbuf, int start, int len) throws SAXException
467 1841 tao
    {
468 2663 sgarg
        logMetacat.info("CHARACTERS");
469 4470 daigle
        // buffer all text nodes for same element. This is for if text was split
470 2076 jones
        // into different nodes
471
        textBuffer.append(new String(cbuf, start, len));
472
        // set hittextnode true
473
        hitTextNode = true;
474
        // if text buffer .size is greater than max, write it to db.
475
        // so we can save memory
476
        if (textBuffer.length() > MAXDATACHARS) {
477 2663 sgarg
            logMetacat.info("Write text into DB in charaters"
478
                    + " when text buffer size is greater than maxmum number");
479 2076 jones
            DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
480
            endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer,
481
                    currentNode);
482
            textBuffer = null;
483
            textBuffer = new StringBuffer();
484 899 berkley
        }
485 2076 jones
    }
486
487
    /**
488
     * SAX Handler that is called for each XML text node that is Ignorable
489
     * white space
490
     */
491
    public void ignorableWhitespace(char[] cbuf, int start, int len)
492
            throws SAXException
493 1841 tao
    {
494 2076 jones
        // When validation is turned "on", white spaces are reported here
495
        // When validation is turned "off" white spaces are not reported here,
496
        // but through characters() callback
497 2663 sgarg
        logMetacat.info("IGNORABLEWHITESPACE");
498 2076 jones
499
        DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
500
        String data = null;
501
        int leftover = len;
502
        int offset = start;
503
        boolean moredata = true;
504
505
        // This loop deals with the case where there are more characters
506
        // than can fit in a single database text field (limit is
507
        // MAXDATACHARS). If the text to be inserted exceeds MAXDATACHARS,
508
        // write a series of nodes that are MAXDATACHARS long, and then the
509
        // final node contains the remainder
510
        while (moredata) {
511
            if (leftover > MAXDATACHARS) {
512
                data = new String(cbuf, offset, MAXDATACHARS);
513
                leftover -= MAXDATACHARS;
514
                offset += MAXDATACHARS;
515
            } else {
516
                data = new String(cbuf, offset, leftover);
517
                moredata = false;
518
            }
519
520
            // Write the content of the node to the database
521
            endNodeId = currentNode.writeChildNodeToDB("TEXT", null, data,
522
                    docid);
523
        }
524 1217 tao
    }
525 2076 jones
526
    /**
527
     * SAX Handler called once for each processing instruction found: node that
528
     * PI may occur before or after the root element.
529
     */
530
    public void processingInstruction(String target, String data)
531
            throws SAXException
532 1217 tao
    {
533 2663 sgarg
        logMetacat.info("PI");
534 2076 jones
        DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
535
        endNodeId = currentNode.writeChildNodeToDB("PI", target, data, docid);
536
    }
537 1359 tao
538 2076 jones
    /** SAX Handler that is called at the end of each XML element */
539
    public void endElement(String uri, String localName, String qName)
540
            throws SAXException
541
    {
542 2663 sgarg
        logMetacat.info("End ELEMENT " + qName);
543 660 bojilova
544 2076 jones
        // write buffered text nodes into db (so no splited)
545
        DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
546 1359 tao
547 2076 jones
        // If before the end element, the parser hit text nodes and store them
548
        // into the buffer, write the buffer to data base. The reason we put
549
        // write database here is for xerces some time split text node
550
        if (hitTextNode) {
551 2663 sgarg
            logMetacat.info("Write text into DB in End Element");
552 2076 jones
            endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer,
553
                    currentNode);
554 1359 tao
555 2076 jones
            //if it is triple parsing process
556
            if (startParseTriple) {
557 660 bojilova
558 2076 jones
                String content = textBuffer.toString().trim();
559
                if (localName.equals("subject")) { //get the subject content
560
                    currentTriple.setSubject(content);
561
                } else if (localName.equals("relationship")) { //get the
562
                                                               // relationship
563
                                                               // content
564
                    currentTriple.setRelationship(content);
565
                } else if (localName.equals("object")) { //get the object
566
                                                         // content
567
                    currentTriple.setObject(content);
568
                }
569
            }
570 17 jones
571 2076 jones
        }//if
572 72 bojilova
573 2076 jones
        //set hitText false
574
        hitTextNode = false;
575
        // reset textbuff
576
        textBuffer = null;
577
        textBuffer = new StringBuffer();
578 17 jones
579 2076 jones
        // Get the node from the stack
580
        currentNode = (DBSAXNode) nodeStack.pop();
581
        //finishing parsing single triple
582
        if (startParseTriple && localName.equals("triple")) {
583
            // add trip to triple collection
584
            tripleList.addTriple(currentTriple);
585
            //rest variable
586
            currentTriple = null;
587
            startParseTriple = false;
588
        }
589
    }
590 17 jones
591 2076 jones
    //
592
    // the next section implements the LexicalHandler interface
593
    //
594 185 jones
595 2076 jones
    /** SAX Handler that receives notification of DOCTYPE. Sets the DTD */
596
    public void startDTD(String name, String publicId, String systemId)
597
            throws SAXException
598
    {
599
        docname = name;
600
        doctype = publicId;
601
        systemid = systemId;
602 185 jones
603 2076 jones
        processingDTD = true;
604
        DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
605
        //create a DTD node and write docname,publicid and system id into db
606
        // we don't put the dtd node into node stack
607
        DBSAXNode dtdNode = new DBSAXNode(connection, name, publicId, systemId,
608
                currentNode, currentNode.getRootNodeID(), docid);
609 2663 sgarg
        logMetacat.info("Start DTD");
610
        logMetacat.info("Setting processingDTD to true");
611
        logMetacat.info("DOCNAME: " + docname);
612
        logMetacat.info("DOCTYPE: " + doctype);
613
        logMetacat.info("  SYSID: " + systemid);
614 2076 jones
    }
615 185 jones
616 2076 jones
    /**
617
     * SAX Handler that receives notification of end of DTD
618
     */
619
    public void endDTD() throws SAXException
620
    {
621 1359 tao
622 2076 jones
        processingDTD = false;
623 2663 sgarg
        logMetacat.info("Setting processingDTD to false");
624
        logMetacat.info("end DTD");
625 2076 jones
    }
626 185 jones
627 2076 jones
    /**
628
     * SAX Handler that receives notification of comments in the DTD
629
     */
630
    public void comment(char[] ch, int start, int length) throws SAXException
631
    {
632 2663 sgarg
        logMetacat.info("COMMENT");
633 2076 jones
        if (!processingDTD) {
634
            DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
635
            endNodeId = currentNode.writeChildNodeToDB("COMMENT", null,
636
                    new String(ch, start, length), docid);
637
        }
638
    }
639 185 jones
640 2076 jones
    /**
641
     * SAX Handler that receives notification of the start of CDATA sections
642
     */
643
    public void startCDATA() throws SAXException
644
    {
645 2663 sgarg
        logMetacat.info("start CDATA");
646 2076 jones
    }
647 185 jones
648 2076 jones
    /**
649
     * SAX Handler that receives notification of the end of CDATA sections
650
     */
651
    public void endCDATA() throws SAXException
652
    {
653 2663 sgarg
        logMetacat.info("end CDATA");
654 2076 jones
    }
655 185 jones
656 2076 jones
    /**
657
     * SAX Handler that receives notification of the start of entities
658
     */
659
    public void startEntity(String name) throws SAXException
660
    {
661 2663 sgarg
        logMetacat.info("start ENTITY: " + name);
662 2076 jones
        //System.out.println("start ENTITY: " + name);
663
        if (name.equals("[dtd]")) {
664
            processingDTD = true;
665
        }
666
    }
667 185 jones
668 2076 jones
    /**
669
     * SAX Handler that receives notification of the end of entities
670
     */
671
    public void endEntity(String name) throws SAXException
672
    {
673 2663 sgarg
        logMetacat.info("end ENTITY: " + name);
674 2076 jones
        //System.out.println("end ENTITY: " + name);
675
        if (name.equals("[dtd]")) {
676
            processingDTD = false;
677
        }
678
    }
679 186 jones
680 2076 jones
    /**
681
     * SAX Handler that receives notification of element declarations
682
     */
683
    public void elementDecl(String name, String model)
684
            throws org.xml.sax.SAXException
685
    {
686
        //System.out.println("ELEMENTDECL: " + name + " " + model);
687 2663 sgarg
        logMetacat.info("ELEMENTDECL: " + name + " " + model);
688 2076 jones
    }
689 186 jones
690 2076 jones
    /**
691
     * SAX Handler that receives notification of attribute declarations
692
     */
693
    public void attributeDecl(String eName, String aName, String type,
694
            String valueDefault, String value) throws org.xml.sax.SAXException
695
    {
696 821 bojilova
697 2076 jones
        //System.out.println("ATTRIBUTEDECL: " + eName + " "
698
        //                        + aName + " " + type + " " + valueDefault + " "
699
        //                        + value);
700 2663 sgarg
        logMetacat.info("ATTRIBUTEDECL: " + eName + " " + aName + " "
701
                + type + " " + valueDefault + " " + value);
702 2076 jones
    }
703 186 jones
704 2076 jones
    /**
705
     * SAX Handler that receives notification of internal entity declarations
706
     */
707
    public void internalEntityDecl(String name, String value)
708
            throws org.xml.sax.SAXException
709
    {
710
        //System.out.println("INTERNENTITYDECL: " + name + " " + value);
711 2663 sgarg
        logMetacat.info("INTERNENTITYDECL: " + name + " " + value);
712 2076 jones
    }
713 186 jones
714 2076 jones
    /**
715
     * SAX Handler that receives notification of external entity declarations
716
     */
717
    public void externalEntityDecl(String name, String publicId, String systemId)
718
            throws org.xml.sax.SAXException
719
    {
720
        //System.out.println("EXTERNENTITYDECL: " + name + " " + publicId
721
        //                              + " " + systemId);
722 2663 sgarg
        logMetacat.info("EXTERNENTITYDECL: " + name + " " + publicId
723
                + " " + systemId);
724 2076 jones
        // it processes other external entity, not the DTD;
725
        // it doesn't signal for the DTD here
726
        processingDTD = false;
727
    }
728 186 jones
729 2076 jones
    //
730
    // the next section implements the ErrorHandler interface
731
    //
732 186 jones
733 2076 jones
    /**
734
     * SAX Handler that receives notification of fatal parsing errors
735
     */
736
    public void fatalError(SAXParseException exception) throws SAXException
737
    {
738 2663 sgarg
        logMetacat.fatal("FATALERROR: " + exception.getMessage());
739 2076 jones
        throw (new SAXException("Fatal processing error.", exception));
740
    }
741 204 jones
742 2076 jones
    /**
743
     * SAX Handler that receives notification of recoverable parsing errors
744
     */
745
    public void error(SAXParseException exception) throws SAXException
746
    {
747 2663 sgarg
        logMetacat.error("ERROR: " + exception.getMessage());
748 2289 sgarg
        throw (new SAXException("Error in processing EML.", exception));
749 2076 jones
    }
750 204 jones
751 2076 jones
    /**
752
     * SAX Handler that receives notification of warnings
753
     */
754
    public void warning(SAXParseException exception) throws SAXException
755
    {
756 2663 sgarg
        logMetacat.warn("WARNING: " + exception.getMessage());
757 2076 jones
        throw (new SAXException("Warning.", exception));
758
    }
759 204 jones
760 2076 jones
    //
761
    // Helper, getter and setter methods
762
    //
763 1359 tao
764 2076 jones
    /**
765
     * get the document name
766
     */
767
    public String getDocname()
768
    {
769
        return docname;
770
    }
771 204 jones
772 2076 jones
    /**
773
     * get the document processing state
774
     */
775
    public boolean processingDTD()
776
    {
777
        return processingDTD;
778
    }
779 2590 tao
780
781
    /**
782
     * get the the is revision doc
783
     * @return
784
     */
785
    public boolean getIsRevisionDoc()
786
    {
787
        return isRevisionDoc;
788
    }
789
790
    /**
791
     * Set the the handler is for revisionDoc
792
     * @param isRevisionDoc
793
     */
794
    public void setIsRevisionDoc(boolean isRevisionDoc)
795
    {
796
       this.isRevisionDoc = isRevisionDoc;
797
    }
798 2076 jones
799
    /* Method to write a text buffer for DBSAXNode */
800
    protected long writeTextForDBSAXNode(long previousEndNodeId,
801
            StringBuffer strBuffer, DBSAXNode node) throws SAXException
802
    {
803
        long nodeId = previousEndNodeId;
804
        // Check parameter
805
        if (strBuffer == null || node == null) { return nodeId; }
806
        boolean moredata = true;
807
        String data = null;
808 2352 sgarg
809
        String normalizedData = strBuffer.toString();
810 4470 daigle
        logMetacat.debug("Before normalize in write process === "+normalizedData);
811 3731 tao
        String afterNormalize = MetaCatUtil.normalize(normalizedData);
812 4470 daigle
        logMetacat.debug("After normalize in write process === "+afterNormalize);
813 3731 tao
        strBuffer = new StringBuffer(afterNormalize);;
814 2352 sgarg
815 2076 jones
        int bufferSize = strBuffer.length();
816
        int start = 0;
817
818
        // if there are some cotent in buffer, write it
819
        if (bufferSize > 0) {
820 2663 sgarg
            logMetacat.info("Write text into DB");
821 2076 jones
            // This loop deals with the case where there are more characters
822
            // than can fit in a single database text field (limit is
823
            // MAXDATACHARS). If the text to be inserted exceeds MAXDATACHARS,
824
            // write a series of nodes that are MAXDATACHARS long, and then the
825
            // final node contains the remainder
826
            while (moredata) {
827
                bufferSize = strBuffer.length();
828
                if (bufferSize > MAXDATACHARS) {
829
                    data = strBuffer.substring(start, MAXDATACHARS);
830
                    // cut the stringbuffer part that already written into db
831
                    strBuffer = strBuffer.delete(start, MAXDATACHARS);
832
                } else {
833
                    data = strBuffer.substring(start, bufferSize);
834
                    moredata = false;
835
                }
836
837
                // Write the content of the node to the database
838 2352 sgarg
                nodeId = node.writeChildNodeToDB("TEXT", null, data, docid);
839 2076 jones
            }//while
840
        }//if
841
        return nodeId;
842
    }
843 2605 tao
844
    public long getRootNodeId()
845
    {
846
        return rootNode.getNodeID();
847
    }
848 2620 tao
849
    public String getDocumentType()
850
    {
851
        return doctype;
852
    }
853
854
    public String getDocumentName()
855
    {
856
        return docname;
857
    }
858
859
    public String getCatalogId()
860
    {
861
        return catalogid;
862
    }
863 17 jones
}