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-26 17:25:52 -0700 (Sat, 26 Apr 2003) $'
12
 * '$Revision: 1622 $'
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
        
370
         try
371
         {
372
            // Get dbconnection
373
            dbConn=DBConnectionPool.getDBConnection
374
                                          ("DBSAXHandler.startElement");
375
            serialNumber=dbConn.getCheckOutSerialNumber();
376

    
377
            Statement stmt = dbConn.createStatement();
378
            ResultSet rs = stmt.executeQuery(
379
                          "SELECT catalog_id FROM xml_catalog " +
380
                          "WHERE entry_type = 'Schema' " +
381
                          "AND public_id = '" + doctype + "'");
382
            boolean hasRow = rs.next();
383
            if ( hasRow ) 
384
            {
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 EMLSaxHandler.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
         
1311
          //write access section into xml_access table
1312
          writeGivenAccessRuleIntoDB(accessSectionObj, top, subSectionId);
1313
          // write relative online data file into xml_access too.
1314
          /*for (int i= 0; i<onlineDataFileIdVector.size(); i++)
1315
          {
1316
            String id = (String)onlineDataFileIdVector.elementAt(i);
1317
            writeAccessRuleForRalatedDataFileIntoDB(accessSectionObj, id);
1318
          }*/
1319
          
1320
       }
1321
       else
1322
       {
1323
   
1324
        // this is a reference and go trough the vector which contains all
1325
        // access object
1326
        String referenceId = accessSectionObj.getReferences();
1327
        boolean findAccessObject = false;
1328
        MetaCatUtil.debugMessage("referered id for top access: "+ 
1329
                               referenceId, 35);
1330
        for (int i=0; i<accessObjectList.size(); i++)
1331
        {
1332
          AccessSection accessObj = (AccessSection)accessObjectList.elementAt(i);
1333
          String accessObjId = accessObj.getSubTreeId();
1334
          if (referenceId != null && accessObj != null &&
1335
              referenceId.equals(accessObjId))
1336
          {
1337
            // make sure the user didn't change any thing in this access moduel
1338
            // too if user doesn't have all permission
1339
            if (needCheckingAccessModule)
1340
            {
1341
              
1342
              Stack newStack = accessObj.getStoredTmpNodeStack();
1343
              //revise order
1344
              newStack = MetaCatUtil.reviseStack(newStack);
1345
               // go throught the vector of unChangableAccessSubtreevector
1346
              // and find the one whose id is as same as referenceid
1347
              AccessSection oldAccessObj = 
1348
                       getAccessSectionFromUnchangableAccessVector(referenceId);
1349
              //if oldAccessObj is null something is wrong
1350
              if (oldAccessObj == null)
1351
              {
1352
                throw new SAXException(UPDATEACCESSERROR);
1353
              }//if
1354
              else
1355
              {
1356
                // Get the node stack from old access obj
1357
                Stack oldStack = oldAccessObj.getSubTreeNodeStack();
1358
                comparingNodeStacks(newStack, oldStack);
1359
              }//else
1360
            }//if
1361
            // write accessobject into db
1362
            writeGivenAccessRuleIntoDB(accessObj, top, subSectionId);
1363
            // add access rule for related on line data id too.
1364
            /*for (int j= 0; j<onlineDataFileIdVector.size(); j++)
1365
            {
1366
              String id = (String)onlineDataFileIdVector.elementAt(j);
1367
              writeAccessRuleForRalatedDataFileIntoDB(accessObj, id);
1368
            }*/
1369
            
1370
            
1371
            //write the reference access into xml_accesssubtree too
1372
             // write the top level access module into xml_accesssubtree to store info
1373
             // and then when update to check if the user can update it or not
1374
            deleteAccessSubTreeRecord(docid);
1375
            writeAccessSubTreeIntoDB(accessSectionObj,TOPLEVEL);
1376
            writeAccessSubTreeIntoDB(accessObj, SUBTREELEVEL);
1377
            findAccessObject = true;
1378
            break;
1379
          }
1380
        }//for
1381
        // if we couldn't find an access subtree id for this reference id
1382
        if (!findAccessObject)
1383
        {
1384
          throw new SAXException("The referenceid: " + referenceId +
1385
                               " is not access subtree");
1386
        }//if
1387
      }//else
1388
      
1389
     
1390
    }//if
