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
 *    Release: @release@
9
 *
10
 *   '$Author: tao $'
11
 *     '$Date: 2003-07-28 17:50:34 -0700 (Mon, 28 Jul 2003) $'
12
 * '$Revision: 1761 $'
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 2 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27
 */
28

    
29
package edu.ucsb.nceas.metacat;
30

    
31
import edu.ucsb.nceas.morpho.datapackage.Triple;
32
import edu.ucsb.nceas.morpho.datapackage.TripleCollection;
33

    
34
import java.sql.*;
35
import java.io.StringReader;
36
import java.util.Stack;
37
import java.util.Vector;
38
import java.util.Hashtable;
39
import java.util.Enumeration;
40
import java.util.EmptyStackException;
41

    
42
import org.xml.sax.Attributes;
43
import org.xml.sax.SAXException;
44
import org.xml.sax.SAXParseException;
45
import org.xml.sax.ext.DeclHandler;
46
import org.xml.sax.ext.LexicalHandler;
47
import org.xml.sax.helpers.DefaultHandler;
48

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

    
56
   protected boolean	atFirstElement;
57
   protected boolean	processingDTD;
58
   protected String 	docname = null;
59
   protected String 	doctype;
60
   protected String 	systemid;
61
   private boolean 	stackCreated = false;
62
   protected Stack 	  nodeStack;
63
   protected Vector   nodeIndex;
64
   protected DBConnection	  connection = null;
65
   protected DocumentImpl currentDocument;
66
   protected DBSAXNode    rootNode;
67
   protected String   action = null;
68
   protected String   docid = null;
69
   protected String   revision = null;
70
   protected String   user = null;
71
   protected String[] groups = null;
72
   protected String   pub = null;
73
   protected Thread   xmlIndex;
74
   private boolean endDocument = false;
75
   protected int serverCode = 1;
76
   protected Hashtable namespaces = new Hashtable();
77
   protected boolean hitTextNode = false; // a flag to hit text node
78
   // a buffer to keep all text nodes for same element
79
   // it is for element was splited
80
   protected StringBuffer textBuffer = new StringBuffer();
81
   protected Stack textBufferStack = new Stack();
82

    
83
   protected static final int MAXDATACHARS = 4000;
84
   //protected static final int MAXDATACHARS = 50;
85
   protected static final long INDEXDELAY = 10000;
86
   // methods writeChildNodeToDB, setAttribute, setNamespace, 
87
   // writeTextForDBSAXNode will increase endNodeId.
88
   protected long  endNodeId = -1;    // The end node id for a substree
89
// DOCTITLE attr cleared from the db
90
//   private static final int MAXTITLELEN = 1000;
91
   //HandlerTriple stuff
92
   TripleCollection tripleList = new TripleCollection();
93
   Triple currentTriple        = new Triple();
94
   boolean startParseTriple    = false;
95
   boolean hasTriple           = false;
96

    
97
   /** Construct an instance of the handler class
98
    *
99
    * @param conn the JDBC connection to which information is written
100
    */
101
   public DBSAXHandler(DBConnection conn) {
102
     this.connection = conn;
103
     this.atFirstElement = true;
104
     this.processingDTD = false;
105

    
106
     // Create the stack for keeping track of node context
107
     // if it doesn't already exist
108
     if (!stackCreated) {
109
       nodeStack = new Stack();
110
       nodeIndex = new Vector();
111
       stackCreated = true;
112
     }
113
   }
114

    
115
  /** Construct an instance of the handler class
116
    *
117
    * @param conn the JDBC connection to which information is written
118
    * @param action - "INSERT" or "UPDATE"
119
    * @param docid to be inserted or updated into JDBC connection
120
    * @param user the user connected to MetaCat servlet and owns the document
121
    * @param groups the groups to which user belongs
122
    * @param pub flag for public "read" access on document
123
    * @param serverCode the serverid from xml_replication on which this document
124
    *        resides.
125
    *
126
    */
127
   public DBSAXHandler(DBConnection conn, String action, String docid,
128
                      String user, String[] groups, String pub, int serverCode)
129
   {
130
     this(conn);
131
     this.action = action;
132
     this.docid = docid;
133
     this.user = user;
134
     this.groups = groups;
135
     this.pub = pub;
136
     this.serverCode = serverCode;
137
     this.xmlIndex = new Thread(this);
138
   }
