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-11 09:22:09 -0700 (Fri, 11 Apr 2003) $'
12
 * '$Revision: 1540 $'
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;
80
   private boolean startCriticalSubTree = false;
81
   private boolean firstElementForCriticalSubTree = false;
82
   private String firstElementNameForCriticalSubTree;
83
   private boolean needCheckingAccessModule = false;
84
   private Vector unChangableAccessSubTreeVector;
85
   private AccessSection topAccessSection;
86
 
87
 
88
   // Constant
89
   private static final String EML ="eml";
90
   private static final String DESCRIBES = "describes";
91
   private static final String ADDITIONALMETADATA = "additionalMetadata";
92
   private static final String ORDER = "order";
93
   private static final String ID ="id";
94
   private static final String REFERENCES = "references";
95
   public  static final String INLINE = "inline";
96
   private static final String PERMISSIONERROR ="User try to update a subtree"+
97
                               " which it doesn't have write permission!";
98
   private static final String TOPLEVEL = "top";
99
   private static final String SUBTREELEVEL ="subtree";
100
  
101
    /** Construct an instance of the handler class
102
    * In this constructor, user can specify the version need to upadate
103
    *
104
    * @param conn the JDBC connection to which information is written
105
    * @param action - "INSERT" or "UPDATE"
106
    * @param docid to be inserted or updated into JDBC connection
107
    * @param revision, the user specified the revision need to be update
108
    * @param user the user connected to MetaCat servlet and owns the document
109
    * @param groups the groups to which user belongs
110
    * @param pub flag for public "read" access on document
111
    * @param serverCode the serverid from xml_replication on which this document
112
    *        resides.
113
    *
114
    */
115
   public EmlSAXHandler(DBConnection conn, String action, String docid,
116
     String revision, String user, String[] groups, String pub, int serverCode)
117
                              throws SAXException
118
   {
119
     super(conn, action, docid, revision, user, groups, pub, serverCode);
120
     // Get the unchangable subtrees (user doesn't have write permission)
121
     try
122
     {
123
       PermissionController control = new PermissionController(docid);
124
       //unChangableSubTreeHash = getUnchangableSubTree(control, user, groups);
125
       
126
       
127
       //If the action is update and user doesn't have "ALL" permission
128
       // we need to check if user update access subtree
129
       if (action.equals("UPDATE") && 
130
         control.hasPermission(user, groups, AccessControlInterface.ALLSTRING))
131
       {
132
         needCheckingAccessModule = true;
133
         unChangableAccessSubTreeVector = getAccessSubTreeListFromDB();
134
       }
135
     }
136
     catch (Exception e)
137
     {
138
       throw new SAXException(e.getMessage());
139
     }
140
   }
141
   
142
   /* Pass a permission control and get the list of unchangable subtree*/
143
   private Hashtable getUnchangableSubTree(PermissionController controller,
144
                                           String user, String[]groups)
145
                                           throws Exception
146
   {
147
     Hashtable list = null;
148
     Hashtable result = new Hashtable();
149
     // get unwritable sutree from controller
150
     list = controller.hasUnaccessableSubTree(user, groups, 
151
                                          AccessControlInterface.WRITESTRING);
152
      if (list != null)
153
      {
154
       
155
         Enumeration en = list.elements();
156
         while (en.hasMoreElements())
157
         {
158
           // Get  a subtree without node record list
159
           SubTree treeWithoutStack = (SubTree)en.nextElement();
160
           String subTreeId   = treeWithoutStack.getSubTreeId();
161
           MetaCatUtil.debugMessage("unchangable subtree id: " + subTreeId, 40);
162
           long   startNodeId = treeWithoutStack.getStartNodeId();
163
           MetaCatUtil.debugMessage("unchangable subtree startnodeid: " +
164
                                    startNodeId, 40);
165
           long   endNodeId   = treeWithoutStack.getEndNodeId();
166
           MetaCatUtil.debugMessage("unchangable subtree endnodeid: " +
167
                                     endNodeId, 40);
168
           // Get a subtree has the nodelist
169
           SubTree tree = new SubTree(docid, subTreeId, startNodeId, endNodeId);
170
           // add this tree to the result
171
           result.put(subTreeId, tree);
172
         
173
          }//while
174
      
175
      }//if
176
      
177
      return result;
178
   }
179
   
180
   
181
   /*
182
    * Get the subtree node info from xml_accesssubtree table
183
    */
184
   private Vector getAccessSubTreeListFromDB() throws Exception