1391
    else
1392
    {
1393
      // couldn't find a access section object 
1394
      MetaCatUtil.debugMessage("couldn't find access control for document: "+
1395
                                docid, 35);
1396
    }
1397
    
1398
  }//writeTopLevelAccessRuletoDB
1399
  
1400
  /* Given a subtree id and find the responding access section*/
1401
  private AccessSection getAccessSectionFromUnchangableAccessVector(String id)
1402
  {
1403
    AccessSection result = null;
1404
    // Makse sure the id
1405
    if (id == null || id.equals(""))
1406
    {
1407
      return result;
1408
    }
1409
    // go throught vector and find the list
1410
    for (int i=0; i<unChangableAccessSubTreeVector.size();i++)
1411
    {
1412
      AccessSection accessObj = (AccessSection)
1413
                                 unChangableAccessSubTreeVector.elementAt(i);
1414
      if (accessObj.getSubTreeId() != null && 
1415
         (accessObj.getSubTreeId()).equals(id))
1416
      {
1417
        result = accessObj;
1418
      }//if
1419
    }//for
1420
    return result;
1421
  }//getAccessSectionFromUnchangableAccessVector
1422
      
1423
  /* Compare two node stacks to see if they are same */
1424
  private void comparingNodeStacks(Stack stack1, Stack stack2) 
1425
                                 throws SAXException
1426
  {
1427
    // make sure stack1 and stack2 are not empty
1428
    if (stack1.isEmpty() || stack2.isEmpty())
1429
    {
1430
      MetaCatUtil.debugMessage("Because stack is empty!", 35);
1431
      throw new SAXException(UPDATEACCESSERROR);
1432
    }
1433
    // go throw two stacks and compare every element
1434
    while (!stack1.isEmpty())
1435
    {
1436
      // Pop an element from stack1
1437
      NodeRecord record1 = (NodeRecord) stack1.pop();
1438
      // Pop an element from stack2(stack 2 maybe empty)
1439
      NodeRecord record2 = null;
1440
      try
1441
      {
1442
        record2 = (NodeRecord) stack2.pop();
1443
      }
1444
      catch (EmptyStackException ee)
1445
      {
1446
        MetaCatUtil.debugMessage("Node stack2 is empty but stack1 isn't!", 35);
1447
        throw new SAXException(UPDATEACCESSERROR);
1448
      }
1449
      // if two records are not same throw a exception
1450
      if (!record1.contentEquals(record2))
1451
      {
1452
        MetaCatUtil.debugMessage("Two records from new and old stack are not "+
1453
                                 "same!", 30);
1454
        throw new SAXException(UPDATEACCESSERROR);
1455
      }//if
1456
    }//while
1457
    
1458
    // now stack1 is empty and we should make sure stack2 is empty too
1459
    if(!stack2.isEmpty())
1460
    {
1461
      MetaCatUtil.debugMessage("stack2 still have some elements while stack "+
1462
                               "is empty! ", 30);
1463
      throw new SAXException(UPDATEACCESSERROR);
1464
    }//if
1465
 }//comparingNodeStacks
1466
  
1467
   /* The method to write addtional access rule into db. */
1468
  private void writeAddtionalAccessRuleToDB() throws SAXException