139

    
140
  /** Construct an instance of the handler class
141
    * In this constructor, user can specify the version need to upadate
142
    *
143
    * @param conn the JDBC connection to which information is written
144
    * @param action - "INSERT" or "UPDATE"
145
    * @param docid to be inserted or updated into JDBC connection
146
    * @param revision, the user specified the revision need to be update
147
    * @param user the user connected to MetaCat servlet and owns the document
148
    * @param groups the groups to which user belongs
149
    * @param pub flag for public "read" access on document
150
    * @param serverCode the serverid from xml_replication on which this document
151
    *        resides.
152
    *
153
    */
154
   public DBSAXHandler(DBConnection conn, String action, String docid,
155
     String revision, String user, String[] groups, String pub, int serverCode)
156
   {
157
     this(conn);
158
     this.action = action;
159
     this.docid = docid;
160
     this.revision = revision;
161
     this.user = user;
162
     this.groups = groups;
163
     this.pub = pub;
164
     this.serverCode = serverCode;
165
     this.xmlIndex = new Thread(this);
166
   }
167

    
168
   /** SAX Handler that receives notification of beginning of the document */
169
   public void startDocument() throws SAXException {
170
     MetaCatUtil.debugMessage("start Document", 50);
171

    
172
     // Create the document node representation as root
173
     rootNode = new DBSAXNode(connection, this.docid);
174
     // Add the node to the stack, so that any text data can be
175
     // added as it is encountered
176
     nodeStack.push(rootNode);
177
   }
178

    
179
   /** SAX Handler that receives notification of end of the document */
180
   public void endDocument() throws SAXException {
181
     MetaCatUtil.debugMessage("end Document", 50);
182
     // Starting new thread for writing XML Index.
183
     // It calls the run method of the thread.
184
     
185
     //if it is data package insert triple into relationtion table;
186
     if ( doctype != null && 
187
         MetaCatUtil.getOptionList(MetaCatUtil.getOption("packagedoctype")).
188
         contains(doctype) && hasTriple)
189
      {
190
        try
191
        {
192
          //initial handler and write into relationdb
193
          RelationHandler handler = 
194
                        new RelationHandler(docid,doctype, connection, tripleList);
195
        }
196
        catch (Exception e)
197
        {
198
          MetaCatUtil.debugMessage
199
                            ("Failed to write triples into relation table" + 
200
                                                           e.getMessage(), 30);
201
          throw new SAXException("Failed to write triples into relation table "+ e.getMessage());
202
        }
203
      }
204
     
205
     
206
     try {
207
       xmlIndex.start();
208
     } catch (NullPointerException e) {
209
       xmlIndex = null;
210
       throw new
211
       SAXException("Problem with starting thread for writing XML Index. " +
212
                    e.getMessage());
213
     }
214
   }
215

    
216
   /** SAX Handler that is called at the start of Namespace */
217
   public void startPrefixMapping(String prefix, String uri)
218
                                          throws SAXException
219
   {
220
    MetaCatUtil.debugMessage("NAMESPACE", 50);
221

    
222
    namespaces.put(prefix, uri);
223
   }
224

    
225
   /** SAX Handler that is called at the start of each XML element */
226
   public void startElement(String uri, String localName,
227
                            String qName, Attributes atts)
228
               throws SAXException {
229
     // for element <eml:eml...> qname is "eml:eml", local name is "eml"            
230
     // for element <acl....> both qname and local name is "eml"
231
     // uri is namesapce
232
     MetaCatUtil.debugMessage("Start ELEMENT(qName) " + qName, 50);
233
     MetaCatUtil.debugMessage("Start ELEMENT(localName) " + localName, 50);
234
     MetaCatUtil.debugMessage("Start ELEMENT(uri) " + uri, 50);
235
     
236
     DBSAXNode parentNode = null;
237
     DBSAXNode currentNode = null;
238

    
239
     // Get a reference to the parent node for the id
240
     try {
241
       parentNode = (DBSAXNode)nodeStack.peek();
242
     } catch (EmptyStackException e) {
243
       parentNode = null;
244
     }
245
     
246
     // If hit a text node, we need write this text for current's parent node
247
     // This will happend if the element is mixted
248
     if (hitTextNode && parentNode != null)
249
     {
250
       // write the textbuffer into db for parent node.
251
        endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer, parentNode);
252
        // rest hitTextNode
253
        hitTextNode =false;
254
        // reset textbuffer
255
        textBuffer = null;
256
        textBuffer = new StringBuffer();
257
       
258
     }