185
   {
186
      Vector result = new Vector();
187
      PreparedStatement pstmt = null;
188
      ResultSet rs = null;
189
      String sql = "SELECT controllevel, subtreeid, startnodeid, endnodeid) " + 
190
                   "FROM xml_accesssubtree WHERE docid like ? " +
191
                   "ORDER BY startnodeid ASC";
192
              
193
      try 
194
      {
195
     
196
        pstmt = connection.prepareStatement(sql);
197
        // Increase DBConnection usage count
198
        connection.increaseUsageCount(1);
199
        // Bind the values to the query
200
        pstmt.setString(1, docid);
201
        pstmt.execute();
202
        
203
        // Get result set
204
        rs = pstmt.getResultSet();
205
        while (rs.next())
206
        {
207
          String level = rs.getString(1);
208
          String sectionId = rs.getString(2);
209
          long startNodeId = rs.getLong(3);
210
          long endNodeId = rs.getLong(4);
211
          // create a new access section
212
          AccessSection accessObj = new AccessSection();
213
          accessObj.setControlLevel(level);
214
          accessObj.setDocId(docid);
215
          accessObj.setSubTreeId(sectionId);
216
          accessObj.setStartNodeId(startNodeId);
217
          accessObj.setEndNodeId(endNodeId); 
218
          Stack nodeStack = accessObj.getSubTreeNodeList();
219
          accessObj.setSubTreeNodeStack(nodeStack);
220
          // add this access obj into vector
221
          result.add(accessObj);
222
          // Get the top level access subtree control
223
          if ( level != null && level.equals(TOPLEVEL))
224
          {
225
            topAccessSection = accessObj;
226
          }
227
        }
228
        pstmt.close();
229
      }//try 
230
      catch (SQLException e) 
231
      {
232
        throw new 
233
        SAXException("EMLSAXHandler.getAccessSubTreeListFromDB(): " + 
234
                      e.getMessage());
235
      }//catch
236
      finally
237
      {
238
        try
239
        {
240
          pstmt.close();
241
        }
242
        catch(SQLException ee)
243
        {
244
          throw new 
245
          SAXException("EMLSAXHandler.getAccessSubTreeListFromDB(): " + 
246
          ee.getMessage());
247
        }
248
      }//finally
249
      return result;
250
   }
251
   /** SAX Handler that is called at the start of each XML element */
252
   public void startElement(String uri, String localName,
253
                            String qName, Attributes atts)
254
               throws SAXException 
