Project

General

Profile

1 1398 tao
/**
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$'
11
 *     '$Date$'
12
 * '$Revision$'
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 1517 tao
import java.io.BufferedReader;
33 1459 tao
import java.io.File;
34 1517 tao
import java.io.FileReader;
35 1459 tao
import java.io.FileWriter;
36 1398 tao
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 1405 tao
   private boolean processTopLeverAccess = false;
62
   private boolean processAdditionalAccess = false;
63 1534 tao
   private boolean processOtherAccess = false;
64 1405 tao
   private AccessSection accessObject= null;
65
   private AccessRule accessRule = null;
66 1422 tao
   private Vector accessObjectList = new Vector(); // store every access rule
67 1405 tao
   private Hashtable topLevelAccessControlMap = new Hashtable();
68 1473 tao
   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 1413 tao
   private Vector describesId = new Vector(); // store the ids in
74
                                      //additionalmetadata/describes
75 1417 tao
   private Stack subTreeInfoStack = new Stack();
76
   private Vector subTreeList = new Vector();// store the final subtree
77 1459 tao
   private int inLineDataIndex = 1;
78 1534 tao
   private Hashtable unChangableSubTreeHash = new Hashtable();
79 1509 tao
   private Stack currentUnChangedableSubtreeNodeStack;
80
   private boolean startCriticalSubTree = false;
81 1512 tao
   private boolean firstElementForCriticalSubTree = false;
82 1509 tao
   private String firstElementNameForCriticalSubTree;
83 1540 tao
   private boolean needCheckingAccessModule = false;
84
   private Vector unChangableAccessSubTreeVector;
85
   private AccessSection topAccessSection;
86 1413 tao
87 1417 tao
88 1398 tao
   // Constant
89 1534 tao
   private static final String EML ="eml";
90 1398 tao
   private static final String DESCRIBES = "describes";
91 1405 tao
   private static final String ADDITIONALMETADATA = "additionalMetadata";
92
   private static final String ORDER = "order";
93
   private static final String ID ="id";
94 1413 tao
   private static final String REFERENCES = "references";
95 1459 tao
   public  static final String INLINE = "inline";
96 1509 tao
   private static final String PERMISSIONERROR ="User try to update a subtree"+
97
                               " which it doesn't have write permission!";
98 1540 tao
   private static final String TOPLEVEL = "top";
99
   private static final String SUBTREELEVEL ="subtree";
100 1459 tao
101 1408 tao
    /** 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 1509 tao
                              throws SAXException
118 1408 tao
   {
119
     super(conn, action, docid, revision, user, groups, pub, serverCode);
120 1509 tao
     // Get the unchangable subtrees (user doesn't have write permission)
121
     try
122
     {
123
       PermissionController control = new PermissionController(docid);
124 1534 tao
       //unChangableSubTreeHash = getUnchangableSubTree(control, user, groups);
125 1540 tao
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 1509 tao
     }
136
     catch (Exception e)
137
     {
138
       throw new SAXException(e.getMessage());
139
     }
140 1408 tao
   }
141
142 1509 tao
   /* 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 1540 tao
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 1398 tao
   /** 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 1422 tao
     try
269
     {
270 1398 tao
       parentNode = (DBSAXNode)nodeStack.peek();
271 1422 tao
     }
272
     catch (EmptyStackException e)
273
     {
274 1398 tao
       parentNode = null;
275
     }
276 1412 tao
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 1511 tao
       //compare text node data
282 1512 tao
       if (startCriticalSubTree)
283 1511 tao
       {
284
            NodeRecord node = null;
285
            try
286
            {
287
              node = (NodeRecord)currentUnChangedableSubtreeNodeStack.pop();
288
            }
289
            catch (EmptyStackException ee)
290
            {
291 1512 tao
              MetaCatUtil.debugMessage("Node stack is empty for text data in startElement", 35);
292 1511 tao
              throw new SAXException(PERMISSIONERROR);
293
            }
294 1512 tao
            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 1511 tao
            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 1412 tao
       // write the textbuffer into db for parent node.
321 1417 tao
        endNodeId = writeTextForDBSAXNode(textBuffer, parentNode);
322 1412 tao
        // rest hitTextNode
323
        hitTextNode =false;
324
        // reset textbuffer
325
        textBuffer = null;
326
        textBuffer = new StringBuffer();
327
328
     }
329
330 1417 tao
331 1398 tao
     // 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 1417 tao
       try
362
       {
363 1398 tao
         // 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 1417 tao
         if ( systemid != null )
373
         {
374 1398 tao
           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 1417 tao
       }
407
       catch (Exception ane)
408
       {
409 1398 tao
         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 1417 tao
     // 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 1398 tao
     // Add all of the namespaces
423
     String prefix;
424
     String nsuri;
425
     Enumeration prefixes = namespaces.keys();
426 1417 tao
     while ( prefixes.hasMoreElements() )
427
     {
428 1398 tao
       prefix = (String)prefixes.nextElement();
429
       nsuri = (String)namespaces.get(prefix);
430 1417 tao
       endNodeId = currentNode.setNamespace(prefix, nsuri, docid);
431 1398 tao
     }
432 1511 tao
433 1398 tao
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 1417 tao
       endNodeId =
440
                currentNode.setAttribute(attributeName, attributeValue, docid);
441 1398 tao
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 1417 tao
       else if (attributeName !=null && attributeName.equals(ID))
454
       {
455 1511 tao
456 1512 tao
457 1509 tao
         //check unchangedable subtree hash if contains this subtree id
458 1511 tao
         if (unChangableSubTreeHash.containsKey(attributeValue))
459 1509 tao
         {
460 1511 tao
           // this subtree couldn't be changed by the user and move it from hash
461 1509 tao
           SubTree currentUnChangedableSubtree = (SubTree)
462 1511 tao
                                  unChangableSubTreeHash.remove(attributeValue);
463 1509 tao
           currentUnChangedableSubtreeNodeStack = currentUnChangedableSubtree.
464
                                                         getSubTreeNodeStack();
465
           startCriticalSubTree = true;
466
           firstElementForCriticalSubTree = true;
467
         }
468
469 1417 tao
         // 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 1512 tao
     }//for
482 1408 tao
483 1398 tao
     // handle access stuff
484
     if (localName.equals(ACCESS))
485
     {
486
       // if it is in addtionalmetacat
487 1405 tao
       if (parentNode.getTagName() == ADDITIONALMETADATA)
488 1398 tao
       {
489 1422 tao
         processAdditionalAccess = true;
490 1405 tao
491 1398 tao
       }
492 1405 tao
       else
493
       {
494 1534 tao
         //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 1405 tao
512
       }
513
       // create access object
514 1537 tao
       accessObject = new AccessSection();
515 1408 tao
         // set permission order
516 1405 tao
       String permOrder = currentNode.getAttribute(ORDER);
517
       accessObject.setPermissionOrder(permOrder);
518
       // set access id
519
       String accessId = currentNode.getAttribute(ID);
520 1540 tao
       accessObject.setSubTreeId(accessId);
521
       accessObject.setStartNodeId(startNodeId);
522 1405 tao
523
     }
524 1413 tao
     // Set up a access rule for allow
525 1422 tao
     else if (parentNode.getTagName() != null &&
526 1408 tao
       (parentNode.getTagName()).equals(ACCESS) && localName.equals(ALLOW))
527 1405 tao
     {
528 1408 tao
529
       accessRule = new AccessRule();
530
531 1405 tao
       //set permission type "allow"
532
       accessRule.setPermissionType(ALLOW);
533 1408 tao
534 1405 tao
     }
535 1413 tao
     // set up an access rule for den
536
     else if (parentNode.getTagName() != null
537 1408 tao
       && (parentNode.getTagName()).equals(ACCESS) && localName.equals(DENY))
538 1405 tao
     {
539
       accessRule = new AccessRule();
540
       //set permission type "allow"
541
       accessRule.setPermissionType(DENY);
542
     }
543 1473 tao
544 1398 tao
     // 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 1422 tao
550 1509 tao
    // handle critical subtree
551
    if (startCriticalSubTree && firstElementForCriticalSubTree)
552
    {
553
      //store the element name
554
      firstElementNameForCriticalSubTree = qName;
555 1511 tao
      firstElementForCriticalSubTree = false;
556 1509 tao
    }//for first element
557 1512 tao
    // handle critical subtree
558
    if (startCriticalSubTree)
559 1509 tao
    {
560
      //Get element subtree node stack (element node)
561 1511 tao
      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 1512 tao
      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 1509 tao
      // if this node is not element or local name not equal or name space not
582
      // equals, throw an exception
583 1511 tao
      if (!elementNode.getNodeType().equals("ELEMENT") ||
584 1512 tao
          !localName.equals(elementNode.getNodeName()))
585
        //  (uri != null && !uri.equals(elementNode.getNodePrefix())))
586 1509 tao
      {
587 1511 tao
        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 1509 tao
        throw new SAXException(PERMISSIONERROR);
598
      }
599 1511 tao
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 1512 tao
     }//while
638 1511 tao
639 1509 tao
      //compare attributes
640
      for (int i=0; i<atts.getLength(); i++)
641
      {
642 1511 tao
        NodeRecord attriNode = null;
643
        try
644
        {
645
          attriNode = (NodeRecord)currentUnChangedableSubtreeNodeStack.pop();
646 1512 tao
647 1511 tao
        }
648
        catch (EmptyStackException ee)
649
        {
650
          MetaCatUtil.debugMessage("Node stack is empty for attribute data", 35);
651
          throw new SAXException(PERMISSIONERROR);
652
        }
653 1509 tao
        String attributeName = atts.getQName(i);
654
        String attributeValue = atts.getValue(i);
655 1512 tao
        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 1509 tao
        if (!attriNode.getNodeType().equals("ATTRIBUTE") ||
669
            !attributeName.equals(attriNode.getNodeName()) ||
670
            !attributeValue.equals(attriNode.getNodeData()))
671
        {
672 1511 tao
          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 1509 tao
          throw new SAXException(PERMISSIONERROR);
685
        }
686 1511 tao
      }//for
687 1509 tao
688 1511 tao
    }
689
    // reset name space
690
    namespaces = null;
691
    namespaces = new Hashtable();
692 1398 tao
  }
693 1405 tao
694 1412 tao
695 1405 tao
  /** 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 1398 tao
701 1405 tao
     // Get the node from the stack
702
     DBSAXNode currentNode = (DBSAXNode)nodeStack.pop();
703 1417 tao
     String currentTag = currentNode.getTagName();
704 1412 tao
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 1428 tao
         if ( data.toUpperCase().equals(READSTRING) )
726 1412 tao
         {
727
           permission = permission | READ;
728
         }
729 1428 tao
         else if ( data.toUpperCase().equals(WRITESTRING) )
730 1412 tao
         {
731
           permission = permission | WRITE;
732
         }
733 1428 tao
         else if ( data.toUpperCase().equals(CHMODSTRING))
734 1412 tao
         {
735
           permission = permission | CHMOD;
736
         }
737 1428 tao
         else if ( data.toUpperCase().equals(ALLSTRING) )
738 1412 tao
         {
739
          permission = permission | ALL;
740
         }
741
         accessRule.setPermission(permission);
742
       }
743 1413 tao
       // put additionalmetadata/describes into vector
744
       else if (currentTag.equals(DESCRIBES))
745
       {
746
          data = (textBuffer.toString()).trim();
747
          describesId.add(data);
748
       }
749 1473 tao
       else if (currentTag.equals(REFERENCES) &&
750 1534 tao
               (processTopLeverAccess ||
751
                processAdditionalAccess || processOtherAccess))
752 1413 tao
       {
753
         // get reference
754
         data = (textBuffer.toString()).trim();
755 1473 tao
         // put reference id into accessSection
756
         accessObject.setReferences(data);
757 1413 tao
758
       }
759 1459 tao
       // 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 1511 tao
          //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 1512 tao
            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 1511 tao
            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 1459 tao
          endNodeId = writeTextForDBSAXNode(textBuffer, currentNode);
805
       }
806
       else
807
       {
808 1473 tao
          MetaCatUtil.debugMessage("Write inline data into file system", 35);
809 1517 tao
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 1459 tao
          // 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 1412 tao
     }//if
849
850 1512 tao
     //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 1412 tao
     //set hitText false
860
     hitTextNode = false;
861
     // reset textbuff
862
     textBuffer = null;
863
     textBuffer = new StringBuffer();
864 1417 tao
865
     // hand sub stree stuff
866 1422 tao
     if (!subTreeInfoStack.empty())
867
     {
868
       SubTree tree = (SubTree)subTreeInfoStack.peek();// get last subtree
869
       if (tree != null && tree.getStartElementName() != null &&
870 1417 tao
         (tree.getStartElementName()).equals(currentTag))
871 1422 tao
       {
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 1412 tao
881 1405 tao
     // access stuff
882 1417 tao
     if (currentTag.equals(ALLOW) || currentTag.equals(DENY))
883 1405 tao
     {
884 1410 tao
       // finish parser a ccess rule and  assign it to new one
885
       AccessRule newRule = accessRule;
886 1405 tao
       //add the new rule to access section object
887
       accessObject.addAccessRule(newRule);
888 1410 tao
       // reset access rule
889 1405 tao
       accessRule = null;
890
     }
891 1417 tao
     else if (currentTag.equals(ACCESS))
892 1405 tao
     {
893 1410 tao
       // finish parse a access setction and assign it to new one
894 1540 tao
       accessObject.setEndNodeId(endNodeId);
895 1410 tao
       AccessSection newAccessObject = accessObject;
896 1422 tao
       if (newAccessObject != null)
897 1405 tao
       {
898 1422 tao
        // add the accessSection into a vector to store it
899 1473 tao
        // if it is not a reference, need to store it
900
        if ( newAccessObject.getReferences() == null)
901
        {
902
          accessObjectList.add(newAccessObject);
903
        }
904 1422 tao
        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 1473 tao
916 1422 tao
          for ( int i=0; i<describesId.size(); i++)
917
          {
918 1473 tao
919 1422 tao
            String subId = (String)describesId.elementAt(i);
920
            if (subId != null)
921
            {
922
              additionalAccessControlMap.put(subId, newAccessObject);
923
            }//if
924
          }//for
925 1473 tao
          // add this hashtable in to vector
926 1422 tao
927 1473 tao
          additionalAccessMapList.add(additionalAccessControlMap);
928
          // reset this hashtable in order to store another additional
929
          //accesscontrol
930
          additionalAccessControlMap = null;
931
          additionalAccessControlMap = new Hashtable();
932 1422 tao
        }//if
933
       }//if
934 1405 tao
       //reset access section object
935
       accessObject = null;
936 1422 tao
       // reset flag
937
       processAdditionalAccess =false;
938
       processTopLeverAccess =false;
939 1534 tao
       processOtherAccess = false;
940 1405 tao
     }
941 1417 tao
     else if (currentTag.equals(ADDITIONALMETADATA))
942 1413 tao
     {
943
        //reset describesId
944 1422 tao
        describesId = null;
945 1413 tao
        describesId = new Vector();
946
     }
947 1398 tao
   }
948 1405 tao
949 1511 tao
   /**
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 1512 tao
         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 1511 tao
         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 1405 tao
   /** SAX Handler that receives notification of end of the document */