259

    
260
     // Document representation that points to the root document node
261
     if (atFirstElement) 
262
     {
263
       atFirstElement = false;
264
       // If no DOCTYPE declaration: docname = root element
265
       // doctype = root element name or name space
266
       if (docname == null) 
267
       {
268
         docname = localName;
269
         // if uri isn't null doctype = uri(namespace)
270
         // othewise root element
271
         if (uri != null && !(uri.trim()).equals(""))
272
         {
273
           doctype = uri;
274
         }
275
         else
276
         {
277
           doctype = docname;
278
         }
279
         MetaCatUtil.debugMessage("DOCNAME-a: " + docname, 30);
280
         MetaCatUtil.debugMessage("DOCTYPE-a: " + doctype, 30);
281
       } 
282
       else if (doctype == null) 
283
       {
284
         // because docname is not null and it is declared in dtd
285
         // so could not be in schema, no namespace
286
         doctype = docname;
287
         MetaCatUtil.debugMessage("DOCTYPE-b: " + doctype, 30);
288
       }
289
       rootNode.writeNodename(docname);
290
       try {
291
         // for validated XML Documents store a reference to XML DB Catalog
292
         // Because this is select statement and it needn't to roll back if
293
         // insert document action fialed.
294
         // In order to decrease DBConnection usage count, we get a new
295
         // dbconnection from pool
296
         String catalogid = null;
297
         DBConnection dbConn = null;
298
         int serialNumber = -1;
299

    
300
         if ( systemid != null ) {
301
           try
302
           {
303
            // Get dbconnection
304
            dbConn=DBConnectionPool.getDBConnection
305
                                          ("DBSAXHandler.startElement");
306
            serialNumber=dbConn.getCheckOutSerialNumber();
307

    
308
            Statement stmt = dbConn.createStatement();
309
            ResultSet rs = stmt.executeQuery(
310
                          "SELECT catalog_id FROM xml_catalog " +
311
                          "WHERE entry_type = 'DTD' " +
312
                          "AND public_id = '" + doctype + "'");
313
            boolean hasRow = rs.next();
314
            if ( hasRow ) {
315
              catalogid = rs.getString(1);
316
            }
317
            stmt.close();
318
           }//try
319
           finally
320
           {
321
             // Return dbconnection
322
             DBConnectionPool.returnDBConnection(dbConn, serialNumber);
323
           }//finally
324
         }
325

    
326
         //create documentImpl object by the constructor which can specify
327
         //the revision
328
         currentDocument = new DocumentImpl(connection, rootNode.getNodeID(),
329
                               docname, doctype, docid, revision, action, user,
330
                               this.pub, catalogid, this.serverCode);
331

    
332

    
333
       } catch (Exception ane) {
334
         throw (new SAXException("Error in DBSaxHandler.startElement " +
335
                                 action, ane));
336
       }
337
     }
338

    
339
     // Create the current node representation
340
     currentNode = new DBSAXNode(connection, qName, localName, parentNode,
341
                                 currentDocument.getRootNodeID(),docid,
342
                                 currentDocument.getDoctype());
343

    
344
     // Add all of the namespaces
345
     String prefix;
346
     String nsuri;
347
     Enumeration prefixes = namespaces.keys();
348
     while ( prefixes.hasMoreElements() ) {
349
       prefix = (String)prefixes.nextElement();
350
       nsuri = (String)namespaces.get(prefix);
351
       currentNode.setNamespace(prefix, nsuri, docid);
352
     }
353
     namespaces = null;
354
     namespaces = new Hashtable();
355

    
356
     // Add all of the attributes
357
     for (int i=0; i<atts.getLength(); i++) 