255
  {
256
      // for element <eml:eml...> qname is "eml:eml", local name is "eml"            
257
     // for element <acl....> both qname and local name is "eml"
258
     // uri is namesapce
259
     MetaCatUtil.debugMessage("Start ELEMENT(qName) " + qName, 50);
260
     MetaCatUtil.debugMessage("Start ELEMENT(localName) " + localName, 50);
261
     MetaCatUtil.debugMessage("Start ELEMENT(uri) " + uri, 50);
262
     
263
     
264
     DBSAXNode parentNode = null;
265
     DBSAXNode currentNode = null;
266

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

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

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

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

    
405

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

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

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

    
701
     // Get the node from the stack
702
     DBSAXNode currentNode = (DBSAXNode)nodeStack.pop();
703
     String currentTag = currentNode.getTagName();
704
    
705
     // If before the end element, the parser hit text nodes and store them
706
     // into the buffer, write the buffer to data base. The reason we put
707
     // write database here is for xerces some time split text node
708
     if (hitTextNode)
709
     {
710
        // get access value
711
        String data = null;
712
        // add principal
713
       if (currentTag.equals(PRINCIPAL) && accessRule != null) 
714
       {
715
          data = (textBuffer.toString()).trim();
716
          accessRule.addPrincipal(data);
717

    
718
       } 
719
       else if (currentTag.equals(PERMISSION) && accessRule != null) 
720
       {
721
         data = (textBuffer.toString()).trim();
722
         // we conbine different a permission into one value
723
         int permission = accessRule.getPermission();
724
         // add permision
725
         if ( data.toUpperCase().equals(READSTRING) ) 
726
         {
727
           permission = permission | READ;
728
         } 
729
         else if ( data.toUpperCase().equals(WRITESTRING) ) 
730
         {
731
           permission = permission | WRITE;
732
         } 
733
         else if ( data.toUpperCase().equals(CHMODSTRING)) 
734
         {
735
           permission = permission | CHMOD;
736
         } 
737
         else if ( data.toUpperCase().equals(ALLSTRING) ) 
738
         {
739
          permission = permission | ALL;
740
         }
741
         accessRule.setPermission(permission);
742
       }
743
       // put additionalmetadata/describes into vector
744
       else if (currentTag.equals(DESCRIBES))
745
       {
746
          data = (textBuffer.toString()).trim();
747
          describesId.add(data);
748
       }
749
       else if (currentTag.equals(REFERENCES) && 
750
               (processTopLeverAccess ||
751
                processAdditionalAccess || processOtherAccess))
752
       {
753
         // get reference 
754
         data = (textBuffer.toString()).trim();
755
         // put reference id into accessSection
756
         accessObject.setReferences(data);
757
         
758
       }
759
       // write text to db if it is not inline data
760
       if (!localName.equals(INLINE))
761
       {
762
          MetaCatUtil.debugMessage("Write text into DB in End Element", 50);
763
          //compare whitespace if need
764
          if (startCriticalSubTree)
765
          {
766
            NodeRecord node = null;
767
            try
768
            {
769
              node = (NodeRecord)currentUnChangedableSubtreeNodeStack.pop();
770
            }
771
            catch (EmptyStackException ee)
772
            {
773
              MetaCatUtil.debugMessage("the stack is empty for text data", 32);
774
              throw new SAXException(PERMISSIONERROR);
775
            }
776
            MetaCatUtil.debugMessage("current node type from xml is TEXT in endElement", 40);
777
            MetaCatUtil.debugMessage("node type from stack: " + 
778
                                        node.getNodeType(), 40);
779
            MetaCatUtil.debugMessage("current node data from xml is: " + 
780
                                        textBuffer.toString(), 40);
781
            MetaCatUtil.debugMessage("node data from stack: " +
782
                                        node.getNodeData(), 40);
783
            MetaCatUtil.debugMessage("node name from stack: " + 
784
                                        node.getNodeName(), 40);
785
            MetaCatUtil.debugMessage("node is from stack: " + 
786
                                        node.getNodeId(), 40);
787
            if (!node.getNodeType().equals("TEXT") || 
788
               !(textBuffer.toString()).equals(node.getNodeData())) 
789
            { 
790
              MetaCatUtil.debugMessage("current node type from xml is TEXT in endElement", 40);
791
              MetaCatUtil.debugMessage("node type from stack: " + 
792
                                        node.getNodeType(), 40);
793
              MetaCatUtil.debugMessage("current node data from xml is: " + 
794
                                        textBuffer.toString(), 40);
795
              MetaCatUtil.debugMessage("node data from stack: " +
796
                                        node.getNodeData(), 40);
797
              MetaCatUtil.debugMessage("node name from stack: " + 
798
                                        node.getNodeName(), 40);
799
              MetaCatUtil.debugMessage("node is from stack: " + 
800
                                        node.getNodeId(), 40);
801
              throw new SAXException(PERMISSIONERROR);
802
            }//if
803
          }//if
804
          endNodeId = writeTextForDBSAXNode(textBuffer, currentNode);
805
       }
806
       else
807
       {
808
          MetaCatUtil.debugMessage("Write inline data into file system", 35);
809
          
810
          //check if user changed inine data or not if user doesn't have
811
          // write permission
812
          if (startCriticalSubTree)
813
          {
814
            NodeRecord node = null;
815
            String inlineData;
816
            try
817
            {
818
              node = (NodeRecord)currentUnChangedableSubtreeNodeStack.pop();
819
              // get file name from db
820
              String fileName = node.getNodeData();
821
              MetaCatUtil.debugMessage("in handle inline data", 35);
822
              MetaCatUtil.debugMessage("the inline data file name from node is: "+
823
                                      fileName, 40);
824
              inlineData = readInlineDataFromFileSystem(fileName);
825
            }
826
            catch (EmptyStackException ee)
827
            {
828
              MetaCatUtil.debugMessage("the stack is empty for text data", 32);
829
              throw new SAXException(PERMISSIONERROR);
830
            }
831
            catch (McdbException eee)
832
            {
833
              throw new SAXException(eee.getMessage());
834
            }
835
            
836
            if (!(textBuffer.toString()).equals(inlineData))
837
            {
838
              MetaCatUtil.debugMessage("inline data was changed by a user" +
839
                                       " who doesn't have permission", 30);
840
              throw new SAXException(PERMISSIONERROR);
841
            }//if
842
          }//if
843
          // write inline data into file system and return file name
844
          textBuffer = writeInlineDataIntoFile(textBuffer);
845
          // write file name into db
846
          endNodeId = writeTextForDBSAXNode(textBuffer, currentNode);
847
       }
848
     }//if
849
     
850
     //end crtical subtree(user doesn't have permission to write)
851
     //When reach the first element and stack is empty
852
     if (localName.equals(firstElementNameForCriticalSubTree) && 
853
         currentUnChangedableSubtreeNodeStack.isEmpty()) 
854
     {
855
       startCriticalSubTree = false;
856
     }
857
     
858
     
859
     //set hitText false
860
     hitTextNode = false;
861
     // reset textbuff
862
     textBuffer = null;
863
     textBuffer = new StringBuffer();
864
     
865
     // hand sub stree stuff
866
     if (!subTreeInfoStack.empty())
867
     {
868
       SubTree tree = (SubTree)subTreeInfoStack.peek();// get last subtree
869
       if (tree != null && tree.getStartElementName() != null && 
870
         (tree.getStartElementName()).equals(currentTag))
871
       {
872
         // find the end of sub tree and set the end node id
873
         tree.setEndNodeId(endNodeId);
874
         // add the subtree into the final store palace
875
         subTreeList.add(tree);
876
         // get rid of it from stack
877
         subTreeInfoStack.pop();
878
       }//if
879
     }//if
880

    
881
     // access stuff
882
     if (currentTag.equals(ALLOW) || currentTag.equals(DENY))
883
     {
884
       // finish parser a ccess rule and  assign it to new one
885
       AccessRule newRule = accessRule;
886
       //add the new rule to access section object
887
       accessObject.addAccessRule(newRule);
888
       // reset access rule
889
       accessRule = null;
890
     }
891
     else if (currentTag.equals(ACCESS))
892
     {
893
       // finish parse a access setction and assign it to new one
894
       accessObject.setEndNodeId(endNodeId);
895
       AccessSection newAccessObject = accessObject;
896
       if (newAccessObject != null)
897
       {
898
        // add the accessSection into a vector to store it
899
        // if it is not a reference, need to store it
900
        if ( newAccessObject.getReferences() == null)
901
        {
902
          accessObjectList.add(newAccessObject);
903
        }
904
        if (processTopLeverAccess)
905
        {
906
          // top level access control will handle whole document -docid
907
          topLevelAccessControlMap.put(docid, newAccessObject);
908
          // reset processtopleveraccess tag
909
          
910
        }//if
911
        else if (processAdditionalAccess)
912
        {
913
          // for additional control
914
          // put everything in describes value and access object into hash
915
       
916
          for ( int i=0; i<describesId.size(); i++)
917
          {
918
           
919
            String subId = (String)describesId.elementAt(i);
920
            if (subId != null)
921
            {
922
              additionalAccessControlMap.put(subId, newAccessObject);
923
            }//if
924
          }//for
925
          // add this hashtable in to vector
926
         
927
          additionalAccessMapList.add(additionalAccessControlMap);
928
          // reset this hashtable in order to store another additional 
929
          //accesscontrol
930
          additionalAccessControlMap = null;
931
          additionalAccessControlMap = new Hashtable();
932
        }//if
933
       }//if
934
       //reset access section object
935
       accessObject = null;
936
       // reset flag
937
       processAdditionalAccess =false;
938
       processTopLeverAccess =false;
939
       processOtherAccess = false;
940
     }
941
     else if (currentTag.equals(ADDITIONALMETADATA))
942
     {
943
        //reset describesId
944
        describesId = null;
945
        describesId = new Vector();
946
     }
947
   }
