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-15 21:18:03 -0700 (Tue, 15 Apr 2003) $'
12
 * '$Revision: 1555 $'
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.BufferedReader;
33
import java.io.File;
34
import java.io.FileReader;
35
import java.io.FileWriter;
36
import java.io.StringReader;
37
import java.util.Stack;
38
import java.util.Vector;
39
import java.util.Hashtable;
40
import java.util.Enumeration;
41
import java.util.EmptyStackException;
42

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

    
50
/**
51
 * A database aware Class implementing callback bethods for the SAX parser to
52
 * call when processing the XML stream and generating events
53
 */
54
public class EmlSAXHandler extends DBSAXHandler implements 
55
                                                      AccessControlInterface
56
{
57
   private Vector allowRules = new Vector();
58
   private Vector denyRules = new Vector();
59
   private String documentId = null;
60
   private Vector subDocumentIdList = new Vector();
61
   private boolean processTopLeverAccess = false;
62
   private boolean processAdditionalAccess = false;
63
   private boolean processOtherAccess = false;
64
   private AccessSection accessObject= null;
65
   private AccessRule accessRule = null;
66
   private Vector accessObjectList = new Vector(); // store every access rule
67
   private Hashtable topLevelAccessControlMap = new Hashtable();
68
   private Hashtable additionalAccessControlMap = new Hashtable();// store 
69
                                                 //subtree access for single
70
                                                 // additionalmetacat
71
   private Vector additionalAccessMapList = new Vector();// store maps for 
72
                                                       // every addionalmetadata
73
   private Vector describesId = new Vector(); // store the ids in
74
                                      //additionalmetadata/describes
75
   private Stack subTreeInfoStack = new Stack();
76
   private Vector subTreeList = new Vector();// store the final subtree
77
   private int inLineDataIndex = 1;
78
   private Hashtable unChangableSubTreeHash = new Hashtable();
79
   private Stack currentUnChangedableSubtreeNodeStack =new Stack();
80
   private boolean startCriticalSubTree = false;
81
   private boolean firstElementForCriticalSubTree = false;
82
   private String firstElementNameForCriticalSubTree;
83
   private boolean needCheckingAccessModule = false;
84
   private Vector unChangableAccessSubTreeVector = new Vector();
85
   private Stack currentUnchangableAccessModuleNodeStack = new Stack();
86
   private AccessSection topAccessSection;
87
   
88
   // we need an another stack to store the access node which we pull out just
89
   // from xml. If a reference happend, we can use the stack the compare nodes
90
   private Stack storedAccessNodeStack = new Stack();
91
   // vector stored the data file id which will be write into relation table
92
   private Vector onlineDataFileIdVector = new Vector();
93
 
94
 
95
   // Constant
96
   private static final String EML ="eml";
97
   private static final String DESCRIBES = "describes";
98
   private static final String ADDITIONALMETADATA = "additionalMetadata";
99
   private static final String ORDER = "order";
100
   private static final String ID ="id";
101
   private static final String REFERENCES = "references";
102
   public  static final String INLINE = "inline";
103
   private static final String ONLINE = "online";
104
   private static final String URL    = "url";
105
   private static final String PERMISSIONERROR ="User try to update a subtree"+
106
                               " which it doesn't have write permission!";
107
   private static final String UPDATEACCESSERROR = "User try to update a " + 
108
                      "access module which it doesn't have \"ALL\" permission!";
109
   private static final String TOPLEVEL = "top";
110
   private static final String SUBTREELEVEL ="subtree";
111
   private static final String RELATION = "Provides info for";
112
  
113
    /** Construct an instance of the handler class
114
    * In this constructor, user can specify the version need to upadate
115
    *
116
    * @param conn the JDBC connection to which information is written
117
    * @param action - "INSERT" or "UPDATE"
118
    * @param docid to be inserted or updated into JDBC connection
119
    * @param revision, the user specified the revision need to be update
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 EmlSAXHandler(DBConnection conn, String action, String docid,
128
     String revision, String user, String[] groups, String pub, int serverCode)
129
                              throws SAXException
130
   {
131
     super(conn, action, docid, revision, user, groups, pub, serverCode);
132
     // Get the unchangable subtrees (user doesn't have write permission)
133
     try
134
     {
135
       PermissionController control = new PermissionController(docid);
136
       //unChangableSubTreeHash = getUnchangableSubTree(control, user, groups);
137
       
138
       
139
       //If the action is update and user doesn't have "ALL" permission
140
       // we need to check if user update access subtree
141
       if (action.equals("UPDATE") && 
142
         !control.hasPermission(user, groups, AccessControlInterface.ALLSTRING))
143
       {
144
         needCheckingAccessModule = true;
145
         unChangableAccessSubTreeVector = getAccessSubTreeListFromDB();
146
       }
147
     }
148
     catch (Exception e)
149
     {
150
       throw new SAXException(e.getMessage());
151
     }
152
   }
153
   
154
   /* Pass a permission control and get the list of unchangable subtree*/
155
   private Hashtable getUnchangableSubTree(PermissionController controller,
156
                                           String user, String[]groups)
157
                                           throws Exception
158
   {
159
     Hashtable list = null;
160
     Hashtable result = new Hashtable();
161
     // get unwritable sutree from controller
162
     list = controller.hasUnaccessableSubTree(user, groups, 
163
                                          AccessControlInterface.WRITESTRING);
164
      if (list != null)
165
      {
166
       
167
         Enumeration en = list.elements();
168
         while (en.hasMoreElements())
169
         {
170
           // Get  a subtree without node record list
171
           SubTree treeWithoutStack = (SubTree)en.nextElement();
172
           String subTreeId   = treeWithoutStack.getSubTreeId();
173
           MetaCatUtil.debugMessage("unchangable subtree id: " + subTreeId, 40);
174
           long   startNodeId = treeWithoutStack.getStartNodeId();
175
           MetaCatUtil.debugMessage("unchangable subtree startnodeid: " +
176
                                    startNodeId, 40);
177
           long   endNodeId   = treeWithoutStack.getEndNodeId();
178
           MetaCatUtil.debugMessage("unchangable subtree endnodeid: " +
179
                                     endNodeId, 40);
180
           // Get a subtree has the nodelist
181
           SubTree tree = new SubTree(docid, subTreeId, startNodeId, endNodeId);
182
           // add this tree to the result
183
           result.put(subTreeId, tree);
184
         
185
          }//while
186
      
187
      }//if
188
      
189
      return result;
190
   }
191
   
192
   
193
   /*
194
    * Get the subtree node info from xml_accesssubtree table
195
    */
196
   private Vector getAccessSubTreeListFromDB() throws Exception
197
   {
198
      Vector result = new Vector();
199
      PreparedStatement pstmt = null;
200
      ResultSet rs = null;
201
      String sql = "SELECT controllevel, subtreeid, startnodeid, endnodeid " + 
202
                   "FROM xml_accesssubtree WHERE docid like ? " +
203
                   "ORDER BY startnodeid ASC";
204
              
205
      try 
206
      {
207
     
208
        pstmt = connection.prepareStatement(sql);
209
        // Increase DBConnection usage count
210
        connection.increaseUsageCount(1);
211
        // Bind the values to the query
212
        pstmt.setString(1, docid);
213
        pstmt.execute();
214
        
215
        // Get result set
216
        rs = pstmt.getResultSet();
217
        while (rs.next())
218
        {
219
          String level = rs.getString(1);
220
          String sectionId = rs.getString(2);
221
          long startNodeId = rs.getLong(3);
222
          long endNodeId = rs.getLong(4);
223
          // create a new access section
224
          AccessSection accessObj = new AccessSection();
225
          accessObj.setControlLevel(level);
226
          accessObj.setDocId(docid);
227
          accessObj.setSubTreeId(sectionId);
228
          accessObj.setStartNodeId(startNodeId);
229
          accessObj.setEndNodeId(endNodeId); 
230
          Stack nodeStack = accessObj.getSubTreeNodeList();
231
          accessObj.setSubTreeNodeStack(nodeStack);
232
          // add this access obj into vector
233
          result.add(accessObj);
234
          // Get the top level access subtree control
235
          if ( level != null && level.equals(TOPLEVEL))
236
          {
237
            topAccessSection = accessObj;
238
          }
239
        }
240
        pstmt.close();
241
      }//try 
242
      catch (SQLException e) 
243
      {
244
        throw new 
245
        SAXException("EMLSAXHandler.getAccessSubTreeListFromDB(): " + 
246
                      e.getMessage());
247
      }//catch
248
      finally
249
      {
250
        try
251
        {
252
          pstmt.close();
253
        }
254
        catch(SQLException ee)
255
        {
256
          throw new 
257
          SAXException("EMLSAXHandler.getAccessSubTreeListFromDB(): " + 
258
          ee.getMessage());
259
        }
260
      }//finally
261
      return result;
262
   }
263
   /** SAX Handler that is called at the start of each XML element */
264
   public void startElement(String uri, String localName,
265
                            String qName, Attributes atts)
266
               throws SAXException 
267
  {
268
      // for element <eml:eml...> qname is "eml:eml", local name is "eml"            
269
     // for element <acl....> both qname and local name is "eml"
270
     // uri is namesapce
271
     MetaCatUtil.debugMessage("Start ELEMENT(qName) " + qName, 50);
272
     MetaCatUtil.debugMessage("Start ELEMENT(localName) " + localName, 50);
273
     MetaCatUtil.debugMessage("Start ELEMENT(uri) " + uri, 50);
274
     
275
     
276
     DBSAXNode parentNode = null;
277
     DBSAXNode currentNode = null;
278

    
279
     // Get a reference to the parent node for the id
280
     try 
281
     {
282
       parentNode = (DBSAXNode)nodeStack.peek();
283
     } 
284
     catch (EmptyStackException e) 
285
     {
286
       parentNode = null;
287
     }
288
     
289
     // If hit a text node, we need write this text for current's parent node
290
     // This will happend if the element is mixted
291
     if (hitTextNode && parentNode != null)
292
     {
293
       //compare text node data for unchangesubtree
294
       if (startCriticalSubTree)
295
       {
296
         compareTextNode(currentUnChangedableSubtreeNodeStack, textBuffer, 
297
                         PERMISSIONERROR);
298
       }//if
299
      
300
       //compare top level access module
301
       if (processTopLeverAccess && needCheckingAccessModule)
302
       {
303
          compareTextNode(currentUnchangableAccessModuleNodeStack, 
304
                          textBuffer, UPDATEACCESSERROR);
305
       }
306
       
307
       if (needCheckingAccessModule && 
308
       (processAdditionalAccess || processOtherAccess || processTopLeverAccess))
309
       {
310
        // stored the pull out nodes into storedNode stack
311
        NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "TEXT", 
312
                      null, null, MetaCatUtil.normalize(textBuffer.toString()));
313
        storedAccessNodeStack.push(nodeElement);
314
                                         
315
      }
316
        
317
       // write the textbuffer into db for parent node.
318
        endNodeId = writeTextForDBSAXNode(textBuffer, parentNode);
319
        // rest hitTextNode
320
        hitTextNode =false;
321
        // reset textbuffer
322
        textBuffer = null;
323
        textBuffer = new StringBuffer();
324
       
325
     }
326
     
327
  
328
     // Document representation that points to the root document node
329
     if (atFirstElement) 
330
     {
331
       atFirstElement = false;
332
       // If no DOCTYPE declaration: docname = root element
333
       // doctype = root element name or name space
334
       if (docname == null) 
335
       {
336
         docname = localName;
337
         // if uri isn't null doctype = uri(namespace)
338
         // othewise root element
339
         if (uri != null && !(uri.trim()).equals(""))
340
         {
341
           doctype = uri;
342
         }
343
         else
344
         {
345
           doctype = docname;
346
         }
347
         MetaCatUtil.debugMessage("DOCNAME-a: " + docname, 30);
348
         MetaCatUtil.debugMessage("DOCTYPE-a: " + doctype, 30);
349
       } 
350
       else if (doctype == null) 
351
       {
352
         // because docname is not null and it is declared in dtd
353
         // so could not be in schema, no namespace
354
         doctype = docname;
355
         MetaCatUtil.debugMessage("DOCTYPE-b: " + doctype, 30);
356
       }
357
       rootNode.writeNodename(docname);
358
       try 
359
       {
360
         // for validated XML Documents store a reference to XML DB Catalog
361
         // Because this is select statement and it needn't to roll back if
362
         // insert document action fialed.
363
         // In order to decrease DBConnection usage count, we get a new
364
         // dbconnection from pool
365
         String catalogid = null;
366
         DBConnection dbConn = null;
367
         int serialNumber = -1;
368

    
369
         if ( systemid != null ) 
370
         {
371
           try
372
           {
373
            // Get dbconnection
374
            dbConn=DBConnectionPool.getDBConnection
375
                                          ("DBSAXHandler.startElement");
376
            serialNumber=dbConn.getCheckOutSerialNumber();
377

    
378
            Statement stmt = dbConn.createStatement();
379
            ResultSet rs = stmt.executeQuery(
380
                          "SELECT catalog_id FROM xml_catalog " +
381
                          "WHERE entry_type = 'DTD' " +
382
                          "AND public_id = '" + doctype + "'");
383
            boolean hasRow = rs.next();
384
            if ( hasRow ) {
385
              catalogid = rs.getString(1);
386
            }
387
            stmt.close();
388
           }//try
389
           finally
390
           {
391
             // Return dbconnection
392
             DBConnectionPool.returnDBConnection(dbConn, serialNumber);
393
           }//finally
394
         }
395

    
396
         //create documentImpl object by the constructor which can specify
397
         //the revision
398
         currentDocument = new DocumentImpl(connection, rootNode.getNodeID(),
399
                               docname, doctype, docid, revision, action, user,
400
                               this.pub, catalogid, this.serverCode);
401

    
402

    
403
       } 
404
       catch (Exception ane) 
405
       {
406
         throw (new SAXException("Error in DBSaxHandler.startElement " +
407
                                 action, ane));
408
       }
409
     }
410

    
411
     // Create the current node representation
412
     currentNode = new DBSAXNode(connection, qName, localName, parentNode,
413
                                 currentDocument.getRootNodeID(),docid,
414
                                 currentDocument.getDoctype());
415
     // Use a local variable to store the element node id
416
     // If this element is a start point of subtree(section), it will be stored
417
     // otherwise, it will be discated
418
     long startNodeId = currentNode.getNodeID();
419
     // Add all of the namespaces
420
     String prefix =null;
421
     String nsuri = null;
422
     Enumeration prefixes = namespaces.keys();
423
     while ( prefixes.hasMoreElements() ) 
424
     {
425
       prefix = (String)prefixes.nextElement();
426
       nsuri = (String)namespaces.get(prefix);
427
       endNodeId = currentNode.setNamespace(prefix, nsuri, docid);
428
     }
429
   
430

    
431
     // Add all of the attributes
432
     for (int i=0; i<atts.getLength(); i++) 
433
     {
434
       String attributeName = atts.getQName(i);
435
       String attributeValue = atts.getValue(i);
436
       endNodeId = 
437
                currentNode.setAttribute(attributeName, attributeValue, docid);
438
       
439
       // To handle name space and schema location if the attribute name is
440
       // xsi:schemaLocation. If the name space is in not in catalog table
441
       // it will be regeistered.
442
       if (attributeName != null && 
443
           attributeName.indexOf(MetaCatServlet.SCHEMALOCATIONKEYWORD) != -1)
444
       {
445
         SchemaLocationResolver resolver = 
446
                                  new SchemaLocationResolver(attributeValue);
447
         resolver.resolveNameSpace();
448
         
449
       }
450
       else if (attributeName !=null && attributeName.equals(ID))
451
       {
452
        
453
        
454
         //check unchangedable subtree hash if contains this subtree id
455
         if (unChangableSubTreeHash.containsKey(attributeValue))
456
         {
457
           // this subtree couldn't be changed by the user and move it from hash
458
           SubTree currentUnChangedableSubtree = (SubTree)
459
                                  unChangableSubTreeHash.remove(attributeValue);
460
           currentUnChangedableSubtreeNodeStack = currentUnChangedableSubtree.
461
                                                         getSubTreeNodeStack();
462
           startCriticalSubTree = true;
463
           firstElementForCriticalSubTree = true;
464
         }
465
         
466
         // handle subtree info
467
         SubTree subTress = new SubTree();
468
         // set sub tree id
469
         subTress.setSubTreeId(attributeValue);
470
         // set sub tree sstart lement name
471
         subTress.setStartElementName(currentNode.getTagName());
472
         // set start node number
473
         subTress.setStartNodeId(startNodeId);
474
         // add to stack, but it didn't get end node id yet
475
         subTreeInfoStack.push(subTress);
476
         
477
       }
478
     }//for
479
   
480
     // handle access stuff
481
     if (localName.equals(ACCESS))
482
     {
483
       // if it is in addtionalmetacat
484
       if (parentNode.getTagName() == ADDITIONALMETADATA)
485
       {
486
         processAdditionalAccess = true;
487
        
488
       }
489
       else
490
       {
491
         //make sure the access is top level
492
         // this mean current node's parent's parent should be "eml"
493
         DBSAXNode tmpNode = (DBSAXNode) nodeStack.pop();// pop out parent node
494
         //peek out grandParentNode
495
         DBSAXNode grandParentNode = (DBSAXNode)nodeStack.peek();
496
         // put parent node back
497
         nodeStack.push(tmpNode);
498
         String grandParentTag = grandParentNode.getTagName();
499
         if (grandParentTag.equals(EML))
500
         {
501
           processTopLeverAccess = true;
502
         }
503
         else
504
         {
505
           // process other access embedded into resource level module
506
           processOtherAccess = true;
507
         }
508
        
509
       }
510
       // create access object 
511
       accessObject = new AccessSection();
512
         // set permission order
513
       String permOrder = currentNode.getAttribute(ORDER);
514
       accessObject.setPermissionOrder(permOrder);
515
       // set access id
516
       String accessId = currentNode.getAttribute(ID);
517
       accessObject.setSubTreeId(accessId);
518
       accessObject.setStartNodeId(startNodeId);
519
       accessObject.setDocId(docid);
520
       
521
       // load top level node stack to currentUnchangableAccessModuleNodeStack
522
       if (processTopLeverAccess && needCheckingAccessModule)
523
       {
524
         // get the node stack for
525
         currentUnchangableAccessModuleNodeStack = 
526
                                        topAccessSection.getSubTreeNodeStack();
527
       }
528
                 
529
       
530
     }
531
     // Set up a access rule for allow
532
     else if (parentNode.getTagName() != null && 
533
       (parentNode.getTagName()).equals(ACCESS) && localName.equals(ALLOW))
534
     {
535
      
536
       accessRule = new AccessRule(); 
537
      
538
       //set permission type "allow"
539
       accessRule.setPermissionType(ALLOW);
540
      
541
     }
542
     // set up an access rule for den
543
     else if (parentNode.getTagName() != null 
544
       && (parentNode.getTagName()).equals(ACCESS) && localName.equals(DENY))
545
     {
546
       accessRule = new AccessRule();
547
       //set permission type "allow"
548
       accessRule.setPermissionType(DENY);
549
     }
550
      
551
     // Add the node to the stack, so that any text data can be
552
     // added as it is encountered
553
     nodeStack.push(currentNode);
554
     // Add the node to the vector used by thread for writing XML Index
555
     nodeIndex.addElement(currentNode);
556
    
557
    // handle critical subtree
558
    if (startCriticalSubTree && firstElementForCriticalSubTree)
559
    {
560
      //store the element name
561
      firstElementNameForCriticalSubTree = qName;
562
      firstElementForCriticalSubTree = false;
563
    }//for first element
564
    
565
    // handle critical subtree
566
    if (startCriticalSubTree)
567
    {
568
      compareElementNameSpaceAttributes(currentUnChangedableSubtreeNodeStack,
569
                                        namespaces, atts, localName, 
570
                                        PERMISSIONERROR);
571
      
572
    }
573
    //compare top access level module
574
    if (processTopLeverAccess && needCheckingAccessModule)
575
    {
576
      compareElementNameSpaceAttributes(currentUnchangableAccessModuleNodeStack, 
577
                                        namespaces, atts, localName, 
578
                                        UPDATEACCESSERROR);
579
       
580
    }
581
    
582
    // store access module element and attributes into stored stack
583
    if (needCheckingAccessModule && 
584
       (processAdditionalAccess || processOtherAccess || processTopLeverAccess))
585
    {
586
       // stored the pull out nodes into storedNode stack
587
       NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "ELEMENT", 
588
                                localName, prefix, MetaCatUtil.normalize(null));
589
       storedAccessNodeStack.push(nodeElement);
590
       for (int i=0; i<atts.getLength(); i++) 
591
       {
592
         String attributeName = atts.getQName(i);
593
         String attributeValue = atts.getValue(i);
594
         NodeRecord nodeAttribute = new NodeRecord(-2, -2, -2, "ATTRIBUTE",
595
                    attributeName, null, MetaCatUtil.normalize(attributeValue));
596
         storedAccessNodeStack.push(nodeAttribute);
597
       }
598
                                   
599
    }