1074
   public void endDocument() throws SAXException
1075 1398 tao
   {
1076 1405 tao
     MetaCatUtil.debugMessage("end Document", 50);
1077 1511 tao
     // 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 1405 tao
     // write access rule to db
1086
     writeAccessRuleToDB();
1087 1511 tao
1088 1405 tao
     // 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 1511 tao
1102 1405 tao
   }
1103 1413 tao
1104
  /* The method to write all access rule intodb */
1105 1405 tao
  private void writeAccessRuleToDB() throws SAXException
1106
  {
1107 1423 tao
    //Delete old permssion
1108
    deletePermissionsInAccessTable(docid);
1109 1413 tao
    //write top leve access rule
1110
    writeTopLevelAccessRuleToDB();
1111
    //write additional access rule
1112 1534 tao
    //writeAddtionalAccessRuleToDB();
1113 1413 tao
  }//writeAccessRuleToDB
1114
1115
  /* The method to write top level access rule into db. */
1116
  private void writeTopLevelAccessRuleToDB() throws SAXException
1117
  {
1118 1398 tao
1119 1405 tao
    // for top document level
1120 1413 tao
    Object accessSection = topLevelAccessControlMap.get(docid);
1121 1422 tao
    boolean top = true;
1122
    String subSectionId = null;
1123 1473 tao
    if ( accessSection != null )
1124 1408 tao
    {
1125 1473 tao
       AccessSection accessSectionObj = (AccessSection)accessSection;
1126 1540 tao
       // 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 1473 tao
       // 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 1540 tao
          String accessObjId = accessObj.getSubTreeId();
1149 1473 tao
          if (referenceId != null && accessObj != null &&
1150
              referenceId.equals(accessObjId))
1151
          {
1152
            writeGivenAccessRuleIntoDB(accessObj, top, subSectionId);
1153 1540 tao
            // write the reference access into xml_accesssubtree too
1154
            writeAccessSubTreeIntoDB(accessObj, SUBTREELEVEL);
1155 1473 tao
            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 1413 tao
    }//if
1167
    else
1168
    {
1169 1481 tao
      // couldn't find a access section object
1170
      MetaCatUtil.debugMessage("couldn't find access control for document: "+
1171
                                docid, 35);
1172 1408 tao
    }
1173 1413 tao
1174
  }//writeTopLevelAccessRuletoDB
1175 1405 tao
1176 1413 tao
   /* The method to write addtional access rule into db. */
1177
  private void writeAddtionalAccessRuleToDB() throws SAXException
1178
  {
1179
1180
     PreparedStatement pstmt = null;
1181 1473 tao
     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 1413 tao
     // additional access rule
1190 1473 tao
     Enumeration en = accessControlMap.keys();
1191
1192 1413 tao
     while(en.hasMoreElements())
1193 1473 tao
     {
1194 1413 tao
       try
1195
       {
1196
         // Get subsection id
1197
          String subSectionId = (String)en.nextElement();
1198 1422 tao
          MetaCatUtil.debugMessage("sub section id in additional access mapping"
1199 1473 tao
                                   +"(go through): "+ subSectionId, 35);
1200 1413 tao
1201
          if (subSectionId == null)
1202
          {
1203 1473 tao
            // if id is null, terminate the program
1204
            throw new SAXException("subtree id is null");
1205 1413 tao
          }
1206
          // Get AccessSection Object
1207 1473 tao
          Object accessSectionObj = accessControlMap.get(subSectionId);
1208
          if (accessSectionObj == null)
1209 1413 tao
          {
1210 1473 tao
            // if accesssection is null, terminate the program
1211
            throw new SAXException("access subtree is null");
1212 1413 tao
          }
1213
          else
1214
          {
1215 1473 tao
            AccessSection accessControlObj = (AccessSection)accessSectionObj;
1216
            // if the access section is not references, write it to db
1217
            if (accessControlObj.getReferences() == null)
1218 1422 tao
            {
1219 1473 tao
              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 1422 tao
                                (AccessSection)accessObjectList.elementAt(i);
1235 1540 tao
                String accessObjId = accessObj.getSubTreeId();
1236 1473 tao
                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 1422 tao
              {
1248 1473 tao
                throw new SAXException("The referenceid: " + referenceId +
1249
                               " is not access subtree");
1250 1422 tao
              }//if
1251 1473 tao
            }//else
1252
          }//else
1253 1413 tao
       }//try
1254
       catch (Exception e)
1255
       {
1256 1422 tao
1257 1413 tao
         MetaCatUtil.debugMessage("error in EmlSAXHandler.writeAddtionalAccess"
1258
                                   + ": "+e.getMessage(), 30);
1259 1422 tao
         throw new SAXException(e.getMessage());
1260 1413 tao
       }
1261 1473 tao
     }//while
1262
    }//for
1263 1413 tao
  }//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 1405 tao