948
   
949
   /**
950
    * SAX Handler that receives notification of comments in the DTD
951
    */
952
   public void comment(char[] ch, int start, int length) throws SAXException {
953
     MetaCatUtil.debugMessage("COMMENT", 50);
954
     if ( !processingDTD ) 
955
     {
956
       DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
957
       String str = new String(ch, start, length);
958
       
959
       //compare comment if need
960
       if (startCriticalSubTree)
961
       {
962
         NodeRecord node = null;
963
         try
964
         {
965
           node = (NodeRecord)currentUnChangedableSubtreeNodeStack.pop();
966
         }
967
         catch (EmptyStackException ee)
968
         {
969
           MetaCatUtil.debugMessage("the stack is empty for comment data", 32);
970
           throw new SAXException(PERMISSIONERROR);
971
         }
972
         MetaCatUtil.debugMessage("current node type from xml is COMMENT", 40);
973
         MetaCatUtil.debugMessage("node type from stack: " + 
974
                                    node.getNodeType(), 40);
975
         MetaCatUtil.debugMessage("current node data from xml is: " + 
976
                                    str, 40);
977
         MetaCatUtil.debugMessage("node data from stack: " +
978
                                    node.getNodeData(), 40);
979
         MetaCatUtil.debugMessage("node is from stack: " + 
980
                                        node.getNodeId(), 40);
981
         if (!node.getNodeType().equals("COMMENT") || 
982
             !str.equals(node.getNodeData())) 
983
         { 
984
          MetaCatUtil.debugMessage("current node type from xml is COMMENT", 40);
985
          MetaCatUtil.debugMessage("node type from stack: " + 
986
                                    node.getNodeType(), 40);
987
          MetaCatUtil.debugMessage("current node data from xml is: " + 
988
                                    str, 40);
989
          MetaCatUtil.debugMessage("node data from stack: " +
990
                                    node.getNodeData(), 40);
991
          MetaCatUtil.debugMessage("node is from stack: " + 
992
                                        node.getNodeId(), 40);
993
          throw new SAXException(PERMISSIONERROR);
994
        }//if
995
       }//if
996
       
997
       endNodeId = currentNode.writeChildNodeToDB("COMMENT", null, str, docid);
998
     }
999
   }
1000
   
1001
      /**
1002
    * SAX Handler that is called for each XML text node that is
1003
    * Ignorable white space
1004
    */
1005
   public void ignorableWhitespace(char[] cbuf, int start, int len)
1006
               throws SAXException 
1007
  {
1008
     // When validation is turned "on", white spaces are reported here
1009
     // When validation is turned "off" white spaces are not reported here,
1010
     // but through characters() callback
1011
     MetaCatUtil.debugMessage("IGNORABLEWHITESPACE", 50);
1012
     DBSAXNode currentNode = (DBSAXNode)nodeStack.peek();
1013
     String data = null;
1014
     int leftover = len;
1015
     int offset = start;
1016
     boolean moredata = true;
1017

    
1018
     // This loop deals with the case where there are more characters
1019
     // than can fit in a single database text field (limit is
1020
     // MAXDATACHARS).  If the text to be inserted exceeds MAXDATACHARS,
1021
     // write a series of nodes that are MAXDATACHARS long, and then the
1022
     // final node contains the remainder
1023
     while (moredata) 
1024
     {
1025
       if (leftover > MAXDATACHARS) 
1026
       {
1027
         data = new String(cbuf, offset, MAXDATACHARS);
1028
         leftover -= MAXDATACHARS;
1029
         offset += MAXDATACHARS;
1030
       } 
1031
       else 
1032
       {
1033
         data = new String(cbuf, offset, leftover);
1034
         moredata = false;
1035
       }
1036

    
1037
       //compare whitespace if need
1038
       if (startCriticalSubTree)
1039
       {
1040
         NodeRecord node = null;
1041
         try
1042
         {
1043
           node = (NodeRecord)currentUnChangedableSubtreeNodeStack.pop();
1044
         }
1045
         catch (EmptyStackException ee)
1046
         {
1047
           MetaCatUtil.debugMessage("the stack is empty for whitespace data", 32);
1048
           throw new SAXException(PERMISSIONERROR);
1049
         }
1050
         if (!node.getNodeType().equals("TEXT") || 
1051
             !data.equals(node.getNodeData())) 
1052
         { 
1053
          MetaCatUtil.debugMessage("current node type from xml is WHITESPACE TEXT", 40);
1054
          MetaCatUtil.debugMessage("node type from stack: " + 
1055
                                    node.getNodeType(), 40);
1056
          MetaCatUtil.debugMessage("current node data from xml is: " + 
1057
                                    data, 40);
1058
          MetaCatUtil.debugMessage("node data from stack: " +
1059
                                    node.getNodeData(), 40);
1060
          MetaCatUtil.debugMessage("node is from stack: " + 
1061
                                        node.getNodeId(), 40);
1062
          throw new SAXException(PERMISSIONERROR);
1063
        }//if
1064
       }//if
1065
       // Write the content of the node to the database
1066
       endNodeId = currentNode.writeChildNodeToDB("TEXT", null, data, docid);
1067
     }
1068
     
1069
     
1070
   
1071
   }