600
   
601
    // reset name space
602
    namespaces = null;
603
    namespaces = new Hashtable();
604
  }
605
  
606
  private void compareElementNameSpaceAttributes(Stack unchangableNodeStack, 
607
                                            Hashtable nameSpaces,
608
                                            Attributes attributes,
609
                                            String localName, String error) 
610
                                            throws SAXException
611
  {
612
     //Get element subtree node stack (element node)
613
      NodeRecord elementNode = null;
614
      try
615
      {
616
        elementNode= (NodeRecord) unchangableNodeStack.pop();
617
      }
618
      catch (EmptyStackException ee)
619
      {
620
        MetaCatUtil.debugMessage("Node stack is empty for element data", 35);
621
        throw new SAXException(error);
622
      }
623
      MetaCatUtil.debugMessage("current node type from xml is ELEMENT", 40);
624
      MetaCatUtil.debugMessage("node type from stack: " + 
625
                                  elementNode.getNodeType(), 40);
626
      MetaCatUtil.debugMessage("node name from xml document: " + 
627
                                  localName, 40);
628
      MetaCatUtil.debugMessage("node name from stack: " +
629
                                  elementNode.getNodeName(), 40);
630
      MetaCatUtil.debugMessage("node data from stack: " +
631
                                  elementNode.getNodeData(), 40);
632
      MetaCatUtil.debugMessage("node id is: "+ elementNode.getNodeId(), 40);
633
      // if this node is not element or local name not equal or name space not
634
      // equals, throw an exception
635
      if (!elementNode.getNodeType().equals("ELEMENT") || 
636
          !localName.equals(elementNode.getNodeName()))
637
        //  (uri != null && !uri.equals(elementNode.getNodePrefix())))
638
      {
639
        MetaCatUtil.debugMessage("Inconsistence happend: ", 40);
640
        MetaCatUtil.debugMessage("current node type from xml is ELEMENT", 40);
641
        MetaCatUtil.debugMessage("node type from stack: " + 
642
                                  elementNode.getNodeType(), 40);
643
        MetaCatUtil.debugMessage("node name from xml document: " + 
644
                                  localName, 40);
645
        MetaCatUtil.debugMessage("node name from stack: " +
646
                                  elementNode.getNodeName(), 40);
647
        MetaCatUtil.debugMessage("node data from stack: " +
648
                                  elementNode.getNodeData(), 40);
649
        MetaCatUtil.debugMessage("node id is: "+ elementNode.getNodeId(), 40);
650
        throw new SAXException(error);
651
      }
652
      
653
      //compare namespace
654
     Enumeration nameEn = nameSpaces.keys();
655
     while ( nameEn.hasMoreElements() ) 
656
     {
657
       //Get namespacke node stack (element node)
658
       NodeRecord nameNode = null;
659
       try
660
       { 
661
         nameNode = (NodeRecord) unchangableNodeStack.pop();
662
       }
663
       catch (EmptyStackException ee)
664
       {
665
         MetaCatUtil.debugMessage("Node stack is empty for namespace data", 35);
666
         throw new SAXException(error);
667
       }
668
       
669
       String prefixName = (String)nameEn.nextElement(); 
670
       String nameSpaceUri = (String)nameSpaces.get(prefixName);
671
       if (!nameNode.getNodeType().equals("NAMESPACE") || 
672
           !prefixName.equals(nameNode.getNodeName()) || 
673
           !nameSpaceUri.equals(nameNode.getNodeData()))
674
       { 
675
         MetaCatUtil.debugMessage("Inconsistence happend: ", 40);
676
         MetaCatUtil.debugMessage("current node type from xml is NAMESPACE", 40);
677
         MetaCatUtil.debugMessage("node type from stack: " + 
678
                                  nameNode.getNodeType(), 40);
679
         MetaCatUtil.debugMessage("current node name from xml is: " + 
680
                                   prefixName, 40);
681
         MetaCatUtil.debugMessage("node name from stack: " +
682
                                  nameNode.getNodeName(), 40);
683
         MetaCatUtil.debugMessage("current node data from xml is: " + 
684
                                   nameSpaceUri, 40);
685
         MetaCatUtil.debugMessage("node data from stack: " +
686
                                  nameNode.getNodeData(), 40);
687
         MetaCatUtil.debugMessage("node id is: "+ nameNode.getNodeId(), 40);
688
         throw new SAXException(error);
689
       }
690
      
691
     }//while
692
      
693
      //compare attributes
694
      for (int i=0; i<attributes.getLength(); i++)
695
      {
696
        NodeRecord attriNode = null;
697
        try
698
        {
699
          attriNode = (NodeRecord)unchangableNodeStack.pop();
700
          
701
        }
702
        catch (EmptyStackException ee)
703
        {
704
          MetaCatUtil.debugMessage("Node stack is empty for attribute data", 35);
705
          throw new SAXException(error);
706
        }
707
        String attributeName = attributes.getQName(i);
708
        String attributeValue = attributes.getValue(i);
709
        MetaCatUtil.debugMessage("current node type from xml is ATTRIBUTE ", 40);
710
        MetaCatUtil.debugMessage("node type from stack: " + 
711
                                   attriNode.getNodeType(), 40);
712
        MetaCatUtil.debugMessage("current node name from xml is: " + 
713
                                    attributeName, 40);
714
        MetaCatUtil.debugMessage("node name from stack: " +
715
                                    attriNode.getNodeName(), 40);
716
        MetaCatUtil.debugMessage("current node data from xml is: " + 
717
                                    attributeValue, 40);
718
        MetaCatUtil.debugMessage("node data from stack: " +
719
                                    attriNode.getNodeData(), 40);
720
        MetaCatUtil.debugMessage("node id  is: "+ attriNode.getNodeId(), 40);
721
        
722
        if (!attriNode.getNodeType().equals("ATTRIBUTE") || 
723
            !attributeName.equals(attriNode.getNodeName()) ||
724
            !attributeValue.equals(attriNode.getNodeData()))
725
        {
726
          MetaCatUtil.debugMessage("Inconsistence happend: ", 40);
727
          MetaCatUtil.debugMessage("current node type from xml is ATTRIBUTE ", 40);
728
          MetaCatUtil.debugMessage("node type from stack: " + 
729
                                   attriNode.getNodeType(), 40);
730
          MetaCatUtil.debugMessage("current node name from xml is: " + 
731
                                    attributeName, 40);
732
          MetaCatUtil.debugMessage("node name from stack: " +
733
                                    attriNode.getNodeName(), 40);
734
          MetaCatUtil.debugMessage("current node data from xml is: " + 
735
                                    attributeValue, 40);
736
          MetaCatUtil.debugMessage("node data from stack: " +
737
                                    attriNode.getNodeData(), 40);
738
          MetaCatUtil.debugMessage("node is: "+ attriNode.getNodeId(), 40);
739
          throw new SAXException(error);
740
        }
741
      }//for
742
    
743
  }
