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-04-09 16:36:27 -0700 (Wed, 09 Apr 2003) $'
12
 * '$Revision: 1535 $'
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 java.sql.*;
32
import java.io.StringReader;
33
import java.util.Stack;
34
import java.util.Vector;
35
import java.util.Hashtable;
36
import java.util.Enumeration;
37
import java.util.EmptyStackException;
38

    
39
import org.xml.sax.Attributes;
40
import org.xml.sax.SAXException;
41
import org.xml.sax.SAXParseException;
42
import org.xml.sax.ext.DeclHandler;
43
import org.xml.sax.ext.LexicalHandler;
44
import org.xml.sax.helpers.DefaultHandler;
45

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

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

    
80
   protected static final int MAXDATACHARS = 4000;
81
   protected static final long INDEXDELAY = 10000;
82
   // methods writeChildNodeToDB, setAttribute, setNamespace, 
83
   // writeTextForDBSAXNode will increase endNodeId.
84
   protected long  endNodeId = -1;    // The end node id for a substree
85
// DOCTITLE attr cleared from the db
86
//   private static final int MAXTITLELEN = 1000;
87

    
88
   /** Construct an instance of the handler class
89
    *
90
    * @param conn the JDBC connection to which information is written
91
    */
92
   public DBSAXHandler(DBConnection conn) {
93
     this.connection = conn;
94
     this.atFirstElement = true;
95
     this.processingDTD = false;
96

    
97
     // Create the stack for keeping track of node context
98
     // if it doesn't already exist
99
     if (!stackCreated) {
100
       nodeStack = new Stack();
101
       nodeIndex = new Vector();
102
       stackCreated = true;
103
     }
104
   }
105

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

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

    
159
   /** SAX Handler that receives notification of beginning of the document */
160
   public void startDocument() throws SAXException {
161
     MetaCatUtil.debugMessage("start Document", 50);
162

    
163
     // Create the document node representation as root
164
     rootNode = new DBSAXNode(connection, this.docid);
165
     // Add the node to the stack, so that any text data can be
166
     // added as it is encountered
167
     nodeStack.push(rootNode);
168
   }
169

    
170
   /** SAX Handler that receives notification of end of the document */
171
   public void endDocument() throws SAXException {
172
     MetaCatUtil.debugMessage("end Document", 50);
173
     // Starting new thread for writing XML Index.
174
     // It calls the run method of the thread.
175
     try {
176
       xmlIndex.start();
177
     } catch (NullPointerException e) {
178
       xmlIndex = null;
179
       throw new
180
       SAXException("Problem with starting thread for writing XML Index. " +
181
                    e.getMessage());
182
     }
183
   }
184

    
185
   /** SAX Handler that is called at the start of Namespace */
186
   public void startPrefixMapping(String prefix, String uri)
187
                                          throws SAXException
188
   {
189
    MetaCatUtil.debugMessage("NAMESPACE", 50);
190

    
191
    namespaces.put(prefix, uri);
192
   }
193

    
194
   /** SAX Handler that is called at the start of each XML element */
195
   public void startElement(String uri, String localName,
196
                            String qName, Attributes atts)