1072
   
1073
   /** SAX Handler that receives notification of end of the document */
1074
   public void endDocument() throws SAXException 
1075
   {
1076
     MetaCatUtil.debugMessage("end Document", 50);
1077
     // There are some unchangable subtree didn't be compare
1078
     // This maybe cause user change the subtree id
1079
     if (!unChangableSubTreeHash.isEmpty())
1080
     {
1081
       MetaCatUtil.debugMessage("The unChangealbe subtree is not empty", 40);
1082
       throw new SAXException(PERMISSIONERROR);
1083
     }
1084
     
1085
     // write access rule to db
1086
     writeAccessRuleToDB();
1087
   
1088
     // Starting new thread for writing XML Index.
1089
     // It calls the run method of the thread.
1090
     try 
1091
     {
1092
       xmlIndex.start();
1093
     } 
1094
     catch (NullPointerException e) 
1095
     {
1096
       xmlIndex = null;
1097
       throw new
1098
       SAXException("Problem with starting thread for writing XML Index. " +
1099
                    e.getMessage());
1100
     }
1101
   
1102
   }
1103
   
1104
  /* The method to write all access rule intodb */
1105
  private void writeAccessRuleToDB() throws SAXException
1106
  {
1107
    //Delete old permssion
1108
    deletePermissionsInAccessTable(docid);
1109
    //write top leve access rule
1110
    writeTopLevelAccessRuleToDB();
1111
    //write additional access rule
1112
    //writeAddtionalAccessRuleToDB();
1113
  }//writeAccessRuleToDB
1114
   
1115
  /* The method to write top level access rule into db. */
1116
  private void writeTopLevelAccessRuleToDB() throws SAXException
1117
  {
1118
    
1119
    // for top document level
1120
    Object accessSection = topLevelAccessControlMap.get(docid);
1121
    boolean top = true;
1122
    String subSectionId = null;
1123
    if ( accessSection != null )
1124
    {
1125
       AccessSection accessSectionObj = (AccessSection)accessSection;
1126
       // write the top level access module into xml_accesssubtree to store info
1127
       // and then when update to check if the user can update it or not
1128
       deleteAccessSubTreeRecord(docid);
1129
       writeAccessSubTreeIntoDB(accessSectionObj,TOPLEVEL);
1130
       
1131
       // if accessSection is not null and is not reference
1132
       if ( accessSectionObj.getReferences() == null)
1133
       {
1134
          writeGivenAccessRuleIntoDB(accessSectionObj, top, subSectionId);
1135
       }
1136
       else
1137
       {
1138
   
1139
        // this is a reference and go trough the vector which contains all
1140
        // access object
1141
        String referenceId = accessSectionObj.getReferences();
1142
        boolean findAccessObject = false;
1143
        MetaCatUtil.debugMessage("referered id for top access: "+ 
1144
                               referenceId, 35);
1145
        for (int i=0; i<accessObjectList.size(); i++)
1146
        {
1147
          AccessSection accessObj = (AccessSection)accessObjectList.elementAt(i);
1148
          String accessObjId = accessObj.getSubTreeId();
1149
          if (referenceId != null && accessObj != null &&
1150
              referenceId.equals(accessObjId))
1151
          {
1152
            writeGivenAccessRuleIntoDB(accessObj, top, subSectionId);
1153
            // write the reference access into xml_accesssubtree too
1154
            writeAccessSubTreeIntoDB(accessObj, SUBTREELEVEL);
1155
            findAccessObject = true;
1156
          }
1157
        }//for
1158
        // if we couldn't find an access subtree id for this reference id
1159
        if (!findAccessObject)
1160
        {
1161
          throw new SAXException("The referenceid: " + referenceId +
1162
                               " is not access subtree");
1163
        }//if
1164
      }//else
1165
      
1166
    }//if
1167
    else
1168
    {
1169
      // couldn't find a access section object 
1170
      MetaCatUtil.debugMessage("couldn't find access control for document: "+
1171
                                docid, 35);
1172
    }
1173
    
1174
  }//writeTopLevelAccessRuletoDB
1175
   
1176
   /* The method to write addtional access rule into db. */
1177
  private void writeAddtionalAccessRuleToDB() throws SAXException