358
     {
359
       String attributeName = atts.getQName(i);
360
       String attributeValue = atts.getValue(i);
361
       endNodeId = 
362
                currentNode.setAttribute(attributeName, attributeValue, docid);
363
       
364
       // To handle name space and schema location if the attribute name is
365
       // xsi:schemaLocation. If the name space is in not in catalog table
366
       // it will be regeistered.
367
       if (attributeName != null && 
368
           attributeName.indexOf(MetaCatServlet.SCHEMALOCATIONKEYWORD) != -1)
369
       {
370
         SchemaLocationResolver resolver = 
371
                                  new SchemaLocationResolver(attributeValue);
372
         resolver.resolveNameSpace();
373
         
374
       }
375
     }
376

    
377
     // Add the node to the stack, so that any text data can be
378
     // added as it is encountered
379
     nodeStack.push(currentNode);
380
     // Add the node to the vector used by thread for writing XML Index
381
     nodeIndex.addElement(currentNode);
382
     // start parsing triple
383
     if ( doctype != null && 
384
         MetaCatUtil.getOptionList(MetaCatUtil.getOption("packagedoctype")).contains(doctype)
385
         && localName.equals("triple"))
386
      {
387
        startParseTriple = true;
388
        hasTriple = true;
389
        currentTriple = new Triple();
390
      }
391
  }
392

    
393
  /* The run method of xmlIndex thread. It writes XML Index for the document. */
394
  public void run () {
395
    DBSAXNode currNode = null;
396
    DBSAXNode prevNode = null;
397
    DBConnection dbConn = null;
398
    int serialNumber = -1;
399
    String doctype = currentDocument.getDoctype();
400
    int step = 0;
401
    int counter = 0;
402

    
403
    try {
404

    
405
      // Opening separate db connection for writing XML Index
406
      dbConn=DBConnectionPool.getDBConnection("DBSAXHandler.run");
407
      serialNumber=dbConn.getCheckOutSerialNumber();
408
      dbConn.setAutoCommit(false);
409

    
410
      //the following while loop construct checks to make sure that the docid
411
      //of the document that we are trying to index is already
412
      //in the xml_documents table.  if this is not the case, the foreign
413
      //key relationship between xml_documents and xml_index is temporarily
414
      //broken causing multiple problems.
415
      boolean inxmldoc = false;
416
      long startTime = System.currentTimeMillis();
417
      while(!inxmldoc)
418
      {
419
        String xmlDocumentsCheck = "select distinct docid from xml_documents";
420
        PreparedStatement xmlDocCheck =
421
                                 dbConn.prepareStatement(xmlDocumentsCheck);
422
        // Increase usage count
423
        dbConn.increaseUsageCount(1);
424
        xmlDocCheck.execute();
425
        ResultSet doccheckRS = xmlDocCheck.getResultSet();
426
        boolean tableHasRows = doccheckRS.next();
427
        Vector docids = new Vector();
428
        while(tableHasRows)
429
        {
430
          docids.add(doccheckRS.getString(1).trim());
431
          tableHasRows = doccheckRS.next();
432
        }
433

    
434
        for(int i=0; i<docids.size(); i++)
435
        {
436
          String d = ((String)docids.elementAt(i)).trim();
437
          if(docid.trim().equals(d))
438
          {
439
            inxmldoc = true;
440
          }
441
        }
442
        doccheckRS.close();
443
        xmlDocCheck.close();
444
        // make sure the while loop will be ended in reseaonable time
445
        long stopTime = System.currentTimeMillis();
446
        if ((stopTime - startTime) > INDEXDELAY)
447
        {
448
          throw new Exception("Couldn't find the docid for index build in" +
449
                              "reseaonable time!");
450
        }
451
      }
452

    
453
      // Going through the elements of the document and writing its Index
454
      Enumeration nodes = nodeIndex.elements();
455
      while ( nodes.hasMoreElements() ) {
456
        currNode = (DBSAXNode)nodes.nextElement();
457
        currNode.updateNodeIndex(dbConn, docid, doctype);
458
      }
459

    
460

    
461
      dbConn.commit();
462

    
463
      //if this is a package file
464
    
465
   
466

    
467
    } catch (Exception e) {
468
      try {
469
        dbConn.rollback();
470
        //dbconn.close();
471
      } catch (SQLException sqle) {}
472
      MetaCatUtil.debugMessage("Error in DBSAXHandler.run " + 
473
                                e.getMessage(), 30);
474
      
475
    }
476
    finally
477
    {
478
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
479
    }//finally
480
  }