744
  
745
  /* mehtod to compare current text node and node in db*/                                         
746
  private void compareTextNode(Stack nodeStack, StringBuffer text, String error) 
747
                               throws SAXException
748
  {
749
    NodeRecord node = null;
750
    //get node from current stack
751
    try
752
    { 
753
      node = (NodeRecord)nodeStack.pop();
754
    }
755
    catch (EmptyStackException ee)
756
    {
757
      MetaCatUtil.
758
          debugMessage("Node stack is empty for text data in startElement", 35);
759
      throw new SAXException(error);
760
    }
761
    MetaCatUtil.debugMessage("current node type from xml is TEXT in start element", 40);
762
    MetaCatUtil.debugMessage("node type from stack: " + 
763
                                        node.getNodeType(), 40);
764
    MetaCatUtil.debugMessage("current node data from xml is: " + 
765
                                        text.toString(), 40);
766
    MetaCatUtil.debugMessage("node data from stack: " +
767
                                        node.getNodeData(), 40);
768
    MetaCatUtil.debugMessage("node name from stack: " +
769
                                        node.getNodeName(), 40);
770
    MetaCatUtil.debugMessage("node is: "+ node.getNodeId(), 40);              
771
    if (!node.getNodeType().equals("TEXT") || 
772
        !(text.toString()).equals(node.getNodeData())) 
773
    { 
774
      MetaCatUtil.debugMessage("Inconsistence happend: ", 40);
775
      MetaCatUtil.debugMessage("current node type from xml is TEXT in start element", 40);
776
      MetaCatUtil.debugMessage("node type from stack: " + 
777
                                        node.getNodeType(), 40);
778
      MetaCatUtil.debugMessage("current node data from xml is: " + 
779
                                        text.toString(), 40);
780
      MetaCatUtil.debugMessage("node data from stack: " +
781
                                        node.getNodeData(), 40);
782
      MetaCatUtil.debugMessage("node name from stack: " +
783
                                        node.getNodeName(), 40);
784
      MetaCatUtil.debugMessage("node is: "+ node.getNodeId(), 40);
785
      throw new SAXException(error);
786
    }//if
787
  } 