1178
  {
1179
    
1180
     PreparedStatement pstmt = null;
1181
     boolean topLevel =false;
1182
    // go through the vector which contains the additional access control 
1183
    //hashtable. Each hashtable has info for one additonalmetadata container 
1184
   for (int j= 0; j < additionalAccessMapList.size(); j++)
1185
   {
1186
     
1187
     Hashtable accessControlMap = 
1188
                                (Hashtable)additionalAccessMapList.elementAt(j);
1189
     // additional access rule
1190
     Enumeration en = accessControlMap.keys();
1191
     
1192
     while(en.hasMoreElements())
1193
     {
1194
       try
1195
       {
1196
         // Get subsection id
1197
          String subSectionId = (String)en.nextElement();
1198
          MetaCatUtil.debugMessage("sub section id in additional access mapping"
1199
                                   +"(go through): "+ subSectionId, 35);
1200
          
1201
          if (subSectionId == null)
1202
          {
1203
            // if id is null, terminate the program
1204
            throw new SAXException("subtree id is null");
1205
          }
1206
          // Get AccessSection Object
1207
          Object accessSectionObj = accessControlMap.get(subSectionId);
1208
          if (accessSectionObj == null)
1209
          {
1210
            // if accesssection is null, terminate the program
1211
            throw new SAXException("access subtree is null");
1212
          }
1213
          else
1214
          {
1215
            AccessSection accessControlObj = (AccessSection)accessSectionObj;
1216
            // if the access section is not references, write it to db
1217
            if (accessControlObj.getReferences() == null)
1218
            {
1219
              writeGivenAccessRuleIntoDB(accessControlObj, topLevel, 
1220
                                         subSectionId);
1221
            }
1222
            else
1223
            {
1224
              // this is a reference and go trough the vector which contains all
1225
              // access object
1226
              String referenceId = accessControlObj.getReferences();
1227
            
1228
              boolean findAccessObject = false;
1229
              MetaCatUtil.debugMessage("referered id for additional access "+
1230
                                     "mapping(go through): "+ referenceId, 35);
1231
              for (int i=0; i<accessObjectList.size(); i++)
1232
              {
1233
                AccessSection accessObj = 
1234
                                (AccessSection)accessObjectList.elementAt(i);
1235
                String accessObjId = accessObj.getSubTreeId();
1236
                MetaCatUtil.debugMessage("access obj id in the list(go through): "
1237
                                        + accessObjId, 35);
1238
                if (referenceId != null && accessObj != null &&
1239
                    referenceId.equals(accessObjId))
1240
                {
1241
                  writeGivenAccessRuleIntoDB(accessObj, topLevel, subSectionId);
1242
                  findAccessObject = true;
1243
                }//if
1244
              }//for
1245
              // if we couldn't find an access subtree id for this reference id
1246
              if (!findAccessObject)
1247
              {
1248
                throw new SAXException("The referenceid: " + referenceId +
1249
                               " is not access subtree");
1250
              }//if
1251
            }//else
1252
          }//else
1253
       }//try
1254
       catch (Exception e)
1255
       {
1256
         
1257
         MetaCatUtil.debugMessage("error in EmlSAXHandler.writeAddtionalAccess"
1258
                                   + ": "+e.getMessage(), 30);
1259
         throw new SAXException(e.getMessage());
1260
       }
1261
     }//while
1262
    }//for
1263
  }//writeAccessRuletoDB
1264
  
1265
  /* Write a gaven access rule into db*/
1266
  private void writeGivenAccessRuleIntoDB(AccessSection accessSection, 
1267
                                         boolean topLevel, String subSectionId) 
1268
                                         throws SAXException