481

    
482
  /** SAX Handler that is called for each XML text node */
483
  public void characters(char[] cbuf, int start, int len) throws SAXException 
484
  {
485
     MetaCatUtil.debugMessage("CHARACTERS", 50);
486
     // buffer all text nodes for same element. This is for text was splited
487
     // into different nodes
488
     textBuffer.append(new String(cbuf, start,len));
489
     // set hittextnode true
490
     hitTextNode = true;
491
     // if text buffer .size is greater than max, write it to db. 
492
     // so we can save memory
493
     if (textBuffer.length() > MAXDATACHARS)
494
     {
495
       MetaCatUtil.debugMessage("Write text into DB in charaters" + 
496
                   " when text buffer size is greater than maxmum number", 50);
497
       DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
498
       endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer, currentNode);
499
       textBuffer = null;
500
       textBuffer = new StringBuffer();
501
     }
502
  }
503

    
504
   /**
505
    * SAX Handler that is called for each XML text node that is
506
    * Ignorable white space
507
    */
508
   public void ignorableWhitespace(char[] cbuf, int start, int len)
509
               throws SAXException {
510
     // When validation is turned "on", white spaces are reported here
511
     // When validation is turned "off" white spaces are not reported here,
512
     // but through characters() callback
513
     MetaCatUtil.debugMessage("IGNORABLEWHITESPACE", 50);
514

    
515

    
516
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
517
     String data = null;
518
     int leftover = len;
519
     int offset = start;
520
     boolean moredata = true;
521

    
522
     // This loop deals with the case where there are more characters
523
     // than can fit in a single database text field (limit is
524
     // MAXDATACHARS).  If the text to be inserted exceeds MAXDATACHARS,
525
     // write a series of nodes that are MAXDATACHARS long, and then the
526
     // final node contains the remainder
527
     while (moredata) {
528
       if (leftover > MAXDATACHARS) {
529
         data = new String(cbuf, offset, MAXDATACHARS);
530
         leftover -= MAXDATACHARS;
531
         offset += MAXDATACHARS;
532
       } else {
533
         data = new String(cbuf, offset, leftover);
534
         moredata = false;
535
       }
536

    
537
       // Write the content of the node to the database
538
       endNodeId = currentNode.writeChildNodeToDB("TEXT", null, data, docid);
539
     }
540
   }
541

    
542
   /**
543
    * SAX Handler called once for each processing instruction found:
544
    * node that PI may occur before or after the root element.
545
    */
546
   public void processingInstruction(String target, String data)
547
          throws SAXException {
548
     MetaCatUtil.debugMessage("PI", 50);
549
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
550
     endNodeId = currentNode.writeChildNodeToDB("PI", target, data, docid);
551
   }
552

    
553
   /** SAX Handler that is called at the end of each XML element */
554
   public void endElement(String uri, String localName,
555
                          String qName) throws SAXException {
556
     MetaCatUtil.debugMessage("End ELEMENT " + qName, 50);
557
     
558
     // write buffered text nodes into db (so no splited)
559
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
560
      
561
     // If before the end element, the parser hit text nodes and store them
562
     // into the buffer, write the buffer to data base. The reason we put
563
     // write database here is for xerces some time split text node
564
     if (hitTextNode)
565
     {
566
       MetaCatUtil.debugMessage("Write text into DB in End Element", 50);
567
       endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer, currentNode);
568
       
569
       //if it is triple parsing process
570
       if (startParseTriple)
571
       {
572
         
573
          String content = textBuffer.toString().trim();
574
          if(localName.equals("subject"))
575
          { //get the subject content
576
            currentTriple.setSubject(content);
577
          }
578
          else if(localName.equals("relationship"))
579
          { //get the relationship content
580
            currentTriple.setRelationship(content);
581
          }
582
          else if(localName.equals("object"))
583
          { //get the object content
584
            currentTriple.setObject(content);
585
          }
586
       }
587
       
588
     }//if
589
     
590
     //set hitText false
591
     hitTextNode = false;
592
     // reset textbuff
593
     textBuffer = null;
594
     textBuffer = new StringBuffer();