197
               throws SAXException {
198
     // for element <eml:eml...> qname is "eml:eml", local name is "eml"            
199
     // for element <acl....> both qname and local name is "eml"
200
     // uri is namesapce
201
     MetaCatUtil.debugMessage("Start ELEMENT(qName) " + qName, 50);
202
     MetaCatUtil.debugMessage("Start ELEMENT(localName) " + localName, 50);
203
     MetaCatUtil.debugMessage("Start ELEMENT(uri) " + uri, 50);
204
     
205
     DBSAXNode parentNode = null;
206
     DBSAXNode currentNode = null;
207

    
208
     // Get a reference to the parent node for the id
209
     try {
210
       parentNode = (DBSAXNode)nodeStack.peek();
211
     } catch (EmptyStackException e) {
212
       parentNode = null;
213
     }
214
     
215
     // If hit a text node, we need write this text for current's parent node
216
     // This will happend if the element is mixted
217
     if (hitTextNode && parentNode != null)
218
     {
219
       // write the textbuffer into db for parent node.
220
        endNodeId = writeTextForDBSAXNode(textBuffer, parentNode);
221
        // rest hitTextNode
222
        hitTextNode =false;
223
        // reset textbuffer
224
        textBuffer = null;
225
        textBuffer = new StringBuffer();
226
       
227
     }
228

    
229
     // Document representation that points to the root document node
230
     if (atFirstElement) 
231
     {
232
       atFirstElement = false;
233
       // If no DOCTYPE declaration: docname = root element
234
       // doctype = root element name or name space
235
       if (docname == null) 
236
       {
237
         docname = localName;
238
         // if uri isn't null doctype = uri(namespace)
239
         // othewise root element
240
         if (uri != null && !(uri.trim()).equals(""))
241
         {
242
           doctype = uri;
243
         }
244
         else
245
         {
246
           doctype = docname;
247
         }
248
         MetaCatUtil.debugMessage("DOCNAME-a: " + docname, 30);
249
         MetaCatUtil.debugMessage("DOCTYPE-a: " + doctype, 30);
250
       } 
251
       else if (doctype == null) 
252
       {
253
         // because docname is not null and it is declared in dtd
254
         // so could not be in schema, no namespace
255
         doctype = docname;
256
         MetaCatUtil.debugMessage("DOCTYPE-b: " + doctype, 30);
257
       }
258
       rootNode.writeNodename(docname);
259
       try {
260
         // for validated XML Documents store a reference to XML DB Catalog
261
         // Because this is select statement and it needn't to roll back if
262
         // insert document action fialed.
263
         // In order to decrease DBConnection usage count, we get a new
264
         // dbconnection from pool
265
         String catalogid = null;
266
         DBConnection dbConn = null;
267
         int serialNumber = -1;
268

    
269
         if ( systemid != null ) {
270
           try
271
           {
272
            // Get dbconnection
273
            dbConn=DBConnectionPool.getDBConnection
274
                                          ("DBSAXHandler.startElement");
275
            serialNumber=dbConn.getCheckOutSerialNumber();
276

    
277
            Statement stmt = dbConn.createStatement();
278
            ResultSet rs = stmt.executeQuery(
279
                          "SELECT catalog_id FROM xml_catalog " +
280
                          "WHERE entry_type = 'DTD' " +
281
                          "AND public_id = '" + doctype + "'");
282
            boolean hasRow = rs.next();
283
            if ( hasRow ) {
284
              catalogid = rs.getString(1);
285
            }
286
            stmt.close();
287
           }//try
288
           finally
289
           {
290
             // Return dbconnection
291
             DBConnectionPool.returnDBConnection(dbConn, serialNumber);
292
           }//finally
293
         }
294

    
295
         //create documentImpl object by the constructor which can specify
296
         //the revision
297
         currentDocument = new DocumentImpl(connection, rootNode.getNodeID(),
298
                               docname, doctype, docid, revision, action, user,
299
                               this.pub, catalogid, this.serverCode);
300

    
301

    
302
       } catch (Exception ane) {
303
         throw (new SAXException("Error in DBSaxHandler.startElement " +
304
                                 action, ane));
305
       }
306
     }
307

    
308
     // Create the current node representation
309
     currentNode = new DBSAXNode(connection, qName, localName, parentNode,
310
                                 currentDocument.getRootNodeID(),docid,
311
                                 currentDocument.getDoctype());
312

    
313
     // Add all of the namespaces
314
     String prefix;
315
     String nsuri;
316
     Enumeration prefixes = namespaces.keys();
317
     while ( prefixes.hasMoreElements() ) {
318
       prefix = (String)prefixes.nextElement();
319
       nsuri = (String)namespaces.get(prefix);
320
       currentNode.setNamespace(prefix, nsuri, docid);
321
     }
322
     namespaces = null;
323
     namespaces = new Hashtable();
324

    
325
     // Add all of the attributes
326
     for (int i=0; i<atts.getLength(); i++) 
327
     {
328
       String attributeName = atts.getQName(i);
329
       String attributeValue = atts.getValue(i);
330
       endNodeId = 
331
                currentNode.setAttribute(attributeName, attributeValue, docid);
332
       
333
       // To handle name space and schema location if the attribute name is
334
       // xsi:schemaLocation. If the name space is in not in catalog table
335
       // it will be regeistered.
336
       if (attributeName != null && 
337
           attributeName.indexOf(MetaCatServlet.SCHEMALOCATIONKEYWORD) != -1)
338
       {
339
         SchemaLocationResolver resolver = 
340
                                  new SchemaLocationResolver(attributeValue);
341
         resolver.resolveNameSpace();
342
         
343
       }
344
     }
345

    
346
     // Add the node to the stack, so that any text data can be
347
     // added as it is encountered
348
     nodeStack.push(currentNode);
349
     // Add the node to the vector used by thread for writing XML Index
350
     nodeIndex.addElement(currentNode);
351

    
352
  }