788
  /** SAX Handler that is called at the end of each XML element */
789
   public void endElement(String uri, String localName,
790
                          String qName) throws SAXException 
791
  {
792
     MetaCatUtil.debugMessage("End ELEMENT " + qName, 50);
793

    
794
     // Get the node from the stack
795
     DBSAXNode currentNode = (DBSAXNode)nodeStack.pop();
796
     String currentTag = currentNode.getTagName();
797
    
798
     // If before the end element, the parser hit text nodes and store them
799
     // into the buffer, write the buffer to data base. The reason we put
800
     // write database here is for xerces some time split text node
801
     if (hitTextNode)
802
     {
803
        // get access value
804
        String data = null;
805
        // add principal
806
       if (currentTag.equals(PRINCIPAL) && accessRule != null) 
807
       {
808
          data = (textBuffer.toString()).trim();
809
          accessRule.addPrincipal(data);
810

    
811
       } 
812
       else if (currentTag.equals(PERMISSION) && accessRule != null) 
813
       {
814
         data = (textBuffer.toString()).trim();
815
         // we conbine different a permission into one value
816
         int permission = accessRule.getPermission();
817
         // add permision
818
         if ( data.toUpperCase().equals(READSTRING) ) 
819
         {
820
           permission = permission | READ;
821
         } 
822
         else if ( data.toUpperCase().equals(WRITESTRING) ) 
823
         {
824
           permission = permission | WRITE;
825
         } 
826
         else if ( data.toUpperCase().equals(CHMODSTRING)) 
827
         {
828
           permission = permission | CHMOD;
829
         } 
830
         else if ( data.toUpperCase().equals(ALLSTRING) ) 
831
         {
832
          permission = permission | ALL;
833
         }
834
         accessRule.setPermission(permission);
835
       }
836
       // put additionalmetadata/describes into vector
837
       else if (currentTag.equals(DESCRIBES))
838
       {
839
          data = (textBuffer.toString()).trim();
840
          describesId.add(data);
841
       }
842
       else if (currentTag.equals(REFERENCES) && 
843
               (processTopLeverAccess ||
844
                processAdditionalAccess || processOtherAccess))
845
       {
846
         // get reference 
847
         data = (textBuffer.toString()).trim();
848
         // put reference id into accessSection
849
         accessObject.setReferences(data);
850
         
851
       }
852
       else if (currentTag.equals(URL))
853
       {
854
         //handle online data, make sure its'parent is online
855
         DBSAXNode parentNode = (DBSAXNode)nodeStack.peek();
856
         if (parentNode != null && parentNode.getTagName()!= null &&
857
             parentNode.getTagName().equals(ONLINE))
858
         {
859
            // if online data is in local metacat, add it to the vector
860
            data = (textBuffer.toString()).trim();
861
            if (data != null && 
862
                (data.indexOf(MetaCatUtil.getOption("httpserver")) != -1 || 
863
                data.indexOf(MetaCatUtil.getOption("server")) != -1))
864
            {
865
              // Get docid from url
866
              String dataId =MetaCatUtil.getDocIdWithRevFromOnlineURL(data);
867
              // add to vector
868
              onlineDataFileIdVector.add(dataId);             
869
            }//if
870
          }//if
871
       }//else if
872
       // write text to db if it is not inline data
873
       if (!localName.equals(INLINE))
874
       {
875
          MetaCatUtil.debugMessage("Write text into DB in End Element", 50);
876
          //compare text node if need
877
          if (startCriticalSubTree)
878
          {
879
            compareTextNode(currentUnChangedableSubtreeNodeStack, textBuffer, 
880
                            PERMISSIONERROR);
881
          }//if
882
          //compare top level access module
883
          if (processTopLeverAccess && needCheckingAccessModule)
884
          {
885
             compareTextNode(currentUnchangableAccessModuleNodeStack, 
886
                            textBuffer, UPDATEACCESSERROR);
887
          }
888
          // write text node into db
889
          endNodeId = writeTextForDBSAXNode(textBuffer, currentNode);
890
       }
891
       else
892
       {
893
          MetaCatUtil.debugMessage("Write inline data into file system", 35);
894
          
895
          //check if user changed inine data or not if user doesn't have
896
          // write permission
897
          if (startCriticalSubTree)
898
          {
899
            NodeRecord node = null;
900
            String inlineData;
901
            try
902
            {
903
              node = (NodeRecord)currentUnChangedableSubtreeNodeStack.pop();
904
              // get file name from db
905
              String fileName = node.getNodeData();
906
              MetaCatUtil.debugMessage("in handle inline data", 35);
907
              MetaCatUtil.debugMessage("the inline data file name from node is: "+
908
                                      fileName, 40);
909
              inlineData = readInlineDataFromFileSystem(fileName);
910
            }
911
            catch (EmptyStackException ee)
912
            {
913
              MetaCatUtil.debugMessage("the stack is empty for text data", 32);
914
              throw new SAXException(PERMISSIONERROR);
915
            }
916
            catch (McdbException eee)
917
            {
918
              throw new SAXException(eee.getMessage());
919
            }
920
            
921
            if (!(textBuffer.toString()).equals(inlineData))
922
            {
923
              MetaCatUtil.debugMessage("inline data was changed by a user" +
924
                                       " who doesn't have permission", 30);
925
              throw new SAXException(PERMISSIONERROR);
926
            }//if
927
          }//if
928
          // write inline data into file system and return file name
929
          textBuffer = writeInlineDataIntoFile(textBuffer);
930
          // write file name into db
931
          endNodeId = writeTextForDBSAXNode(textBuffer, currentNode);
932
       }
933
       
934
       if (needCheckingAccessModule && 
935
       (processAdditionalAccess || processOtherAccess || processTopLeverAccess))
936
       {
937
        // stored the pull out nodes into storedNode stack
938
        NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "TEXT", 
939
                      null, null, MetaCatUtil.normalize(textBuffer.toString()));
940
        storedAccessNodeStack.push(nodeElement);
941
                                         
942
      }
943
     }//if
944
     
945
     //end crtical subtree(user doesn't have permission to write)
946
     //When reach the first element and stack is empty
947
     if (localName.equals(firstElementNameForCriticalSubTree) && 
948
         currentUnChangedableSubtreeNodeStack.isEmpty()) 
949
     {
950
       startCriticalSubTree = false;
951
     }
952
     
953
     
954
     //set hitText false
955
     hitTextNode = false;
956
     // reset textbuff
957
     textBuffer = null;
958
     textBuffer = new StringBuffer();
959
     
960
     // hand sub stree stuff
961
     if (!subTreeInfoStack.empty())
962
     {
963
       SubTree tree = (SubTree)subTreeInfoStack.peek();// get last subtree
964
       if (tree != null && tree.getStartElementName() != null && 
965
         (tree.getStartElementName()).equals(currentTag))
966
       {
967
         // find the end of sub tree and set the end node id
968
         tree.setEndNodeId(endNodeId);
969
         // add the subtree into the final store palace
970
         subTreeList.add(tree);
971
         // get rid of it from stack
972
         subTreeInfoStack.pop();
973
       }//if
974
     }//if
975

    
976
     // access stuff
977
     if (currentTag.equals(ALLOW) || currentTag.equals(DENY))