595

    
596
     // Get the node from the stack
597
     currentNode = (DBSAXNode)nodeStack.pop();
598
     //finishing parsing single triple
599
     if (startParseTriple && localName.equals("triple"))
600
      {
601
        // add trip to triple collection
602
        tripleList.addTriple(currentTriple);
603
        //rest variable
604
        currentTriple = null;
605
        startParseTriple = false;   
606
      }
607
   }
608

    
609
   //
610
   // the next section implements the LexicalHandler interface
611
   //
612

    
613
   /** SAX Handler that receives notification of DOCTYPE. Sets the DTD */
614
   public void startDTD(String name, String publicId, String systemId)
615
               throws SAXException {
616
     docname = name;
617
     doctype = publicId;
618
     systemid = systemId;
619

    
620
     processingDTD = true;
621

    
622
     MetaCatUtil.debugMessage("Start DTD", 50);
623
     MetaCatUtil.debugMessage("Setting processingDTD to true", 50);
624
     MetaCatUtil.debugMessage("DOCNAME: " + docname, 50);
625
     MetaCatUtil.debugMessage("DOCTYPE: " + doctype, 50);
626
     MetaCatUtil.debugMessage("  SYSID: " + systemid, 50);
627
   }
628

    
629
   /**
630
    * SAX Handler that receives notification of end of DTD
631
    */
632
   public void endDTD() throws SAXException {
633

    
634
     processingDTD = false;
635
     MetaCatUtil.debugMessage("Setting processingDTD to false", 50);
636
     MetaCatUtil.debugMessage("end DTD", 50);
637
   }
638

    
639
   /**
640
    * SAX Handler that receives notification of comments in the DTD
641
    */
642
   public void comment(char[] ch, int start, int length) throws SAXException {
643
     MetaCatUtil.debugMessage("COMMENT", 50);
644
     if ( !processingDTD ) {
645
       DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
646
       endNodeId = 
647
        currentNode.writeChildNodeToDB("COMMENT", null, 
648
                                       new String(ch, start, length), docid);
649
     }
650
   }
651

    
652
   /**
653
    * SAX Handler that receives notification of the start of CDATA sections
654
    */
655
   public void startCDATA() throws SAXException {
656
     MetaCatUtil.debugMessage("start CDATA", 50);
657
   }
658

    
659
   /**
660
    * SAX Handler that receives notification of the end of CDATA sections
661
    */
662
   public void endCDATA() throws SAXException {
663
     MetaCatUtil.debugMessage("end CDATA", 50);
664
   }
665

    
666
   /**
667
    * SAX Handler that receives notification of the start of entities
668
    */
669
   public void startEntity(String name) throws SAXException {
670
     MetaCatUtil.debugMessage("start ENTITY: " + name, 50);
671
//System.out.println("start ENTITY: " + name);
672
     if (name.equals("[dtd]")) {
673
       processingDTD = true;
674
     }
675
   }
676

    
677
   /**
678
    * SAX Handler that receives notification of the end of entities
679
    */
680
   public void endEntity(String name) throws SAXException {
681
     MetaCatUtil.debugMessage("end ENTITY: " + name, 50);
682
//System.out.println("end ENTITY: " + name);
683
     if (name.equals("[dtd]")) {
684
       processingDTD = false;
685
     }
686
   }
687

    
688
   /**
689
    * SAX Handler that receives notification of element declarations
690
    */
691
   public void elementDecl(String name, String model)
692
                        throws org.xml.sax.SAXException {
693
//System.out.println("ELEMENTDECL: " + name + " " + model);
694
     MetaCatUtil.debugMessage("ELEMENTDECL: " + name + " " + model, 50);
695
   }
696

    
697
   /**
698
    * SAX Handler that receives notification of attribute declarations
699
    */
700
   public void attributeDecl(String eName, String aName,
701
                        String type, String valueDefault, String value)
702
                        throws org.xml.sax.SAXException {
703

    
704
//System.out.println("ATTRIBUTEDECL: " + eName + " "
705
//                        + aName + " " + type + " " + valueDefault + " "
706
//                        + value);
707
     MetaCatUtil.debugMessage("ATTRIBUTEDECL: " + eName + " "
708
                        + aName + " " + type + " " + valueDefault + " "
709
                        + value, 50);
710
   }