353

    
354
  /* The run method of xmlIndex thread. It writes XML Index for the document. */
355
  public void run () {
356
    DBSAXNode currNode = null;
357
    DBSAXNode prevNode = null;
358
    DBConnection dbConn = null;
359
    int serialNumber = -1;
360
    String doctype = currentDocument.getDoctype();
361
    int step = 0;
362
    int counter = 0;
363

    
364
    try {
365

    
366
      // Opening separate db connection for writing XML Index
367
      dbConn=DBConnectionPool.getDBConnection("DBSAXHandler.run");
368
      serialNumber=dbConn.getCheckOutSerialNumber();
369
      dbConn.setAutoCommit(false);
370

    
371
      //the following while loop construct checks to make sure that the docid
372
      //of the document that we are trying to index is already
373
      //in the xml_documents table.  if this is not the case, the foreign
374
      //key relationship between xml_documents and xml_index is temporarily
375
      //broken causing multiple problems.
376
      boolean inxmldoc = false;
377
      long startTime = System.currentTimeMillis();
378
      while(!inxmldoc)
379
      {
380
        String xmlDocumentsCheck = "select distinct docid from xml_documents";
381
        PreparedStatement xmlDocCheck =
382
                                 dbConn.prepareStatement(xmlDocumentsCheck);
383
        // Increase usage count
384
        dbConn.increaseUsageCount(1);
385
        xmlDocCheck.execute();
386
        ResultSet doccheckRS = xmlDocCheck.getResultSet();
387
        boolean tableHasRows = doccheckRS.next();
388
        Vector docids = new Vector();
389
        while(tableHasRows)
390
        {
391
          docids.add(doccheckRS.getString(1).trim());
392
          tableHasRows = doccheckRS.next();
393
        }
394

    
395
        for(int i=0; i<docids.size(); i++)
396
        {
397
          String d = ((String)docids.elementAt(i)).trim();
398
          if(docid.trim().equals(d))
399
          {
400
            inxmldoc = true;
401
          }
402
        }
403
        doccheckRS.close();
404
        xmlDocCheck.close();
405
        // make sure the while loop will be ended in reseaonable time
406
        long stopTime = System.currentTimeMillis();
407
        if ((stopTime - startTime) > INDEXDELAY)
408
        {
409
          throw new Exception("Couldn't find the docid for index build in" +
410
                              "reseaonable time!");
411
        }
412
      }
413

    
414
      // Going through the elements of the document and writing its Index
415
      Enumeration nodes = nodeIndex.elements();
416
      while ( nodes.hasMoreElements() ) {
417
        currNode = (DBSAXNode)nodes.nextElement();
418
        currNode.updateNodeIndex(dbConn, docid, doctype);
419
      }
420

    
421

    
422
      dbConn.commit();
423

    
424
      //if this is a package file
425
      String packagedoctype = MetaCatUtil.getOption("packagedoctype");
426
      Vector packagedoctypes = new Vector();
427

    
428
      packagedoctypes = MetaCatUtil.getOptionList(packagedoctype);
429

    
430
      if ( packagedoctypes.contains(doctype) )
431
      {
432
        // write the package info to xml_relation table
433
        RelationHandler rth = new RelationHandler(docid, dbConn);
434
        // from the relations get the access file id for that package
435
        String aclid = rth.getAccessFileID(docid);
436
        // if there are access file, write ACL for that package
437
        if ( aclid != null ) {
438
          runAccessControlList(dbConn, aclid);
439
        }
440

    
441
      }
442
        // if it is an access file
443
      else if ( MetaCatUtil.getOptionList(
444
                     MetaCatUtil.getOption("accessdoctype")).contains(doctype) )
445
      {
446
        // write ACL for the package
447
        runAccessControlList(dbConn, docid);
448
        
449
      }
450
   
451

    
452
    } catch (Exception e) {
453
      try {
454
        dbConn.rollback();
455
        //dbconn.close();
456
      } catch (SQLException sqle) {}
457
      MetaCatUtil.debugMessage("Error in DBSAXHandler.run " + 
458
                                e.getMessage(), 30);
459
      
460
    }
461
    finally
462
    {
463
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
464
    }//finally
465
  }