978
     {
979
       // finish parser a ccess rule and  assign it to new one
980
       AccessRule newRule = accessRule;
981
       //add the new rule to access section object
982
       accessObject.addAccessRule(newRule);
983
       // reset access rule
984
       accessRule = null;
985
     }
986
     else if (currentTag.equals(ACCESS))
987
     {
988
       // finish parse a access setction and assign it to new one
989
      
990
       accessObject.setEndNodeId(endNodeId);
991
       AccessSection newAccessObject = accessObject;
992
    
993
       if (newAccessObject != null)
994
       {
995
       
996
        // add the accessSection into a vector to store it
997
        // if it is not a reference, need to store it
998
        if ( newAccessObject.getReferences() == null)
999
        {
1000
          
1001
          newAccessObject.setStoredTmpNodeStack(storedAccessNodeStack);
1002
          accessObjectList.add(newAccessObject);
1003
        }
1004
        if (processTopLeverAccess)
1005
        {
1006
          
1007
          // top level access control will handle whole document -docid
1008
          topLevelAccessControlMap.put(docid, newAccessObject);
1009
          // reset processtopleveraccess tag
1010
          
1011
        }//if
1012
        else if (processAdditionalAccess)
1013
        {
1014
          // for additional control
1015
          // put everything in describes value and access object into hash
1016
          for ( int i=0; i<describesId.size(); i++)
1017
          {
1018
           
1019
            String subId = (String)describesId.elementAt(i);
1020
            if (subId != null)
1021
            {
1022
              additionalAccessControlMap.put(subId, newAccessObject);
1023
            }//if
1024
          }//for
1025
          // add this hashtable in to vector
1026
         
1027
          additionalAccessMapList.add(additionalAccessControlMap);
1028
          // reset this hashtable in order to store another additional 
1029
          //accesscontrol
1030
          additionalAccessControlMap = null;
1031
          additionalAccessControlMap = new Hashtable();
1032
        }//if
1033
       
1034
       }//if
1035
       //check if  access node stack is empty after parsing top access
1036
       //module
1037
      
1038
       if (needCheckingAccessModule && processTopLeverAccess && 
1039
           !currentUnchangableAccessModuleNodeStack.isEmpty())
1040
       {
1041
         
1042
         MetaCatUtil.debugMessage("Access node stack is not empty after " + 
1043
                                   "parsing access subtree", 40);
1044
         throw new SAXException(UPDATEACCESSERROR);
1045
                                  
1046
       }
1047
       //reset access section object
1048
      
1049
       accessObject = null;
1050
     
1051
       // reset tmp stored node stack
1052
       storedAccessNodeStack = null;
1053
       storedAccessNodeStack = new Stack();
1054
    
1055
       // reset flag
1056
       processAdditionalAccess =false;
1057
       processTopLeverAccess =false;
1058
       processOtherAccess = false;
1059
      
1060
     }
1061
     else if (currentTag.equals(ADDITIONALMETADATA))
1062
     {
1063
        //reset describesId
1064
        describesId = null;
1065
        describesId = new Vector();
1066
     }
1067
    
1068
   }
1069
   
1070
   /**
1071
    * SAX Handler that receives notification of comments in the DTD
1072
    */
1073
   public void comment(char[] ch, int start, int length) throws SAXException {
1074
     MetaCatUtil.debugMessage("COMMENT", 50);
1075
     if ( !processingDTD ) 
1076
     {
1077
       DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
1078
       String str = new String(ch, start, length);
1079
       
1080
       //compare comment if need
1081
       if (startCriticalSubTree)
1082
       {
1083
         compareCommentNode(currentUnChangedableSubtreeNodeStack, str, 
1084
                            PERMISSIONERROR);
1085
       }//if
1086
       //compare top level access module
1087
       if (processTopLeverAccess && needCheckingAccessModule)
1088
       {
1089
         compareCommentNode(currentUnchangableAccessModuleNodeStack, str,
1090
                            UPDATEACCESSERROR);
1091
       }
1092
       endNodeId = currentNode.writeChildNodeToDB("COMMENT", null, str, docid);
1093
       if (needCheckingAccessModule && 
1094
       (processAdditionalAccess || processOtherAccess || processTopLeverAccess))
1095
       {
1096
        // stored the pull out nodes into storedNode stack
1097
        NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "COMMENT", 
1098
                                        null, null, MetaCatUtil.normalize(str));
1099
        storedAccessNodeStack.push(nodeElement);
1100
                                         
1101
      }
1102
     }
1103
   }
1104
   
1105
   /* Comparet comment from xml and db */
1106
   private void compareCommentNode(Stack nodeStack, String string, String error)
1107
                                   throws SAXException
1108
   {
1109
     NodeRecord node = null;
1110
     try
1111
     {
1112
       node = (NodeRecord)nodeStack.pop();
1113
     }
1114
     catch (EmptyStackException ee)
1115
     {
1116
       MetaCatUtil.debugMessage("the stack is empty for comment data", 32);
1117
       throw new SAXException(error);
1118
     }
1119
     MetaCatUtil.debugMessage("current node type from xml is COMMENT", 40);
1120
     MetaCatUtil.debugMessage("node type from stack: " + 
1121
                                    node.getNodeType(), 40);
1122
     MetaCatUtil.debugMessage("current node data from xml is: " + 
1123
                                    string, 40);
1124
     MetaCatUtil.debugMessage("node data from stack: " +
1125
                                    node.getNodeData(), 40);
1126
     MetaCatUtil.debugMessage("node is from stack: " + 
1127
                                    node.getNodeId(), 40);
1128
     // if not consistent terminate program and throw a exception
1129
     if (!node.getNodeType().equals("COMMENT") || 
1130
         !string.equals(node.getNodeData())) 
1131
     { 
1132
       MetaCatUtil.debugMessage("Inconsistence happend: ", 40);
1133
       MetaCatUtil.debugMessage("current node type from xml is COMMENT", 40);
1134
       MetaCatUtil.debugMessage("node type from stack: " + 
1135
                                    node.getNodeType(), 40);
1136
       MetaCatUtil.debugMessage("current node data from xml is: " + 
1137
                                    string, 40);
1138
       MetaCatUtil.debugMessage("node data from stack: " +
1139
                                    node.getNodeData(), 40);
1140
       MetaCatUtil.debugMessage("node is from stack: " + 
1141
                                        node.getNodeId(), 40);
1142
       throw new SAXException(error);
1143
     }//if
1144
   }
1145
   
1146
      /**
1147
    * SAX Handler that is called for each XML text node that is
1148
    * Ignorable white space
1149
    */
1150
   public void ignorableWhitespace(char[] cbuf, int start, int len)
1151
               throws SAXException 
1152
  {
1153
     // When validation is turned "on", white spaces are reported here
1154
     // When validation is turned "off" white spaces are not reported here,
1155
     // but through characters() callback
1156
     MetaCatUtil.debugMessage("IGNORABLEWHITESPACE", 50);
1157
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
1158
     String data = null;
1159
     int leftover = len;
1160
     int offset = start;
1161
     boolean moredata = true;
1162

    
1163
     // This loop deals with the case where there are more characters
1164
     // than can fit in a single database text field (limit is
1165
     // MAXDATACHARS).  If the text to be inserted exceeds MAXDATACHARS,
1166
     // write a series of nodes that are MAXDATACHARS long, and then the
1167
     // final node contains the remainder
1168
     while (moredata) 
1169
     {
1170
       if (leftover > MAXDATACHARS) 
1171
       {
1172
         data = new String(cbuf, offset, MAXDATACHARS);
1173
         leftover -= MAXDATACHARS;
1174
         offset += MAXDATACHARS;
1175
       } 
1176
       else 
1177
       {
1178
         data = new String(cbuf, offset, leftover);
1179
         moredata = false;
1180
       }
1181

    
1182
       //compare whitespace if need
1183
       if (startCriticalSubTree)
1184
       {
1185
         compareWhiteSpace(currentUnChangedableSubtreeNodeStack, data, 
1186
                           PERMISSIONERROR);
1187
       }//if
1188
       
1189
       //compare whitespace in access top module
1190
       if (processTopLeverAccess && needCheckingAccessModule)
1191
       {
1192
         compareWhiteSpace(currentUnchangableAccessModuleNodeStack, data, 
1193
                           UPDATEACCESSERROR);
1194
       }
1195
       // Write the content of the node to the database
1196
       if (needCheckingAccessModule && 
1197
       (processAdditionalAccess || processOtherAccess || processTopLeverAccess))
1198
       {
1199
        // stored the pull out nodes into storedNode stack
1200
        NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "TEXT", 
1201
                                     null, null, MetaCatUtil.normalize(data));
1202
        storedAccessNodeStack.push(nodeElement);
1203
                                         
1204
       }
1205
       endNodeId = currentNode.writeChildNodeToDB("TEXT", null, data, docid);
1206
     }
1207
   }
1208
   
1209
   /* Compare whitespace from xml and db */
1210
   private void compareWhiteSpace(Stack nodeStack, String string, String error)
1211
                                  throws SAXException