1469
  {
1470
    
1471
     PreparedStatement pstmt = null;
1472
     boolean topLevel =false;
1473
    // go through the vector which contains the additional access control 
1474
    //hashtable. Each hashtable has info for one additonalmetadata container 
1475
   for (int j= 0; j < additionalAccessMapList.size(); j++)
1476
   {
1477
     
1478
     Hashtable accessControlMap = 
1479
                                (Hashtable)additionalAccessMapList.elementAt(j);
1480
     // additional access rule
1481
     Enumeration en = accessControlMap.keys();
1482
     
1483
     while(en.hasMoreElements())
1484
     {
1485
       try
1486
       {
1487
         // Get subsection id
1488
          String subSectionId = (String)en.nextElement();
1489
          MetaCatUtil.debugMessage("sub section id in additional access mapping"
1490
                                   +"(go through): "+ subSectionId, 35);
1491
          
1492
          if (subSectionId == null)
1493
          {
1494
            // if id is null, terminate the program
1495
            throw new SAXException("subtree id is null");
1496
          }
1497
          // Get AccessSection Object
1498
          Object accessSectionObj = accessControlMap.get(subSectionId);
1499
          if (accessSectionObj == null)
1500
          {
1501
            // if accesssection is null, terminate the program
1502
            throw new SAXException("access subtree is null");
1503
          }
1504
          else
1505
          {
1506
            AccessSection accessControlObj = (AccessSection)accessSectionObj;
1507
            // if the access section is not references, write it to db
1508
            if (accessControlObj.getReferences() == null)
1509
            {
1510
              writeGivenAccessRuleIntoDB(accessControlObj, topLevel, 
1511
                                         subSectionId);
1512
            }
1513
            else
1514
            {
1515
              // this is a reference and go trough the vector which contains all
1516
              // access object
1517
              String referenceId = accessControlObj.getReferences();
1518
            
1519
              boolean findAccessObject = false;
1520
              MetaCatUtil.debugMessage("referered id for additional access "+
1521
                                     "mapping(go through): "+ referenceId, 35);
1522
              for (int i=0; i<accessObjectList.size(); i++)
1523
              {
1524
                AccessSection accessObj = 
1525
                                (AccessSection)accessObjectList.elementAt(i);
1526
                String accessObjId = accessObj.getSubTreeId();
1527
                MetaCatUtil.debugMessage("access obj id in the list(go through): "
1528
                                        + accessObjId, 35);
1529
                if (referenceId != null && accessObj != null &&
1530
                    referenceId.equals(accessObjId))
1531
                {
1532
                  writeGivenAccessRuleIntoDB(accessObj, topLevel, subSectionId);
1533
                  findAccessObject = true;
1534
                }//if
1535
              }//for
1536
              // if we couldn't find an access subtree id for this reference id
1537
              if (!findAccessObject)
1538
              {
1539
                throw new SAXException("The referenceid: " + referenceId +
1540
                               " is not access subtree");
1541
              }//if
1542
            }//else
1543
          }//else
1544
       }//try
1545
       catch (Exception e)
1546
       {
1547
         
1548
         MetaCatUtil.debugMessage("error in EmlSAXHandler.writeAddtionalAccess"
1549
                                   + ": "+e.getMessage(), 30);
1550
         throw new SAXException(e.getMessage());
1551
       }
1552
     }//while
1553
    }//for
1554
  }//writeAccessRuletoDB
1555
  
1556
  /* Write a gaven access rule into db*/
1557
  private void writeGivenAccessRuleIntoDB(AccessSection accessSection, 
1558
                                         boolean topLevel, String subSectionId) 
1559
                                         throws SAXException