466

    
467
  // It runs in xmlIndex thread. It writes ACL for a package.
468
  private void runAccessControlList (DBConnection conn, String aclid)
469
                                                throws Exception
470
  {
471
    // read the access file from xml_nodes
472
    // parse the access file and store the access info into xml_access
473
    AccessControlList aclobj =
474
    new AccessControlList(conn, aclid, //new StringReader(xml),
475
                          user, groups, serverCode);
476
    conn.commit();
477
  }
478

    
479

    
480
  /** SAX Handler that is called for each XML text node */
481
  public void characters(char[] cbuf, int start, int len) throws SAXException 
482
  {
483
     MetaCatUtil.debugMessage("CHARACTERS", 50);
484
     // buffer all text nodes for same element. This is for text was splited
485
     // into different nodes
486
     textBuffer.append(new String(cbuf, start,len));
487
     // set hittextnode true
488
     hitTextNode = true;
489
  }
490

    
491
   /**
492
    * SAX Handler that is called for each XML text node that is
493
    * Ignorable white space
494
    */
495
   public void ignorableWhitespace(char[] cbuf, int start, int len)
496
               throws SAXException {
497
     // When validation is turned "on", white spaces are reported here
498
     // When validation is turned "off" white spaces are not reported here,
499
     // but through characters() callback
500
     MetaCatUtil.debugMessage("IGNORABLEWHITESPACE", 50);
501

    
502

    
503
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
504
     String data = null;
505
     int leftover = len;
506
     int offset = start;
507
     boolean moredata = true;
508

    
509
     // This loop deals with the case where there are more characters
510
     // than can fit in a single database text field (limit is
511
     // MAXDATACHARS).  If the text to be inserted exceeds MAXDATACHARS,
512
     // write a series of nodes that are MAXDATACHARS long, and then the
513
     // final node contains the remainder
514
     while (moredata) {
515
       if (leftover > MAXDATACHARS) {
516
         data = new String(cbuf, offset, MAXDATACHARS);
517
         leftover -= MAXDATACHARS;
518
         offset += MAXDATACHARS;
519
       } else {
520
         data = new String(cbuf, offset, leftover);
521
         moredata = false;
522
       }
523

    
524
       // Write the content of the node to the database
525
       endNodeId = currentNode.writeChildNodeToDB("TEXT", null, data, docid);
526
     }
527
   }
528

    
529
   /**
530
    * SAX Handler called once for each processing instruction found:
531
    * node that PI may occur before or after the root element.
532
    */
533
   public void processingInstruction(String target, String data)
534
          throws SAXException {
535
     MetaCatUtil.debugMessage("PI", 50);
536
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
537
     endNodeId = currentNode.writeChildNodeToDB("PI", target, data, docid);
538
   }
539

    
540
   /** SAX Handler that is called at the end of each XML element */