1275 1413 tao
      String permOrder = accessSection.getPermissionOrder();
1276
      String sql = null;
1277
      PreparedStatement pstmt = null;
1278
      if (topLevel)
1279 1405 tao
      {
1280 1413 tao
        sql = "INSERT INTO xml_access (docid, principal_name, permission, "+
1281
                 "perm_type, perm_order, accessfileid) VALUES " +
1282
                 " (?, ?, ?, ?, ?, ?)";
1283
      }
1284
      else
1285 1405 tao
      {
1286 1422 tao
        sql ="INSERT INTO xml_access (docid,principal_name, "+
1287
             "permission, perm_type, perm_order, accessfileid, subtreeid, "+
1288
             " startnodeid, endnodeid) VALUES" +
1289
             " (?, ?, ?, ?, ?, ?, ?, ?, ?)";
1290 1405 tao
      }
1291 1413 tao
      try
1292 1405 tao
      {
1293 1413 tao
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 1473 tao
        MetaCatUtil.debugMessage("Docid in accesstable: "+ docid, 35);
1300 1413 tao
        pstmt.setString(6, docid);
1301 1473 tao
        MetaCatUtil.debugMessage("Accessfileid in accesstable: "+ docid, 35);
1302 1413 tao
        pstmt.setString(5, permOrder);
1303 1473 tao
        MetaCatUtil.debugMessage("PermOder in accesstable: "+ permOrder, 35);
1304 1413 tao
        // if it is not top level, set subsection id
1305
        if (!topLevel)
1306
        {
1307 1422 tao
          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 1413 tao
          pstmt.setString(7, subSectionId);
1332
          MetaCatUtil.debugMessage("SubSectionId in accesstable: "+
1333 1473 tao
                                    subSectionId, 35);
1334 1422 tao
          pstmt.setLong(8, startNodeId);
1335 1473 tao
          MetaCatUtil.debugMessage("Start node id is: " + startNodeId, 35);
1336 1422 tao
          pstmt.setLong(9, endNodeId);
1337 1473 tao
          MetaCatUtil.debugMessage("End node id is: " + endNodeId, 35);
1338 1422 tao
1339 1413 tao
        }
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 1473 tao
          MetaCatUtil.debugMessage("permission in accesstable: "+ permission, 35);
1350 1413 tao
          pstmt.setString(4, permType);
1351 1473 tao
          MetaCatUtil.debugMessage("Permtype in accesstable: "+ permType, 35);
1352 1413 tao
          // 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 1473 tao
            MetaCatUtil.debugMessage("Principal in accesstable: "+prName, 35);
1359 1413 tao
            pstmt.execute();
1360
          }//for
1361
        }//for
1362
        pstmt.close();
1363
      }//try
1364
      catch (SQLException e)
1365
      {
1366 1405 tao
        throw new
1367 1413 tao
        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 1398 tao
1383 1423 tao
  }//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 1459 tao
  }//deletePermissionsInAccessTable
1416
1417 1540 tao
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 1459 tao
  // 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 1461 tao
      writer.close();
1535 1459 tao
    }
1536
    catch (Exception e)
1537
    {
1538
      throw new SAXException(e.getMessage());
1539
    }
1540
1541
    fileNameBuffer = new StringBuffer(fileName);
1542
    return fileNameBuffer;
1543 1413 tao
  }
1544 1517 tao
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 1398 tao
}