1212
   {
1213
      NodeRecord node = null;
1214
      try
1215
      {
1216
        node = (NodeRecord)nodeStack.pop();
1217
      }
1218
      catch (EmptyStackException ee)
1219
      {
1220
        MetaCatUtil.debugMessage("the stack is empty for whitespace data", 32);
1221
        throw new SAXException(error);
1222
      }
1223
      if (!node.getNodeType().equals("TEXT") || 
1224
          !string.equals(node.getNodeData())) 
1225
      { 
1226
        MetaCatUtil.debugMessage("Inconsistence happend: ", 40);
1227
        MetaCatUtil.debugMessage("current node type from xml is WHITESPACE TEXT", 40);
1228
        MetaCatUtil.debugMessage("node type from stack: " + 
1229
                                  node.getNodeType(), 40);
1230
        MetaCatUtil.debugMessage("current node data from xml is: " + 
1231
                                  string, 40);
1232
        MetaCatUtil.debugMessage("node data from stack: " +
1233
                                  node.getNodeData(), 40);
1234
        MetaCatUtil.debugMessage("node is from stack: " + 
1235
                                  node.getNodeId(), 40);
1236
        throw new SAXException(error);
1237
     }//if
1238
   }
1239
   
1240
   /** SAX Handler that receives notification of end of the document */
1241
   public void endDocument() throws SAXException 
1242
   {
1243
     MetaCatUtil.debugMessage("end Document", 50);
1244
     // There are some unchangable subtree didn't be compare
1245
     // This maybe cause user change the subtree id
1246
     if (!unChangableSubTreeHash.isEmpty())
1247
     {
1248
       MetaCatUtil.debugMessage("The unChangealbe subtree is not empty", 40);
1249
       throw new SAXException(PERMISSIONERROR);
1250
     }
1251
     
1252
     // write access rule to db
1253
     writeAccessRuleToDB();
1254
     
1255
     //delete relation table
1256
     deleteRelations();
1257
     //write relations
1258
     for (int i= 0; i<onlineDataFileIdVector.size(); i++)
1259
     {
1260
       String id = (String)onlineDataFileIdVector.elementAt(i);
1261
       writeOnlineDataFileIdIntoRelationTable(id);
1262
     }
1263
   
1264
     // Starting new thread for writing XML Index.
1265
     // It calls the run method of the thread.
1266
     try 
1267
     {
1268
       xmlIndex.start();
1269
     } 
1270
     catch (NullPointerException e) 
1271
     {
1272
       xmlIndex = null;
1273
       throw new
1274
       SAXException("Problem with starting thread for writing XML Index. " +
1275
                    e.getMessage());
1276
     }
1277
   
1278
   }
1279
   
1280
  /* The method to write all access rule intodb */
1281
  private void writeAccessRuleToDB() throws SAXException
1282
  {
1283
    //Delete old permssion
1284
    deletePermissionsInAccessTable(docid);
1285
    //write top leve access rule
1286
    writeTopLevelAccessRuleToDB();
1287
    //write additional access rule
1288
    //writeAddtionalAccessRuleToDB();
1289
  }//writeAccessRuleToDB
1290
   
1291
  /* The method to write top level access rule into db. */
1292
  private void writeTopLevelAccessRuleToDB() throws SAXException
1293
  {
1294
    
1295
    // for top document level
1296
    Object accessSection = topLevelAccessControlMap.get(docid);
1297
    boolean top = true;
1298
    String subSectionId = null;
1299
    if ( accessSection != null )
1300
    {
1301
       AccessSection accessSectionObj = (AccessSection)accessSection;
1302
           
1303
       // if accessSection is not null and is not reference
1304
       if ( accessSectionObj.getReferences() == null)
1305
       {
1306
          // write the top level access module into xml_accesssubtree to store info
1307
          // and then when update to check if the user can update it or not
1308
          deleteAccessSubTreeRecord(docid);
1309
          writeAccessSubTreeIntoDB(accessSectionObj,TOPLEVEL);
1310
          //write access section into xml_access table
1311
          writeGivenAccessRuleIntoDB(accessSectionObj, top, subSectionId);
1312
       }
1313
       else
1314
       {
1315
   
1316
        // this is a reference and go trough the vector which contains all
1317
        // access object
1318
        String referenceId = accessSectionObj.getReferences();
1319
        boolean findAccessObject = false;
1320
        MetaCatUtil.debugMessage("referered id for top access: "+ 
1321
                               referenceId, 35);
1322
        for (int i=0; i<accessObjectList.size(); i++)
1323
        {
1324
          AccessSection accessObj = (AccessSection)accessObjectList.elementAt(i);
1325
          String accessObjId = accessObj.getSubTreeId();
1326
          if (referenceId != null && accessObj != null &&
1327
              referenceId.equals(accessObjId))
1328
          {
1329
            // make sure the user didn't change any thing in this access moduel
1330
            // too if user doesn't have all permission
1331
            if (needCheckingAccessModule)
1332
            {
1333
              
1334
              Stack newStack = accessObj.getStoredTmpNodeStack();
1335
              //revise order
1336
              newStack = MetaCatUtil.reviseStack(newStack);
1337
               // go throught the vector of unChangableAccessSubtreevector
1338
              // and find the one whose id is as same as referenceid
1339
              AccessSection oldAccessObj = 
1340
                       getAccessSectionFromUnchangableAccessVector(referenceId);
1341
              //if oldAccessObj is null something is wrong
1342
              if (oldAccessObj == null)
1343
              {
1344
                throw new SAXException(UPDATEACCESSERROR);
1345
              }//if
1346
              else
1347
              {
1348
                // Get the node stack from old access obj
1349
                Stack oldStack = oldAccessObj.getSubTreeNodeStack();
1350
                comparingNodeStacks(newStack, oldStack);
1351
              }//else
1352
            }//if
1353
            
1354
            writeGivenAccessRuleIntoDB(accessObj, top, subSectionId);
1355
            //write the reference access into xml_accesssubtree too
1356
             // write the top level access module into xml_accesssubtree to store info
1357
             // and then when update to check if the user can update it or not
1358
            deleteAccessSubTreeRecord(docid);
1359
            writeAccessSubTreeIntoDB(accessSectionObj,TOPLEVEL);
1360
            writeAccessSubTreeIntoDB(accessObj, SUBTREELEVEL);
1361
            findAccessObject = true;
1362
            break;
1363
          }
1364
        }//for
1365
        // if we couldn't find an access subtree id for this reference id
1366
        if (!findAccessObject)
1367
        {
1368
          throw new SAXException("The referenceid: " + referenceId +
1369
                               " is not access subtree");
1370
        }//if
1371
      }//else
1372
      
1373
     
1374
    }//if
1375
    else
1376
    {
1377
      // couldn't find a access section object 
1378
      MetaCatUtil.debugMessage("couldn't find access control for document: "+
1379
                                docid, 35);
1380
    }
1381
    
1382
  }//writeTopLevelAccessRuletoDB
1383
  
1384
  /* Given a subtree id and find the responding access section*/
1385
  private AccessSection getAccessSectionFromUnchangableAccessVector(String id)
1386
  {
1387
    AccessSection result = null;
1388
    // Makse sure the id
1389
    if (id == null || id.equals(""))
1390
    {
1391
      return result;
1392
    }
1393
    // go throught vector and find the list
1394
    for (int i=0; i<unChangableAccessSubTreeVector.size();i++)
1395
    {
1396
      AccessSection accessObj = (AccessSection)
1397
                                 unChangableAccessSubTreeVector.elementAt(i);
1398
      if (accessObj.getSubTreeId() != null && 
1399
         (accessObj.getSubTreeId()).equals(id))
1400
      {
1401
        result = accessObj;
1402
      }//if
1403
    }//for
1404
    return result;
1405
  }//getAccessSectionFromUnchangableAccessVector
1406
      
1407
  /* Compare two node stacks to see if they are same */
1408
  private void comparingNodeStacks(Stack stack1, Stack stack2) 
1409
                                 throws SAXException
1410
  {
1411
    // make sure stack1 and stack2 are not empty
1412
    if (stack1.isEmpty() || stack2.isEmpty())
1413
    {
1414
      MetaCatUtil.debugMessage("Because stack is empty!", 35);
1415
      throw new SAXException(UPDATEACCESSERROR);
1416
    }
1417
    // go throw two stacks and compare every element
1418
    while (!stack1.isEmpty())
1419
    {
1420
      // Pop an element from stack1
1421
      NodeRecord record1 = (NodeRecord) stack1.pop();
1422
      // Pop an element from stack2(stack 2 maybe empty)
1423
      NodeRecord record2 = null;
1424
      try
1425
      {
1426
        record2 = (NodeRecord) stack2.pop();
1427
      }
1428
      catch (EmptyStackException ee)
1429
      {
1430
        MetaCatUtil.debugMessage("Node stack2 is empty but stack1 isn't!", 35);
1431
        throw new SAXException(UPDATEACCESSERROR);
1432
      }
1433
      // if two records are not same throw a exception
1434
      if (!record1.contentEquals(record2))
1435
      {
1436
        MetaCatUtil.debugMessage("Two records from new and old stack are not "+
1437
                                 "same!", 30);
1438
        throw new SAXException(UPDATEACCESSERROR);
1439
      }//if
1440
    }//while
1441
    
1442
    // now stack1 is empty and we should make sure stack2 is empty too
1443
    if(!stack2.isEmpty())
1444
    {
1445
      MetaCatUtil.debugMessage("stack2 still have some elements while stack "+
1446
                               "is empty! ", 30);
1447
      throw new SAXException(UPDATEACCESSERROR);
1448
    }//if
1449
 }//comparingNodeStacks
1450
  
1451
   /* The method to write addtional access rule into db. */