541
   public void endElement(String uri, String localName,
542
                          String qName) throws SAXException {
543
     MetaCatUtil.debugMessage("End ELEMENT " + qName, 50);
544
     
545
     // write buffered text nodes into db (so no splited)
546
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
547
      
548
     // If before the end element, the parser hit text nodes and store them
549
     // into the buffer, write the buffer to data base. The reason we put
550
     // write database here is for xerces some time split text node
551
     if (hitTextNode)
552
     {
553
       MetaCatUtil.debugMessage("Write text into DB in End Element", 50);
554
       endNodeId = writeTextForDBSAXNode(textBuffer, currentNode);
555
     }//if
556
     
557
     //set hitText false
558
     hitTextNode = false;
559
     // reset textbuff
560
     textBuffer = null;
561
     textBuffer = new StringBuffer();
562

    
563
     // Get the node from the stack
564
     currentNode = (DBSAXNode)nodeStack.pop();
565
   }
566

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

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

    
578
     processingDTD = true;
579

    
580
     MetaCatUtil.debugMessage("Start DTD", 50);
581
     MetaCatUtil.debugMessage("Setting processingDTD to true", 50);
582
     MetaCatUtil.debugMessage("DOCNAME: " + docname, 50);
583
     MetaCatUtil.debugMessage("DOCTYPE: " + doctype, 50);
584
     MetaCatUtil.debugMessage("  SYSID: " + systemid, 50);
585
   }
586

    
587
   /**
588
    * SAX Handler that receives notification of end of DTD
589
    */
590
   public void endDTD() throws SAXException {
591

    
592
     processingDTD = false;
593
     MetaCatUtil.debugMessage("Setting processingDTD to false", 50);
594
     MetaCatUtil.debugMessage("end DTD", 50);
595
   }
596

    
597
   /**
598
    * SAX Handler that receives notification of comments in the DTD
599
    */
600
   public void comment(char[] ch, int start, int length) throws SAXException {
601
     MetaCatUtil.debugMessage("COMMENT", 50);
602
     if ( !processingDTD ) {
603
       DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
604
       endNodeId = 
605
        currentNode.writeChildNodeToDB("COMMENT", null, 
606
                                       new String(ch, start, length), docid);
607
     }
608
   }
609

    
610
   /**
611
    * SAX Handler that receives notification of the start of CDATA sections
612
    */
613
   public void startCDATA() throws SAXException {
614
     MetaCatUtil.debugMessage("start CDATA", 50);
615
   }
616

    
617
   /**
618
    * SAX Handler that receives notification of the end of CDATA sections
619
    */
620
   public void endCDATA() throws SAXException {
621
     MetaCatUtil.debugMessage("end CDATA", 50);
622
   }
623

    
624
   /**
625
    * SAX Handler that receives notification of the start of entities
626
    */
627
   public void startEntity(String name) throws SAXException {
628
     MetaCatUtil.debugMessage("start ENTITY: " + name, 50);
629
//System.out.println("start ENTITY: " + name);
630
     if (name.equals("[dtd]")) {
631
       processingDTD = true;
632
     }
633
   }
634

    
635
   /**
636
    * SAX Handler that receives notification of the end of entities
637
    */
638
   public void endEntity(String name) throws SAXException {
639
     MetaCatUtil.debugMessage("end ENTITY: " + name, 50);
640
//System.out.println("end ENTITY: " + name);
641
     if (name.equals("[dtd]")) {
642
       processingDTD = false;
643
     }
644
   }
645

    
646
   /**
647
    * SAX Handler that receives notification of element declarations
648
    */
649
   public void elementDecl(String name, String model)
650
                        throws org.xml.sax.SAXException {
651
//System.out.println("ELEMENTDECL: " + name + " " + model);
652
     MetaCatUtil.debugMessage("ELEMENTDECL: " + name + " " + model, 50);
653
   }
654

    
655
   /**
656
    * SAX Handler that receives notification of attribute declarations
657
    */
658
   public void attributeDecl(String eName, String aName,
659
                        String type, String valueDefault, String value)
660
                        throws org.xml.sax.SAXException {
661

    
662
//System.out.println("ATTRIBUTEDECL: " + eName + " "
663
//                        + aName + " " + type + " " + valueDefault + " "
664
//                        + value);
665
     MetaCatUtil.debugMessage("ATTRIBUTEDECL: " + eName + " "
666
                        + aName + " " + type + " " + valueDefault + " "
667
                        + value, 50);
668
   }