1269
  {
1270
     if (accessSection == null)
1271
     {
1272
       throw new SAXException("The access object is null");
1273
     }
1274
     
1275
      String permOrder = accessSection.getPermissionOrder();
1276
      String sql = null;
1277
      PreparedStatement pstmt = null;
1278
      if (topLevel)
1279
      {
1280
        sql = "INSERT INTO xml_access (docid, principal_name, permission, "+
1281
                 "perm_type, perm_order, accessfileid) VALUES " +
1282
                 " (?, ?, ?, ?, ?, ?)";
1283
      }
1284
      else
1285
      {
1286
        sql ="INSERT INTO xml_access (docid,principal_name, "+ 
1287
             "permission, perm_type, perm_order, accessfileid, subtreeid, "+
1288
             " startnodeid, endnodeid) VALUES" +
1289
             " (?, ?, ?, ?, ?, ?, ?, ?, ?)";
1290
      }
1291
      try 
1292
      {
1293
     
1294
        pstmt = connection.prepareStatement(sql);
1295
        // Increase DBConnection usage count
1296
        connection.increaseUsageCount(1);
1297
        // Bind the values to the query
1298
        pstmt.setString(1, docid);
1299
        MetaCatUtil.debugMessage("Docid in accesstable: "+ docid, 35);
1300
        pstmt.setString(6, docid);
1301
        MetaCatUtil.debugMessage("Accessfileid in accesstable: "+ docid, 35);
1302
        pstmt.setString(5, permOrder);
1303
        MetaCatUtil.debugMessage("PermOder in accesstable: "+ permOrder, 35);
1304
        // if it is not top level, set subsection id
1305
        if (!topLevel)
1306
        {
1307
          long startNodeId = 0;
1308
          long endNodeId = 0;
1309
          // for subtree should specify the
1310
          if (subSectionId == null)
1311
          {
1312
            throw new SAXException("The subsection is null");
1313
          }
1314
          // go through the substree list vector and found the start node id
1315
          // and stop node id for this subtree id
1316
          for (int i=0; i<subTreeList.size(); i++)
1317
          {
1318
            SubTree tree = (SubTree)subTreeList.elementAt(i);
1319
            String subTreeId = tree.getSubTreeId();
1320
            if (subSectionId.equals(subTreeId))
1321
            {
1322
              startNodeId = tree.getStartNodeId();
1323
              endNodeId = tree.getEndNodeId(); 
1324
            }//if
1325
          }//for
1326
          if (startNodeId == 0 || endNodeId == 0)
1327
          {
1328
            throw new SAXException("Could find the subtree"
1329
                                   + "for this id: "+subSectionId);
1330
          }
1331
          pstmt.setString(7, subSectionId);
1332
          MetaCatUtil.debugMessage("SubSectionId in accesstable: "+ 
1333
                                    subSectionId, 35);
1334
          pstmt.setLong(8, startNodeId);
1335
          MetaCatUtil.debugMessage("Start node id is: " + startNodeId, 35);
1336
          pstmt.setLong(9, endNodeId);
1337
          MetaCatUtil.debugMessage("End node id is: " + endNodeId, 35);
1338
          
1339
        }
1340
      
1341
        Vector accessRules = accessSection.getAccessRules();
1342
        // go through every rule
1343
        for (int i=0; i<accessRules.size(); i++)
1344
        {
1345
          AccessRule rule = (AccessRule)accessRules.elementAt(i);
1346
          String permType = rule.getPermissionType();
1347
          int permission = rule.getPermission();
1348
          pstmt.setInt(3, permission);
1349
          MetaCatUtil.debugMessage("permission in accesstable: "+ permission, 35);
1350
          pstmt.setString(4, permType);
1351
          MetaCatUtil.debugMessage("Permtype in accesstable: "+ permType, 35);
1352
          // go through every principle in rule
1353
          Vector nameVector = rule.getPrincipal();
1354
          for ( int j = 0; j < nameVector.size(); j++ ) 
1355
          {
1356
            String prName = (String)nameVector.elementAt(j);
1357
            pstmt.setString(2, prName);
1358
            MetaCatUtil.debugMessage("Principal in accesstable: "+prName, 35);
1359
            pstmt.execute();
1360
          }//for
1361
        }//for
1362
        pstmt.close();
1363
      }//try 
1364
      catch (SQLException e) 
1365
      {
1366
        throw new 
1367
        SAXException("EMLSAXHandler.writeAccessRuletoDB(): " + e.getMessage());
1368
      }//catch
1369
      finally
1370
      {
1371
        try
1372
        {
1373
          pstmt.close();
1374
        }
1375
        catch(SQLException ee)
1376
        {
1377
          throw new 
1378
          SAXException("EMLSAXHandler.writeAccessRuletoDB(): " + 
1379
          ee.getMessage());
1380
        }
1381
      }//finally
1382
     
1383
  }//writeGivenAccessRuleIntoDB
1384
  
1385
  /* Delete from db all permission for resources related to @aclid if any.*/
1386
  private void deletePermissionsInAccessTable(String aclid) 
1387
          throws SAXException 
1388
  {
1389
    Statement stmt = null;
1390
    try
1391
    {
1392
      // delete all acl records for resources related to @aclid if any
1393
      stmt = connection.createStatement();
1394
      // Increase DBConnection usage count
1395
      connection.increaseUsageCount(1);
1396
      stmt.execute("DELETE FROM xml_access WHERE accessfileid = '" + aclid +
1397
                   "'"); 
1398
    
1399
    }
1400
    catch (SQLException e)
1401
    {
1402
      throw new SAXException(e.getMessage());
1403
    }
1404
    finally
1405
    {
1406
      try
1407
      {
1408
        stmt.close();
1409
      }
1410
      catch (SQLException ee)
1411
      {
1412
        throw new SAXException(ee.getMessage());
1413
      }
1414
    }
1415
  }//deletePermissionsInAccessTable
1416
  
1417
  
1418
  /* In order to make sure only usr has "all" permission can update access
1419
   * subtree in eml document we need to keep access subtree info in 
1420
   * xml_accesssubtree table, such as docid, version, startnodeid, endnodeid
1421
   */
1422
  private void writeAccessSubTreeIntoDB(AccessSection accessSection, 
1423
                                         String level) 
1424
                                         throws SAXException