1452
  private void writeAddtionalAccessRuleToDB() throws SAXException
1453
  {
1454
    
1455
     PreparedStatement pstmt = null;
1456
     boolean topLevel =false;
1457
    // go through the vector which contains the additional access control 
1458
    //hashtable. Each hashtable has info for one additonalmetadata container 
1459
   for (int j= 0; j < additionalAccessMapList.size(); j++)
1460
   {
1461
     
1462
     Hashtable accessControlMap = 
1463
                                (Hashtable)additionalAccessMapList.elementAt(j);
1464
     // additional access rule
1465
     Enumeration en = accessControlMap.keys();
1466
     
1467
     while(en.hasMoreElements())
1468
     {
1469
       try
1470
       {
1471
         // Get subsection id
1472
          String subSectionId = (String)en.nextElement();
1473
          MetaCatUtil.debugMessage("sub section id in additional access mapping"
1474
                                   +"(go through): "+ subSectionId, 35);
1475
          
1476
          if (subSectionId == null)
1477
          {
1478
            // if id is null, terminate the program
1479
            throw new SAXException("subtree id is null");
1480
          }
1481
          // Get AccessSection Object
1482
          Object accessSectionObj = accessControlMap.get(subSectionId);
1483
          if (accessSectionObj == null)
1484
          {
1485
            // if accesssection is null, terminate the program
1486
            throw new SAXException("access subtree is null");
1487
          }
1488
          else
1489
          {
1490
            AccessSection accessControlObj = (AccessSection)accessSectionObj;
1491
            // if the access section is not references, write it to db
1492
            if (accessControlObj.getReferences() == null)
1493
            {
1494
              writeGivenAccessRuleIntoDB(accessControlObj, topLevel, 
1495
                                         subSectionId);
1496
            }
1497
            else
1498
            {
1499
              // this is a reference and go trough the vector which contains all
1500
              // access object
1501
              String referenceId = accessControlObj.getReferences();
1502
            
1503
              boolean findAccessObject = false;
1504
              MetaCatUtil.debugMessage("referered id for additional access "+
1505
                                     "mapping(go through): "+ referenceId, 35);
1506
              for (int i=0; i<accessObjectList.size(); i++)
1507
              {
1508
                AccessSection accessObj = 
1509
                                (AccessSection)accessObjectList.elementAt(i);
1510
                String accessObjId = accessObj.getSubTreeId();
1511
                MetaCatUtil.debugMessage("access obj id in the list(go through): "
1512
                                        + accessObjId, 35);
1513
                if (referenceId != null && accessObj != null &&
1514
                    referenceId.equals(accessObjId))
1515
                {
1516
                  writeGivenAccessRuleIntoDB(accessObj, topLevel, subSectionId);
1517
                  findAccessObject = true;
1518
                }//if
1519
              }//for
1520
              // if we couldn't find an access subtree id for this reference id
1521
              if (!findAccessObject)
1522
              {
1523
                throw new SAXException("The referenceid: " + referenceId +
1524
                               " is not access subtree");
1525
              }//if
1526
            }//else
1527
          }//else
1528
       }//try
1529
       catch (Exception e)
1530
       {
1531
         
1532
         MetaCatUtil.debugMessage("error in EmlSAXHandler.writeAddtionalAccess"
1533
                                   + ": "+e.getMessage(), 30);
1534
         throw new SAXException(e.getMessage());
1535
       }
1536
     }//while
1537
    }//for
1538
  }//writeAccessRuletoDB
1539
  
1540
  /* Write a gaven access rule into db*/
1541
  private void writeGivenAccessRuleIntoDB(AccessSection accessSection, 
1542
                                         boolean topLevel, String subSectionId) 
1543
                                         throws SAXException
1544
  {
1545
     if (accessSection == null)
1546
     {
1547
       throw new SAXException("The access object is null");
1548
     }
1549
     
1550
      String permOrder = accessSection.getPermissionOrder();
1551
      String sql = null;
1552
      PreparedStatement pstmt = null;
1553
      if (topLevel)
1554
      {
1555
        sql = "INSERT INTO xml_access (docid, principal_name, permission, "+
1556
                 "perm_type, perm_order, accessfileid) VALUES " +
1557
                 " (?, ?, ?, ?, ?, ?)";
1558
      }
1559
      else
1560
      {
1561
        sql ="INSERT INTO xml_access (docid,principal_name, "+ 
1562
             "permission, perm_type, perm_order, accessfileid, subtreeid, "+
1563
             " startnodeid, endnodeid) VALUES" +
1564
             " (?, ?, ?, ?, ?, ?, ?, ?, ?)";
1565
      }
1566
      try 
1567
      {
1568
     
1569
        pstmt = connection.prepareStatement(sql);
1570
        // Increase DBConnection usage count
1571
        connection.increaseUsageCount(1);
1572
        // Bind the values to the query
1573
        pstmt.setString(1, docid);
1574
        MetaCatUtil.debugMessage("Docid in accesstable: "+ docid, 35);
1575
        pstmt.setString(6, docid);
1576
        MetaCatUtil.debugMessage("Accessfileid in accesstable: "+ docid, 35);
1577
        pstmt.setString(5, permOrder);
1578
        MetaCatUtil.debugMessage("PermOder in accesstable: "+ permOrder, 35);
1579
        // if it is not top level, set subsection id
1580
        if (!topLevel)
1581
        {
1582
          long startNodeId = 0;
1583
          long endNodeId = 0;
1584
          // for subtree should specify the
1585
          if (subSectionId == null)
1586
          {
1587
            throw new SAXException("The subsection is null");
1588
          }
1589
          // go through the substree list vector and found the start node id
1590
          // and stop node id for this subtree id
1591
          for (int i=0; i<subTreeList.size(); i++)
1592
          {
1593
            SubTree tree = (SubTree)subTreeList.elementAt(i);
1594
            String subTreeId = tree.getSubTreeId();
1595
            if (subSectionId.equals(subTreeId))
1596
            {
1597
              startNodeId = tree.getStartNodeId();
1598
              endNodeId = tree.getEndNodeId(); 
1599
            }//if
1600
          }//for
1601
          if (startNodeId == 0 || endNodeId == 0)
1602
          {
1603
            throw new SAXException("Could find the subtree"
1604
                                   + "for this id: "+subSectionId);
1605
          }
1606
          pstmt.setString(7, subSectionId);
1607
          MetaCatUtil.debugMessage("SubSectionId in accesstable: "+ 
1608
                                    subSectionId, 35);
1609
          pstmt.setLong(8, startNodeId);
1610
          MetaCatUtil.debugMessage("Start node id is: " + startNodeId, 35);
1611
          pstmt.setLong(9, endNodeId);
1612
          MetaCatUtil.debugMessage("End node id is: " + endNodeId, 35);
1613
          
1614
        }
1615
      
1616
        Vector accessRules = accessSection.getAccessRules();
1617
        // go through every rule
1618
        for (int i=0; i<accessRules.size(); i++)
1619
        {
1620
          AccessRule rule = (AccessRule)accessRules.elementAt(i);
1621
          String permType = rule.getPermissionType();
1622
          int permission = rule.getPermission();
1623
          pstmt.setInt(3, permission);
1624
          MetaCatUtil.debugMessage("permission in accesstable: "+ permission, 35);
1625
          pstmt.setString(4, permType);
1626
          MetaCatUtil.debugMessage("Permtype in accesstable: "+ permType, 35);
1627
          // go through every principle in rule
1628
          Vector nameVector = rule.getPrincipal();
1629
          for ( int j = 0; j < nameVector.size(); j++ ) 
1630
          {
1631
            String prName = (String)nameVector.elementAt(j);
1632
            pstmt.setString(2, prName);
1633
            MetaCatUtil.debugMessage("Principal in accesstable: "+prName, 35);
1634
            pstmt.execute();
1635
          }//for
1636
        }//for
1637
        pstmt.close();
1638
      }//try 
1639
      catch (SQLException e) 
1640
      {
1641
        throw new 
1642
        SAXException("EMLSAXHandler.writeAccessRuletoDB(): " + e.getMessage());
1643
      }//catch
1644
      finally
1645
      {
1646
        try
1647
        {
1648
          pstmt.close();
1649
        }
1650
        catch(SQLException ee)
1651
        {
1652
          throw new 
1653
          SAXException("EMLSAXHandler.writeAccessRuletoDB(): " + 
1654
          ee.getMessage());
1655
        }
1656
      }//finally
1657
     
1658
  }//writeGivenAccessRuleIntoDB
1659
  
1660
  /* Delete from db all permission for resources related to @aclid if any.*/
1661
  private void deletePermissionsInAccessTable(String aclid) 
1662
          throws SAXException 
1663
  {
1664
    Statement stmt = null;
1665
    try
1666
    {
1667
      // delete all acl records for resources related to @aclid if any
1668
      stmt = connection.createStatement();
1669
      // Increase DBConnection usage count
1670
      connection.increaseUsageCount(1);
1671
      stmt.execute("DELETE FROM xml_access WHERE accessfileid = '" + aclid +
1672
                   "'"); 
1673
    
1674
    }
1675
    catch (SQLException e)
1676
    {
1677
      throw new SAXException(e.getMessage());
1678
    }
1679
    finally
1680
    {
1681
      try
1682
      {
1683
        stmt.close();
1684
      }
1685
      catch (SQLException ee)
1686
      {
1687
        throw new SAXException(ee.getMessage());
1688
      }
1689
    }
1690
  }//deletePermissionsInAccessTable