669

    
670
   /**
671
    * SAX Handler that receives notification of internal entity declarations
672
    */
673
   public void internalEntityDecl(String name, String value)
674
                        throws org.xml.sax.SAXException {
675
//System.out.println("INTERNENTITYDECL: " + name + " " + value);
676
     MetaCatUtil.debugMessage("INTERNENTITYDECL: " + name + " " + value, 50);
677
   }
678

    
679
   /**
680
    * SAX Handler that receives notification of external entity declarations
681
    */
682
   public void externalEntityDecl(String name, String publicId,
683
                        String systemId)
684
                        throws org.xml.sax.SAXException {
685
//System.out.println("EXTERNENTITYDECL: " + name + " " + publicId
686
//                              + " " + systemId);
687
     MetaCatUtil.debugMessage("EXTERNENTITYDECL: " + name + " " + publicId
688
                              + " " + systemId, 50);
689
     // it processes other external entity, not the DTD;
690
     // it doesn't signal for the DTD here
691
     processingDTD = false;
692
   }
693

    
694
   //
695
   // the next section implements the ErrorHandler interface
696
   //
697

    
698
   /**
699
    * SAX Handler that receives notification of fatal parsing errors
700
    */
701
   public void fatalError(SAXParseException exception) throws SAXException {
702
     MetaCatUtil.debugMessage("FATALERROR: "+exception.getMessage(), 50);
703
     throw (new SAXException("Fatal processing error.", exception));
704
   }
705

    
706
   /**
707
    * SAX Handler that receives notification of recoverable parsing errors
708
    */
709
   public void error(SAXParseException exception) throws SAXException {
710
     MetaCatUtil.debugMessage("ERROR: "+exception.getMessage(), 50);
711
     throw (new SAXException("Processing error.", exception));
712
   }
713

    
714
   /**
715
    * SAX Handler that receives notification of warnings
716
    */
717
   public void warning(SAXParseException exception) throws SAXException {
718
     MetaCatUtil.debugMessage("WARNING: "+exception.getMessage(), 50);
719
     throw (new SAXException("Warning.", exception));
720
   }
721

    
722
   //
723
   // Helper, getter and setter methods
724
   //
725

    
726
   /**
727
    * get the document name
728
    */
729
   public String getDocname() {
730
     return docname;
731
   }
732

    
733
   /**
734
    * get the document processing state
735
    */
736
   public boolean processingDTD() {
737
     return processingDTD;
738
   }
739
   
740
   /* Method to write a text buffer for DBSAXNode*/
741
   protected long writeTextForDBSAXNode(StringBuffer strBuffer, DBSAXNode node)
742
                                      throws SAXException
743
   {
744
     long nodeId = -1;
745
     // Check parameter
746
     if ( strBuffer == null || node == null)
747
     {
748
       return nodeId;
749
     }
750
     boolean moredata = true;
751
     String data = null;
752
     int bufferSize = strBuffer.length();
753
     int start = 0;
754
    
755
     // if there are some cotent in buffer, write it
756
     if (bufferSize > 0)
757
     {
758
       MetaCatUtil.debugMessage("Write text into DB", 50);
759
       // This loop deals with the case where there are more characters
760
       // than can fit in a single database text field (limit is
761
       // MAXDATACHARS).  If the text to be inserted exceeds MAXDATACHARS,
762
       // write a series of nodes that are MAXDATACHARS long, and then the
763
       // final node contains the remainder
764
       while (moredata) 
765
       {
766
          bufferSize = strBuffer.length();
767
          if (bufferSize > MAXDATACHARS) 
768
         {
769
            data = strBuffer.substring(start, MAXDATACHARS);
770
            // cut the stringbuffer part that already written into db
771
            strBuffer = strBuffer.delete(start, MAXDATACHARS);
772
          } 
773
          else 
774
          {
775
            data = strBuffer.substring(start, bufferSize);
776
            moredata = false;
777
          }
778
       
779
          // Write the content of the node to the database
780
          nodeId = node.writeChildNodeToDB("TEXT", null, data, docid);
781
        }//while
782
     }//if
783
     return nodeId;
784
   }
785
}
(22-22/56)