1560
  {
1561
     if (accessSection == null)
1562
     {
1563
       throw new SAXException("The access object is null");
1564
     }
1565
     
1566
      String permOrder = accessSection.getPermissionOrder();
1567
      String sql = null;
1568
      PreparedStatement pstmt = null;
1569
      if (topLevel)
1570
      {
1571
        sql = "INSERT INTO xml_access (docid, principal_name, permission, "+
1572
                 "perm_type, perm_order, accessfileid) VALUES " +
1573
                 " (?, ?, ?, ?, ?, ?)";
1574
      }
1575
      else
1576
      {
1577
        sql ="INSERT INTO xml_access (docid,principal_name, "+ 
1578
             "permission, perm_type, perm_order, accessfileid, subtreeid, "+
1579
             " startnodeid, endnodeid) VALUES" +
1580
             " (?, ?, ?, ?, ?, ?, ?, ?, ?)";
1581
      }
1582
      try 
1583
      {
1584
     
1585
        pstmt = connection.prepareStatement(sql);
1586
        // Increase DBConnection usage count
1587
        connection.increaseUsageCount(1);
1588
        // Bind the values to the query
1589
        pstmt.setString(1, docid);
1590
        MetaCatUtil.debugMessage("Docid in accesstable: "+ docid, 35);
1591
        pstmt.setString(6, docid);
1592
        MetaCatUtil.debugMessage("Accessfileid in accesstable: "+ docid, 35);
1593
        pstmt.setString(5, permOrder);
1594
        MetaCatUtil.debugMessage("PermOder in accesstable: "+ permOrder, 35);
1595
        // if it is not top level, set subsection id
1596
        if (!topLevel)
1597
        {
1598
          long startNodeId = 0;
1599
          long endNodeId = 0;
1600
          // for subtree should specify the
1601
          if (subSectionId == null)
1602
          {
1603
            throw new SAXException("The subsection is null");
1604
          }
1605
          // go through the substree list vector and found the start node id
1606
          // and stop node id for this subtree id
1607
          for (int i=0; i<subTreeList.size(); i++)
1608
          {
1609
            SubTree tree = (SubTree)subTreeList.elementAt(i);
1610
            String subTreeId = tree.getSubTreeId();
1611
            if (subSectionId.equals(subTreeId))
1612
            {
1613
              startNodeId = tree.getStartNodeId();
1614
              endNodeId = tree.getEndNodeId(); 
1615
            }//if
1616
          }//for
1617
          if (startNodeId == 0 || endNodeId == 0)
1618
          {
1619
            throw new SAXException("Could find the subtree"
1620
                                   + "for this id: "+subSectionId);
1621
          }
1622
          pstmt.setString(7, subSectionId);
1623
          MetaCatUtil.debugMessage("SubSectionId in accesstable: "+ 
1624
                                    subSectionId, 35);
1625
          pstmt.setLong(8, startNodeId);
1626
          MetaCatUtil.debugMessage("Start node id is: " + startNodeId, 35);
1627
          pstmt.setLong(9, endNodeId);
1628
          MetaCatUtil.debugMessage("End node id is: " + endNodeId, 35);
1629
          
1630
        }
1631
      
1632
        Vector accessRules = accessSection.getAccessRules();
1633
        // go through every rule
1634
        for (int i=0; i<accessRules.size(); i++)
1635
        {
1636
          AccessRule rule = (AccessRule)accessRules.elementAt(i);
1637
          String permType = rule.getPermissionType();
1638
          int permission = rule.getPermission();
1639
          pstmt.setInt(3, permission);
1640
          MetaCatUtil.debugMessage("permission in accesstable: "+ permission, 35);
1641
          pstmt.setString(4, permType);
1642
          MetaCatUtil.debugMessage("Permtype in accesstable: "+ permType, 35);
1643
          // go through every principle in rule
1644
          Vector nameVector = rule.getPrincipal();
1645
          for ( int j = 0; j < nameVector.size(); j++ ) 
1646
          {
1647
            String prName = (String)nameVector.elementAt(j);
1648
            pstmt.setString(2, prName);
1649
            MetaCatUtil.debugMessage("Principal in accesstable: "+prName, 35);
1650
            pstmt.execute();
1651
          }//for
1652
        }//for
1653
        pstmt.close();
1654
      }//try 
1655
      catch (SQLException e) 
1656
      {
1657
        throw new 
1658
        SAXException("EMLSAXHandler.writeAccessRuletoDB(): " + e.getMessage());
1659
      }//catch
1660
      finally
1661
      {
1662
        try
1663
        {
1664
          pstmt.close();
1665
        }
1666
        catch(SQLException ee)
1667
        {
1668
          throw new 
1669
          SAXException("EMLSAXHandler.writeAccessRuletoDB(): " + 
1670
          ee.getMessage());
1671
        }
1672
      }//finally
1673
     
1674
  }//writeGivenAccessRuleIntoDB
1675
  
1676
  
1677
  
1678
    /* Write a gaven access rule into db*/
1679
  private void writeAccessRuleForRalatedDataFileIntoDB
1680
                  (AccessSection accessSection, String dataId) 
1681
                                         throws SAXException