1691
  
1692
  
1693
  /* In order to make sure only usr has "all" permission can update access
1694
   * subtree in eml document we need to keep access subtree info in 
1695
   * xml_accesssubtree table, such as docid, version, startnodeid, endnodeid
1696
   */
1697
  private void writeAccessSubTreeIntoDB(AccessSection accessSection, 
1698
                                         String level) 
1699
                                         throws SAXException
1700
  {
1701
     if (accessSection == null)
1702
     {
1703
       throw new SAXException("The access object is null");
1704
     }
1705
     
1706
      String sql = null;
1707
      PreparedStatement pstmt = null;
1708
      sql = "INSERT INTO xml_accesssubtree (docid, rev, controllevel, "+
1709
                 "subtreeid, startnodeid, endnodeid) VALUES " +
1710
                 " (?, ?, ?, ?, ?, ?)";
1711
      try 
1712
      {
1713
     
1714
        pstmt = connection.prepareStatement(sql);
1715
        // Increase DBConnection usage count
1716
        connection.increaseUsageCount(1);
1717
        long startNodeId = accessSection.getStartNodeId();
1718
        long endNodeId = accessSection.getEndNodeId();
1719
        String sectionId = accessSection.getSubTreeId();
1720
        // Bind the values to the query
1721
        pstmt.setString(1, docid);
1722
        MetaCatUtil.debugMessage("Docid in access-subtreetable: "+ docid, 35);
1723
        pstmt.setString(2, revision );
1724
        MetaCatUtil.debugMessage("rev in accesssubtreetable: "+ revision, 35);
1725
        pstmt.setString(3, level);
1726
        MetaCatUtil.debugMessage("contorl level in access-subtree table: "+
1727
                                  level, 35);
1728
        pstmt.setString(4, sectionId);
1729
        MetaCatUtil.debugMessage("Subtree id in access-subtree table: "+ 
1730
                                  sectionId, 35);
1731
        pstmt.setLong(5, startNodeId);
1732
        MetaCatUtil.debugMessage("Start node id is: " + startNodeId, 35);
1733
        pstmt.setLong(6, endNodeId);
1734
        MetaCatUtil.debugMessage("End node id is: " + endNodeId, 35);
1735
        pstmt.execute();
1736
        pstmt.close();
1737
      }//try 
1738
      catch (SQLException e) 
1739
      {
1740
        throw new 
1741
        SAXException("EMLSAXHandler.writeAccessSubTreeIntoDB(): " + 
1742
                      e.getMessage());
1743
      }//catch
1744
      finally
1745
      {
1746
        try
1747
        {
1748
          pstmt.close();
1749
        }
1750
        catch(SQLException ee)
1751
        {
1752
          throw new 
1753
          SAXException("EMLSAXHandler.writeAccessSubTreeIntoDB(): " + 
1754
          ee.getMessage());
1755
        }
1756
      }//finally
1757
     
1758
  }//writeAccessSubtreeIntoDB
1759
  
1760
   /* Delete every access subtree record from xml_accesssubtree.*/
1761
  private void deleteAccessSubTreeRecord(String docId) throws SAXException 
1762
  {
1763
    Statement stmt = null;
1764
    try
1765
    {
1766
      // delete all acl records for resources related to @aclid if any
1767
      stmt = connection.createStatement();
1768
      // Increase DBConnection usage count
1769
      connection.increaseUsageCount(1);
1770
      stmt.execute("DELETE FROM xml_accesssubtree WHERE docid = '" + docId + "'"); 
1771
   
1772
    }
1773
    catch (SQLException e)
1774
    {
1775
      throw new SAXException(e.getMessage());
1776
    }
1777
    finally
1778
    {
1779
      try
1780
      {
1781
        stmt.close();
1782
      }
1783
      catch (SQLException ee)
1784
      {
1785
        throw new SAXException(ee.getMessage());
1786
      }
1787
    }
1788
  }//deleteAccessSubTreeRecord
1789
  
1790
  // write inline data into file system and return file name(without path)
1791
  private StringBuffer writeInlineDataIntoFile(StringBuffer data) 
1792
                                               throws SAXException
1793
  {
1794
    StringBuffer fileNameBuffer = null;
1795
    String fileName = null;
1796
    String docidWithoutRev = MetaCatUtil.getDocIdFromString(docid);
1797
    String path = MetaCatUtil.getOption("inlinedatafilepath");
1798
    String seperator = MetaCatUtil.getOption("accNumSeparator");
1799
    // the new file name will look like path/docid.rev.2
1800
    fileName = docidWithoutRev + seperator+revision+seperator +inLineDataIndex;
1801
    File inlineDataDirectory = new File(path);
1802
    File newFile = new File(inlineDataDirectory, fileName); 
1803
    // incease inLinedataindex for next one
1804
    inLineDataIndex++ ;
1805
    try
1806
    {
1807
      FileWriter writer = new FileWriter(newFile);
1808
      writer.write(data.toString());
1809
      writer.close();
1810
    }
1811
    catch (Exception e)
1812
    {
1813
      throw new SAXException(e.getMessage());
1814
    }
1815
    
1816
    fileNameBuffer = new StringBuffer(fileName);
1817
    return fileNameBuffer;
1818
  }
1819
  
1820
  /* In eml2, the inline data wouldn't store in db, it store in file system
1821
   * The db stores file name(without path).
1822
   */
1823
  public static String readInlineDataFromFileSystem(String fileName) 
1824
                                              throws McdbException
1825
  {
1826
    String data = null;
1827
    String path = MetaCatUtil.getOption("inlinedatafilepath");
1828
    // the new file name will look like path/docid.rev.2
1829
    File inlineDataDirectory = new File(path);
1830
    File dataFile = new File(inlineDataDirectory, fileName);
1831
    try
1832
    {
1833
      FileReader fileReader = new FileReader(dataFile);
1834
      BufferedReader stringReader = new BufferedReader(fileReader);
1835
      // read first line of data
1836
      String tmp = stringReader.readLine();
1837
      // pass first line data to data varible
1838
      data = tmp;
1839
      // at the end tmp will be null
1840
      while (tmp != null)
1841
      {
1842
        // read a new line
1843
        tmp = stringReader.readLine();
1844
        // append new line to data
1845
        if (tmp != null)
1846
        {
1847
          data = data+tmp;
1848
        }
1849
      }
1850
      
1851
    }
1852
    catch (Exception e)
1853
    {
1854
      throw new McdbException(e.getMessage());
1855
    }
1856
    MetaCatUtil.debugMessage("the inline data retrieve from file: "+data, 50);
1857
    return data;
1858
  }
1859
  
1860
  /* Delete relations */
1861
  private void deleteRelations() throws SAXException
1862
  {
1863
    PreparedStatement pStmt = null;
1864
    String sql = "DELETE FROM xml_relation where docid =?";
1865
    try
1866
    {
1867
      pStmt = connection.prepareStatement(sql);
1868
      //bind variable
1869
      pStmt.setString(1, docid);
1870
      //execute query
1871
      pStmt.execute();
1872
      pStmt.close();
1873
    }//try
1874
    catch (SQLException e) 
1875
    {
1876
       throw new 
1877
       SAXException("EMLSAXHandler.deleteRelations(): " + 
1878
                      e.getMessage());
1879
    }//catch
1880
    finally
1881
    {
1882
      try
1883
      {
1884
        pStmt.close();
1885
      }//try
1886
      catch(SQLException ee)
1887
      {
1888
        throw new 
1889
        SAXException("EMLSAXHandler.deleteRelations: " + 
1890
        ee.getMessage());
1891
      }//catch
1892
    }//finally
1893
  }
1894
  
1895
  /* Write an online data file id into xml_relation table*/
1896
  private void writeOnlineDataFileIdIntoRelationTable(String dataId) 
1897
                                                        throws SAXException
1898
  {
1899
    // Get rid of rev
1900
    dataId = MetaCatUtil.getDocIdFromString(dataId);
1901
    PreparedStatement pStmt = null;
1902
    String sql = "INSERT into xml_relation (docid, packagetype, subject, "+
1903
                 "relationship, object) values (?, ?, ?, ?, ?)";
1904
    try
1905
    {
1906
      pStmt = connection.prepareStatement(sql);
1907
      //bind variable
1908
      pStmt.setString(1, docid);
1909
      pStmt.setString(2, DocumentImpl.EMLNAMESPACE);
1910
      pStmt.setString(3, docid);
1911
      pStmt.setString(4, RELATION);
1912
      pStmt.setString(5, dataId);
1913
      //execute query
1914
      pStmt.execute();
1915
      pStmt.close();
1916
    }//try
1917
    catch (SQLException e) 
1918
    {
1919
       throw new 
1920
       SAXException("EMLSAXHandler.writeOnlineDataFileIdIntoRelationTable(): " + 
1921
                      e.getMessage());
1922
    }//catch
1923
    finally
1924
    {
1925
      try
1926
      {
1927
        pStmt.close();
1928
      }//try
1929
      catch(SQLException ee)
1930
      {
1931
        throw new 
1932
        SAXException("EMLSAXHandler.writeOnlineDataFileIdIntoRelationTable(): " + 
1933
        ee.getMessage());
1934
      }//catch
1935
    }//finally
1936
    
1937
  }//writeOnlineDataFileIdIntoRelationTable
1938
}
(34-34/57)