711

    
712
   /**
713
    * SAX Handler that receives notification of internal entity declarations
714
    */
715
   public void internalEntityDecl(String name, String value)
716
                        throws org.xml.sax.SAXException {
717
//System.out.println("INTERNENTITYDECL: " + name + " " + value);
718
     MetaCatUtil.debugMessage("INTERNENTITYDECL: " + name + " " + value, 50);
719
   }
720

    
721
   /**
722
    * SAX Handler that receives notification of external entity declarations
723
    */
724
   public void externalEntityDecl(String name, String publicId,
725
                        String systemId)
726
                        throws org.xml.sax.SAXException {
727
//System.out.println("EXTERNENTITYDECL: " + name + " " + publicId
728
//                              + " " + systemId);
729
     MetaCatUtil.debugMessage("EXTERNENTITYDECL: " + name + " " + publicId
730
                              + " " + systemId, 50);
731
     // it processes other external entity, not the DTD;
732
     // it doesn't signal for the DTD here
733
     processingDTD = false;
734
   }
735

    
736
   //
737
   // the next section implements the ErrorHandler interface
738
   //
739

    
740
   /**
741
    * SAX Handler that receives notification of fatal parsing errors
742
    */
743
   public void fatalError(SAXParseException exception) throws SAXException {
744
     MetaCatUtil.debugMessage("FATALERROR: "+exception.getMessage(), 50);
745
     throw (new SAXException("Fatal processing error.", exception));
746
   }
747

    
748
   /**
749
    * SAX Handler that receives notification of recoverable parsing errors
750
    */
751
   public void error(SAXParseException exception) throws SAXException {
752
     MetaCatUtil.debugMessage("ERROR: "+exception.getMessage(), 50);
753
     throw (new SAXException("Processing error.", exception));
754
   }
755

    
756
   /**
757
    * SAX Handler that receives notification of warnings
758
    */
759
   public void warning(SAXParseException exception) throws SAXException {
760
     MetaCatUtil.debugMessage("WARNING: "+exception.getMessage(), 50);
761
     throw (new SAXException("Warning.", exception));
762
   }
763

    
764
   //
765
   // Helper, getter and setter methods
766
   //
767

    
768
   /**
769
    * get the document name
770
    */
771
   public String getDocname() {
772
     return docname;
773
   }
774

    
775
   /**
776
    * get the document processing state
777
    */
778
   public boolean processingDTD() {
779
     return processingDTD;
780
   }
781
   
782
   /* Method to write a text buffer for DBSAXNode*/
783
   protected long writeTextForDBSAXNode(long previousEndNodeId, 
784
                                        StringBuffer strBuffer, DBSAXNode node)
785
                                        throws SAXException
786
   {
787
     long nodeId = previousEndNodeId;
788
     // Check parameter
789
     if ( strBuffer == null || node == null)
790
     {
791
       return nodeId;
792
     }
793
     boolean moredata = true;
794
     String data = null;
795
     int bufferSize = strBuffer.length();
796
     int start = 0;
797
    
798
     // if there are some cotent in buffer, write it
799
     if (bufferSize > 0)
800
     {
801
       MetaCatUtil.debugMessage("Write text into DB", 50);
802
       // This loop deals with the case where there are more characters
803
       // than can fit in a single database text field (limit is
804
       // MAXDATACHARS).  If the text to be inserted exceeds MAXDATACHARS,
805
       // write a series of nodes that are MAXDATACHARS long, and then the
806
       // final node contains the remainder
807
       while (moredata) 
808
       {
809
          bufferSize = strBuffer.length();
810
          if (bufferSize > MAXDATACHARS) 
811
         {
812
            data = strBuffer.substring(start, MAXDATACHARS);
813
            // cut the stringbuffer part that already written into db
814
            strBuffer = strBuffer.delete(start, MAXDATACHARS);
815
          } 
816
          else 
817
          {
818
            data = strBuffer.substring(start, bufferSize);
819
            moredata = false;
820
          }
821
       
822
          // Write the content of the node to the database
823
          nodeId = node.writeChildNodeToDB("TEXT", null, data, docid);
824
        }//while
825
     }//if
826
     return nodeId;
827
   }
828
}
(23-23/57)