1425
  {
1426
     if (accessSection == null)
1427
     {
1428
       throw new SAXException("The access object is null");
1429
     }
1430
     
1431
      String sql = null;
1432
      PreparedStatement pstmt = null;
1433
      sql = "INSERT INTO xml_accesssubtree (docid, rev, controllevel, "+
1434
                 "subtreeid, startnodeid, endnodeid) VALUES " +
1435
                 " (?, ?, ?, ?, ?, ?)";
1436
      try 
1437
      {
1438
     
1439
        pstmt = connection.prepareStatement(sql);
1440
        // Increase DBConnection usage count
1441
        connection.increaseUsageCount(1);
1442
        long startNodeId = accessSection.getStartNodeId();
1443
        long endNodeId = accessSection.getEndNodeId();
1444
        String sectionId = accessSection.getSubTreeId();
1445
        // Bind the values to the query
1446
        pstmt.setString(1, docid);
1447
        MetaCatUtil.debugMessage("Docid in access-subtreetable: "+ docid, 35);
1448
        pstmt.setString(2, revision );
1449
        MetaCatUtil.debugMessage("rev in accesssubtreetable: "+ revision, 35);
1450
        pstmt.setString(3, level);
1451
        MetaCatUtil.debugMessage("contorl level in access-subtree table: "+
1452
                                  level, 35);
1453
        pstmt.setString(4, sectionId);
1454
        MetaCatUtil.debugMessage("Subtree id in access-subtree table: "+ 
1455
                                  sectionId, 35);
1456
        pstmt.setLong(5, startNodeId);
1457
        MetaCatUtil.debugMessage("Start node id is: " + startNodeId, 35);
1458
        pstmt.setLong(6, endNodeId);
1459
        MetaCatUtil.debugMessage("End node id is: " + endNodeId, 35);
1460
        pstmt.execute();
1461
        pstmt.close();
1462
      }//try 
1463
      catch (SQLException e) 
1464
      {
1465
        throw new 
1466
        SAXException("EMLSAXHandler.writeAccessSubTreeIntoDB(): " + 
1467
                      e.getMessage());
1468
      }//catch
1469
      finally
1470
      {
1471
        try
1472
        {
1473
          pstmt.close();
1474
        }
1475
        catch(SQLException ee)
1476
        {
1477
          throw new 
1478
          SAXException("EMLSAXHandler.writeAccessSubTreeIntoDB(): " + 
1479
          ee.getMessage());
1480
        }
1481
      }//finally
1482
     
1483
  }//writeAccessSubtreeIntoDB
1484
  
1485
   /* Delete every access subtree record from xml_accesssubtree.*/
1486
  private void deleteAccessSubTreeRecord(String docId) throws SAXException 
1487
  {
1488
    Statement stmt = null;
1489
    try
1490
    {
1491
      // delete all acl records for resources related to @aclid if any
1492
      stmt = connection.createStatement();
1493
      // Increase DBConnection usage count
1494
      connection.increaseUsageCount(1);
1495
      stmt.execute("DELETE FROM xml_accesssubtree WHERE docid = '" + docId + "'"); 
1496
   
1497
    }
1498
    catch (SQLException e)
1499
    {
1500
      throw new SAXException(e.getMessage());
1501
    }
1502
    finally
1503
    {
1504
      try
1505
      {
1506
        stmt.close();
1507
      }
1508
      catch (SQLException ee)
1509
      {
1510
        throw new SAXException(ee.getMessage());
1511
      }
1512
    }
1513
  }//deleteAccessSubTreeRecord
1514
  
1515
  // write inline data into file system and return file name(without path)
1516
  private StringBuffer writeInlineDataIntoFile(StringBuffer data) 
1517
                                               throws SAXException
1518
  {
1519
    StringBuffer fileNameBuffer = null;
1520
    String fileName = null;
1521
    String docidWithoutRev = MetaCatUtil.getDocIdFromString(docid);
1522
    String path = MetaCatUtil.getOption("inlinedatafilepath");
1523
    String seperator = MetaCatUtil.getOption("accNumSeparator");
1524
    // the new file name will look like path/docid.rev.2
1525
    fileName = docidWithoutRev + seperator+revision+seperator +inLineDataIndex;
1526
    File inlineDataDirectory = new File(path);
1527
    File newFile = new File(inlineDataDirectory, fileName); 
1528
    // incease inLinedataindex for next one
1529
    inLineDataIndex++ ;
1530
    try
1531
    {
1532
      FileWriter writer = new FileWriter(newFile);
1533
      writer.write(data.toString());
1534
      writer.close();
1535
    }
1536
    catch (Exception e)
1537
    {
1538
      throw new SAXException(e.getMessage());
1539
    }
1540
    
1541
    fileNameBuffer = new StringBuffer(fileName);
1542
    return fileNameBuffer;
1543
  }
1544
  
1545
  /* In eml2, the inline data wouldn't store in db, it store in file system
1546
   * The db stores file name(without path).
1547
   */
1548
  public static String readInlineDataFromFileSystem(String fileName) 
1549
                                              throws McdbException
1550
  {
1551
    String data = null;
1552
    String path = MetaCatUtil.getOption("inlinedatafilepath");
1553
    // the new file name will look like path/docid.rev.2
1554
    File inlineDataDirectory = new File(path);
1555
    File dataFile = new File(inlineDataDirectory, fileName);
1556
    try
1557
    {
1558
      FileReader fileReader = new FileReader(dataFile);
1559
      BufferedReader stringReader = new BufferedReader(fileReader);
1560
      // read first line of data
1561
      String tmp = stringReader.readLine();
1562
      // pass first line data to data varible
1563
      data = tmp;
1564
      // at the end tmp will be null
1565
      while (tmp != null)
1566
      {
1567
        // read a new line
1568
        tmp = stringReader.readLine();
1569
        // append new line to data
1570
        if (tmp != null)
1571
        {
1572
          data = data+tmp;
1573
        }
1574
      }
1575
      
1576
    }
1577
    catch (Exception e)
1578
    {
1579
      throw new McdbException(e.getMessage());
1580
    }
1581
    MetaCatUtil.debugMessage("the inline data retrieve from file: "+data, 50);
1582
    return data;
1583
  }
1584
}
(33-33/56)