1682
  {
1683
      if (accessSection == null)
1684
      {
1685
        throw new SAXException("The access object is null");
1686
      }
1687
      // get rid of rev from dataId
1688
      dataId = MetaCatUtil.getDocIdFromString(dataId);
1689
      String permOrder = accessSection.getPermissionOrder();
1690
      String sql = null;
1691
      PreparedStatement pstmt = null;
1692
      sql = "INSERT INTO xml_access (docid, principal_name, permission, "+
1693
                 "perm_type, perm_order, accessfileid) VALUES " +
1694
                 " (?, ?, ?, ?, ?, ?)";
1695
   
1696
      try 
1697
      {
1698
     
1699
        pstmt = connection.prepareStatement(sql);
1700
        // Increase DBConnection usage count
1701
        connection.increaseUsageCount(1);
1702
        // Bind the values to the query
1703
        pstmt.setString(1, dataId);
1704
        MetaCatUtil.debugMessage("Docid in accesstable: "+ docid, 35);
1705
        pstmt.setString(6, docid);
1706
        MetaCatUtil.debugMessage("Accessfileid in accesstable: "+ docid, 35);
1707
        pstmt.setString(5, permOrder);
1708
        MetaCatUtil.debugMessage("PermOder in accesstable: "+ permOrder, 35);
1709
        // if it is not top level, set subsection id
1710
            
1711
        Vector accessRules = accessSection.getAccessRules();
1712
        // go through every rule
1713
        for (int i=0; i<accessRules.size(); i++)
1714
        {
1715
          AccessRule rule = (AccessRule)accessRules.elementAt(i);
1716
          String permType = rule.getPermissionType();
1717
          int permission = rule.getPermission();
1718
          pstmt.setInt(3, permission);
1719
          MetaCatUtil.debugMessage("permission in accesstable: "+ permission, 35);
1720
          pstmt.setString(4, permType);
1721
          MetaCatUtil.debugMessage("Permtype in accesstable: "+ permType, 35);
1722
          // go through every principle in rule
1723
          Vector nameVector = rule.getPrincipal();
1724
          for ( int j = 0; j < nameVector.size(); j++ ) 
1725
          {
1726
            String prName = (String)nameVector.elementAt(j);
1727
            pstmt.setString(2, prName);
1728
            MetaCatUtil.debugMessage("Principal in accesstable: "+prName, 35);
1729
            pstmt.execute();
1730
          }//for
1731
        }//for
1732
        pstmt.close();
1733
      }//try 
1734
      catch (SQLException e) 
1735
      {
1736
        throw new 
1737
        SAXException("EMLSAXHandler.writeAccessRuletoDB(): " + e.getMessage());
1738
      }//catch
1739
      finally
1740
      {
1741
        try
1742
        {
1743
          pstmt.close();
1744
        }
1745
        catch(SQLException ee)
1746
        {
1747
          throw new 
1748
          SAXException("EMLSAXHandler.writeAccessRuletoDB(): " + 
1749
          ee.getMessage());
1750
        }
1751
      }//finally
1752
     
1753
  }//writeAccessRuleForRalatedDataFileIntoDB
1754
  
1755
  
1756
  
1757
  
1758
  
1759
  /* Delete from db all permission for resources related to @aclid if any.*/
1760
  private void deletePermissionsInAccessTable(String aclid) 
1761
          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_access WHERE accessfileid = '" + aclid +
1771
                   "'"); 
1772
    
1773
    }
1774
    catch (SQLException e)
1775
    {
1776
      throw new SAXException(e.getMessage());
1777
    }
1778
    finally
1779
    {
1780
      try
1781
      {
1782
        stmt.close();
1783
      }
1784
      catch (SQLException ee)
1785
      {
1786
        throw new SAXException(ee.getMessage());
1787
      }
1788
    }
1789
  }//deletePermissionsInAccessTable
1790
  
1791
  
1792
  /* In order to make sure only usr has "all" permission can update access
1793
   * subtree in eml document we need to keep access subtree info in 
1794
   * xml_accesssubtree table, such as docid, version, startnodeid, endnodeid
1795
   */
1796
  private void writeAccessSubTreeIntoDB(AccessSection accessSection, 
1797
                                         String level) 
1798
                                         throws SAXException
1799
  {
1800
     if (accessSection == null)
1801
     {
1802
       throw new SAXException("The access object is null");
1803
     }
1804
     
1805
      String sql = null;
1806
      PreparedStatement pstmt = null;
1807
      sql = "INSERT INTO xml_accesssubtree (docid, rev, controllevel, "+
1808
                 "subtreeid, startnodeid, endnodeid) VALUES " +
1809
                 " (?, ?, ?, ?, ?, ?)";
1810
      try 
1811
      {
1812
     
1813
        pstmt = connection.prepareStatement(sql);
1814
        // Increase DBConnection usage count
1815
        connection.increaseUsageCount(1);
1816
        long startNodeId = accessSection.getStartNodeId();
1817
        long endNodeId = accessSection.getEndNodeId();
1818
        String sectionId = accessSection.getSubTreeId();
1819
        // Bind the values to the query
1820
        pstmt.setString(1, docid);
1821
        MetaCatUtil.debugMessage("Docid in access-subtreetable: "+ docid, 35);
1822
        pstmt.setString(2, revision );
1823
        MetaCatUtil.debugMessage("rev in accesssubtreetable: "+ revision, 35);
1824
        pstmt.setString(3, level);
1825
        MetaCatUtil.debugMessage("contorl level in access-subtree table: "+
1826
                                  level, 35);
1827
        pstmt.setString(4, sectionId);
1828
        MetaCatUtil.debugMessage("Subtree id in access-subtree table: "+ 
1829
                                  sectionId, 35);
1830
        pstmt.setLong(5, startNodeId);
1831
        MetaCatUtil.debugMessage("Start node id is: " + startNodeId, 35);
1832
        pstmt.setLong(6, endNodeId);
1833
        MetaCatUtil.debugMessage("End node id is: " + endNodeId, 35);
1834
        pstmt.execute();
1835
        pstmt.close();
1836
      }//try 
1837
      catch (SQLException e) 
1838
      {
1839
        throw new 
1840
        SAXException("EMLSAXHandler.writeAccessSubTreeIntoDB(): " + 
1841
                      e.getMessage());
1842
      }//catch
1843
      finally
1844
      {
1845
        try
1846
        {
1847
          pstmt.close();
1848
        }
1849
        catch(SQLException ee)
1850
        {
1851
          throw new 
1852
          SAXException("EMLSAXHandler.writeAccessSubTreeIntoDB(): " + 
1853
          ee.getMessage());
1854
        }
1855
      }//finally
1856
     
1857
  }//writeAccessSubtreeIntoDB
1858
  
1859
   /* Delete every access subtree record from xml_accesssubtree.*/
1860
  private void deleteAccessSubTreeRecord(String docId) throws SAXException 
1861
  {
1862
    Statement stmt = null;
1863
    try
1864
    {
1865
      // delete all acl records for resources related to @aclid if any
1866
      stmt = connection.createStatement();
1867
      // Increase DBConnection usage count
1868
      connection.increaseUsageCount(1);
1869
      stmt.execute("DELETE FROM xml_accesssubtree WHERE docid = '" + docId + "'"); 
1870
   
1871
    }
1872
    catch (SQLException e)
1873
    {
1874
      throw new SAXException(e.getMessage());
1875
    }
1876
    finally
1877
    {
1878
      try
1879
      {
1880
        stmt.close();
1881
      }
1882
      catch (SQLException ee)
1883
      {
1884
        throw new SAXException(ee.getMessage());
1885
      }
1886
    }
1887
  }//deleteAccessSubTreeRecord
1888
  
1889
  // write inline data into file system and return file name(without path)
1890
  private StringBuffer writeInlineDataIntoFile(StringBuffer data) 
1891
                                               throws SAXException
1892
  {
1893
    StringBuffer fileNameBuffer = null;
1894
    String fileName = null;
1895
    String docidWithoutRev = MetaCatUtil.getDocIdFromString(docid);
1896
    String path = MetaCatUtil.getOption("inlinedatafilepath");
1897
    String seperator = MetaCatUtil.getOption("accNumSeparator");
1898
    // the new file name will look like path/docid.rev.2
1899
    fileName = docidWithoutRev + seperator+revision+seperator +inLineDataIndex;
1900
    File inlineDataDirectory = new File(path);
1901
    File newFile = new File(inlineDataDirectory, fileName); 
1902
    // incease inLinedataindex for next one
1903
    inLineDataIndex++ ;
1904
    try
1905
    {
1906
      FileWriter writer = new FileWriter(newFile);
1907
      writer.write(data.toString());
1908
      writer.close();
1909
    }
1910
    catch (Exception e)
1911
    {
1912
      throw new SAXException(e.getMessage());
1913
    }
1914
    
1915
    fileNameBuffer = new StringBuffer(fileName);
1916
    return fileNameBuffer;
1917
  }
1918
  
1919
  /* In eml2, the inline data wouldn't store in db, it store in file system
1920
   * The db stores file name(without path).
1921
   */
1922
  public static String readInlineDataFromFileSystem(String fileName) 
1923
                                              throws McdbException
1924
  {
1925
    String data = null;
1926
    String path = MetaCatUtil.getOption("inlinedatafilepath");
1927
    // the new file name will look like path/docid.rev.2
1928
    File inlineDataDirectory = new File(path);
1929
    File dataFile = new File(inlineDataDirectory, fileName);
1930
    try
1931
    {
1932
      FileReader fileReader = new FileReader(dataFile);
1933
      BufferedReader stringReader = new BufferedReader(fileReader);
1934
      // read first line of data
1935
      String tmp = stringReader.readLine();
1936
      // pass first line data to data varible
1937
      data = tmp;
1938
      // at the end tmp will be null
1939
      while (tmp != null)
1940
      {
1941
        // read a new line
1942
        tmp = stringReader.readLine();
1943
        // append new line to data
1944
        if (tmp != null)
1945
        {
1946
          data = data+tmp;
1947
        }
1948
      }
1949
      
1950
    }
1951
    catch (Exception e)
1952
    {
1953
      throw new McdbException(e.getMessage());
1954
    }
1955
    MetaCatUtil.debugMessage("the inline data retrieve from file: "+data, 50);
1956
    return data;
1957
  }
1958
  
1959
  /* Delete relations */
1960
  private void deleteRelations() throws SAXException
1961
  {
1962
    PreparedStatement pStmt = null;
1963
    String sql = "DELETE FROM xml_relation where docid =?";
1964
    try
1965
    {
1966
      pStmt = connection.prepareStatement(sql);
1967
      //bind variable
1968
      pStmt.setString(1, docid);
1969
      //execute query
1970
      pStmt.execute();
1971
      pStmt.close();
1972
    }//try
1973
    catch (SQLException e) 
1974
    {
1975
       throw new 
1976
       SAXException("EMLSAXHandler.deleteRelations(): " + 
1977
                      e.getMessage());
1978
    }//catch
1979
    finally
1980
    {
1981
      try
1982
      {
1983
        pStmt.close();
1984
      }//try
1985
      catch(SQLException ee)
1986
      {
1987
        throw new 
1988
        SAXException("EMLSAXHandler.deleteRelations: " + 
1989
        ee.getMessage());
1990
      }//catch
1991
    }//finally
1992
  }
1993
  
1994
  /* Write an online data file id into xml_relation table*/
1995
  private void writeOnlineDataFileIdIntoRelationTable(String dataId) 
1996
                                                        throws SAXException
1997
  {
1998
    // Get rid of rev
1999
    dataId = MetaCatUtil.getDocIdFromString(dataId);
2000
    PreparedStatement pStmt = null;
2001
    String sql = "INSERT into xml_relation (docid, packagetype, subject, "+
2002
                 "relationship, object) values (?, ?, ?, ?, ?)";
2003
    try
2004
    {
2005
      pStmt = connection.prepareStatement(sql);
2006
      //bind variable
2007
      pStmt.setString(1, docid);
2008
      pStmt.setString(2, DocumentImpl.EMLNAMESPACE);
2009
      pStmt.setString(3, docid);
2010
      pStmt.setString(4, RELATION);
2011
      pStmt.setString(5, dataId);
2012
      //execute query
2013
      pStmt.execute();
2014
      pStmt.close();
2015
    }//try
2016
    catch (SQLException e) 
2017
    {
2018
       throw new 
2019
       SAXException("EMLSAXHandler.writeOnlineDataFileIdIntoRelationTable(): " + 
2020
                      e.getMessage());
2021
    }//catch
2022
    finally
2023
    {
2024
      try
2025
      {
2026
        pStmt.close();
2027
      }//try
2028
      catch(SQLException ee)
2029
      {
2030
        throw new 
2031
        SAXException("EMLSAXHandler.writeOnlineDataFileIdIntoRelationTable(): " + 
2032
        ee.getMessage());
2033
      }//catch
2034
    }//finally
2035
    
2036
  }//writeOnlineDataFileIdIntoRelationTable
2037
}
(34-34/57)