Project

General

Profile

1 2161 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 2245 sgarg
 *    Authors: Jing Tao
8 2161 tao
 *
9
 *   '$Author$'
10
 *     '$Date$'
11
 * '$Revision$'
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
 */
27
28
package edu.ucsb.nceas.metacat;
29
30
import java.io.BufferedReader;
31
import java.io.File;
32 5752 leinfelder
import java.io.FileInputStream;
33
import java.io.FileOutputStream;
34 2161 tao
import java.io.IOException;
35 5752 leinfelder
import java.io.InputStream;
36
import java.io.InputStreamReader;
37
import java.io.OutputStream;
38
import java.io.OutputStreamWriter;
39 2161 tao
import java.io.Reader;
40 5752 leinfelder
import java.io.Writer;
41 2161 tao
import java.sql.PreparedStatement;
42
import java.sql.ResultSet;
43
import java.sql.SQLException;
44
import java.sql.Statement;
45
import java.util.EmptyStackException;
46
import java.util.Enumeration;
47
import java.util.Hashtable;
48
import java.util.Stack;
49
import java.util.Vector;
50
51 2663 sgarg
import org.apache.log4j.Logger;
52 2161 tao
import org.xml.sax.Attributes;
53
import org.xml.sax.SAXException;
54
55 5090 daigle
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlInterface;
56
import edu.ucsb.nceas.metacat.accesscontrol.AccessRule;
57
import edu.ucsb.nceas.metacat.accesscontrol.AccessSection;
58 5015 daigle
import edu.ucsb.nceas.metacat.database.DBConnection;
59
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
60 5030 daigle
import edu.ucsb.nceas.metacat.properties.PropertyService;
61 4589 daigle
import edu.ucsb.nceas.metacat.util.AuthUtil;
62 5025 daigle
import edu.ucsb.nceas.metacat.util.DocumentUtil;
63 4698 daigle
import edu.ucsb.nceas.metacat.util.MetacatUtil;
64 4080 daigle
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
65
66 2161 tao
/**
67 5311 daigle
 * A database aware Class implementing callback methods for the SAX parser to
68 2161 tao
 * call when processing the XML stream and generating events
69 2245 sgarg
 * Here is the rules for user which has write permission in top level access
70
 * rules(he can update metadata but can't update access module) try to update
71
 * a document:
72 5166 daigle
 * 1. Checking access part (both in top level and additional level, node by node)
73 2245 sgarg
 *    If something was modified, reject the document. Note: for additional part
74 5311 daigle
 *    The access subtree startnode starts at "<describe>" rather than <access>.
75 2245 sgarg
 *    This is because make sure ids wouldn't be mess up by user.
76
 * 2. Checking ids in additional access part, if they points a distribution
77
 *    module with online or inline. If some ids don't, reject the documents.
78
 * 3. For inline distribution:
79
 *    If user can't read the inline data, the empty string in inline element
80
 *    will be send to user if he read this eml document(user has read access
81
 *    at top level - metadata, but user couldn't read inline data).
82 5311 daigle
 *    Here is some interested scenario: If user does have read and write
83 2245 sgarg
 *    permission in top level access rules(for metadata)
84
 *    but 1) user doesn't have read and write permission in inline data block,
85
 *    so if user update the document with some inline data rather than
86
 *    empty string in same inline data block(same distribution inline id),
87
 *    this means user updated the inline data. So the document should be
88
 *    rejected.
89 5311 daigle
 *    2) user doesn't have read permission, but has write permission in
90 2245 sgarg
 *    inline data block. If user send back inline data block with empty
91
 *    string, we will think user doesn't update inline data and we will
92
 *    copy old inline data back to the new one. If user send something
93
 *    else, we will overwrite the old inline data by new one.
94
 * 4. For online distribution:
95
 *    It is easy than inline distribution. When the user try to change a external
96
 *    document id, we will checking if the user have "all" permission to it.
97
 *    If don't have, reject the document. If have, delete the old rules and apply
98
 *    The new rules.
99
 *
100
 *
101 5166 daigle
 * Here is some info about additional access rules ( data object rules):
102 2245 sgarg
 *  The data access rules format looks like:
103
 *  <additionalMetadata>
104
 *    <describes>100</describes>
105
 *    <describes>300</describes>
106
 *    <access>rulesone</access>
107
 *  </additionalMetadata>
108
 *  <additionalMetadata>
109
 *    <describes>200</describes>
110
 *    <access>rulesthree</access>
111
 *  </additionalMetadata>
112
 *  Because eml additionalMetadata is (describes+, any) and any ocurrence is 1.
113
 *  So following xml will be rejected by xerces.
114
 *  <additionalMetadata>
115
 *    <describes>100</describes>
116
 *    <describes>300</describes>
117
 *    <other>....</other>
118
 *    <access>rulesone</access>
119
 *  </additionalMetadata>
120 2161 tao
 */
121
public class Eml200SAXHandler extends DBSAXHandler implements
122
        AccessControlInterface
123
{
124 5311 daigle
	// Boolean that tells whether we are processing top level (document level) access.
125
	// this is true when we hit an 'access' element, and the grandparent element is
126
	// 'eml' and we are not inside an 'additionalMetadata' section.  Set back to false
127
	// in endElement
128
    private boolean processTopLevelAccess = false;
129 2161 tao
130 2188 tao
    // now additionalAccess will be explained as distribution access control
131
    // - data file
132 2161 tao
    private boolean processAdditionalAccess = false;
133
134 5311 daigle
	// Boolean that tells whether we are processing other access. This is true when
135
    // we find an 'access' element inside an 'additionalMetadata' element.  Set back
136
    // to false in endElement
137 2161 tao
    private boolean processOtherAccess = false;
138
139 5311 daigle
    // if we are inside an 'access' element, we use this object to hold the
140
    // current access info
141 2161 tao
    private AccessSection accessObject = null;
142
143 5311 daigle
    // for each 'access/allow' and 'access/deny' we create a new access Rule to hold
144
    // the info
145 2161 tao
    private AccessRule accessRule = null;
146
147 2245 sgarg
    private Vector describesId = new Vector(); // store the ids in
148
                                               //additionalmetadata/describes
149 2161 tao
150 2245 sgarg
    //store all distribution element id for online url. key is the distribution
151
    // id and  data  is url
152
    private Hashtable onlineURLDistributionIdList = new Hashtable();
153
    // distribution/oneline/url will store this vector if distribution doesn't
154
    // have a id.
155 4501 daigle
    private Vector onlineURLDistributionListWithoutId = new Vector();
156 2161 tao
157 2245 sgarg
    //store all distribution element id for online other distribution, such as
158
    // connection or connectiondefination. key is the distribution id
159
    // and  data  is distribution id
160
    private Hashtable onlineOtherDistributionIdList = new Hashtable();
161 2161 tao
162 2245 sgarg
    //store all distribution element id for inline data.
163
    // key is the distribution id, data is the internal inline id
164
    private Hashtable inlineDistributionIdList = new Hashtable();
165 2161 tao
166 2245 sgarg
    //store all distribution element id for off line data.
167
    // key is the distribution id, data is the id too.
168
    private Hashtable offlineDistributionIdList = new Hashtable();
169 2161 tao
170 2245 sgarg
    // a hash to stored all distribution id, both key and value are id itself
171
    private Hashtable distributionAllIdList = new Hashtable();
172 2161 tao
173 2245 sgarg
    // temporarily store distribution id
174
    private String distributionId = null;
175 2161 tao
176 5311 daigle
    // flag to indicate to handle distribution
177 2245 sgarg
    private boolean proccessDistribution = false;
178 2161 tao
179 2245 sgarg
    // a hash table to stored the distribution which is a reference and this
180
    // distribution has a id too. The key is itself id of this distribution,
181
    // the value is the referenced id.
182
    // So, we only stored the format like this:
183
    // <distribution id ="100"><reference>300</reference></distribution>
184
    // the reason is:
185
    // if not id in distribution, then the distribution couldn't be added
186
    // to additional access module. The distribution block which was referenced
187
    // id (300) will be stored in above distribution lists.
188
    private Hashtable distributionReferenceList = new Hashtable();
189 2161 tao
190 5311 daigle
    // if the action is update and the user does not have ALL permission
191
    // and the user is not an administrator, then we will need to compare
192
    // access modules to make sure the user has update permissions
193
    private boolean needToCheckAccessModule = false;
194 2161 tao
195 5311 daigle
    private AccessSection topAccessSubTreeFromDB = null;
196 2161 tao
197 5311 daigle
    private Vector additionalAccessSubTreeListFromDB = new Vector();
198 2161 tao
199 5311 daigle
    private Hashtable referencedAccessSubTreeListFromDB = new Hashtable();
200 2161 tao
201 5311 daigle
    // this holds the top level (document level) access section.
202 2245 sgarg
    private AccessSection topAccessSection;
203 2161 tao
204 5166 daigle
    private Vector additionalAccessVector = new Vector();
205 2161 tao
206 2245 sgarg
    // key is subtree id and value is accessSection object
207
    private Hashtable possibleReferencedAccessHash = new Hashtable();
208 2161 tao
209
    // we need an another stack to store the access node which we pull out just
210
    // from xml. If a reference happend, we can use the stack the compare nodes
211
    private Stack storedAccessNodeStack = new Stack();
212
213
    // vector stored the data file id which will be write into relation table
214 2165 tao
    private Vector onlineDataFileIdInRelationVector = new Vector();
215 2161 tao
216
    // Indicator of inline data
217
    private boolean handleInlineData = false;
218
219
    private Hashtable inlineDataNameSpace = null;
220
221 5752 leinfelder
    private Writer inlineDataFileWriter = null;
222 2161 tao
223
    private String inlineDataFileName = null;
224
225
    private int inLineDataIndex = 0;
226
227
    private Vector inlineFileIDList = new Vector();
228
229 5311 daigle
    private boolean inAdditionalMetaData = false;
230 2165 tao
231 2245 sgarg
    //user has unwritable inline data object when it updates a document
232
    private boolean unWritableInlineDataObject = false;
233
    //user has unreadable inline data when it updates a dcoument
234
    private boolean unReadableInlineDataObject = false;
235
236
    // the hashtable contains the info from xml_access table which
237
    // inline data the user can't read when user update a document.
238
    // The key in hashtable is subtree id and data is the inline data internal
239
    // file name.
240
241
    private Hashtable previousUnreadableInlineDataObjectHash = new Hashtable();
242
243
    // the hashtable contains the info from xml_access table which
244
    // inline data the user can't write when user update a document.
245
    // The key in hashtable is subtree id and data is the inline data internal
246
    // file name.
247
    private Hashtable previousUnwritableInlineDataObjectHash = new Hashtable();
248
249
    private Hashtable accessSubTreeAlreadyWriteDBList = new Hashtable();
250
251
    //This hashtable will stored the id which already has additional access
252
    // control. So the top level access control will ignore them.
253 5166 daigle
    private Hashtable onlineURLIdHasadditionalAccess   = new Hashtable();
254 2245 sgarg
255
    // additional access module will be in additionalMetadata part. Its format
256
    // look like
257
    //<additionalMetadata>
258
    //   <describes>100</describes>
259
    //   <describes>300</describes>
260
    //   <access>rulesone</access>
261
    //</additionalMetadata>
262
    // If user couldn't have all permission to update access rules, he/she could
263
    // not update access module, but also couldn't update "describes".
264
    // So the start node id for additional access section is the first describes
265
    // element
266
    private boolean firstDescribesInAdditionalMetadata = true;
267
    private long    firstDescribesNodeId               = -1;
268
269
    private int numberOfHitUnWritableInlineData = 0;
270
271 2161 tao
    // Constant
272
    private static final String EML = "eml";
273
274
    private static final String DESCRIBES = "describes";
275
276
    private static final String ADDITIONALMETADATA = "additionalMetadata";
277
278
    private static final String ORDER = "order";
279
280
    private static final String ID = "id";
281
282
    private static final String REFERENCES = "references";
283
284
    public static final String INLINE = "inline";
285
286
    private static final String ONLINE = "online";
287
288 2245 sgarg
    private static final String OFFLINE = "offline";
289
290
    private static final String CONNECTION = "connection";
291
292
    private static final String CONNECTIONDEFINITION = "connectionDefinition";
293
294 2161 tao
    private static final String URL = "url";
295
296 4471 daigle
    private static final String PERMISSIONERROR = "User tried to update a subtree "
297
        + "when they don't have write permission!";
298 2161 tao
299 4471 daigle
    private static final String UPDATEACCESSERROR = "User tried to update an "
300
        + "access module when they don't have \"ALL\" permission!";
301 2161 tao
302 2245 sgarg
    public static final String TOPLEVEL = "top";
303 2161 tao
304 2245 sgarg
    public static final String DATAACCESSLEVEL = "dataAccess";
305 2161 tao
306 2245 sgarg
    // this level is for the access module which is not in top or additional
307
    // place, but it was referenced by top or additional
308
    private static final String REFERENCEDLEVEL = "referenced";
309
310 2161 tao
    private static final String RELATION = "Provides info for";
311
312 2245 sgarg
    private static final String DISTRIBUTION = "distribution";
313
314 2663 sgarg
    private Logger logMetacat = Logger.getLogger(Eml200SAXHandler.class);
315
316 2161 tao
    /**
317
     * Construct an instance of the handler class In this constructor, user can
318
     * specify the version need to upadate
319
     *
320
     * @param conn the JDBC connection to which information is written
321
     * @param action - "INSERT" or "UPDATE"
322
     * @param docid to be inserted or updated into JDBC connection
323
     * @param revision, the user specified the revision need to be update
324
     * @param user the user connected to MetaCat servlet and owns the document
325
     * @param groups the groups to which user belongs
326
     * @param pub flag for public "read" access on document
327
     * @param serverCode the serverid from xml_replication on which this
328
     *            document resides.
329
     *
330
     */
331
    public Eml200SAXHandler(DBConnection conn, String action, String docid,
332
            String revision, String user, String[] groups, String pub,
333 2623 tao
            int serverCode, String createDate, String updateDate) throws SAXException
334 2161 tao
    {
335 2623 tao
        super(conn, action, docid, revision, user, groups, pub,
336
                serverCode, createDate, updateDate);
337 2161 tao
        // Get the unchangable subtrees (user doesn't have write permission)
338 2245 sgarg
        try
339
        {
340 2161 tao
            PermissionController control = new PermissionController(docid
341 4212 daigle
                    + PropertyService.getProperty("document.accNumSeparator") + revision);
342 2161 tao
            //unChangableSubTreeHash = getUnchangableSubTree(control, user,
343
            // groups);
344
345 5311 daigle
            // If the action is update and user doesn't have "ALL" permission
346 2161 tao
            // we need to check if user update access subtree
347 2245 sgarg
            if (action != null && action.equals("UPDATE")
348 2161 tao
                    && !control.hasPermission(user, groups,
349 3004 sgarg
                            AccessControlInterface.ALLSTRING)
350 4589 daigle
                            && !AuthUtil.isAdministrator(user, groups))
351 2245 sgarg
            {
352 5311 daigle
                needToCheckAccessModule = true;
353
                topAccessSubTreeFromDB = getTopAccessSubTreeFromDB();
354
                additionalAccessSubTreeListFromDB =
355 2245 sgarg
                                         getAdditionalAccessSubTreeListFromDB();
356 5311 daigle
                referencedAccessSubTreeListFromDB =
357 2245 sgarg
                                         getReferencedAccessSubTreeListFromDB();
358 2161 tao
            }
359 2245 sgarg
360
            //Here is for  data object checking.
361
            if (action != null && action.equals("UPDATE"))
362
            {
363
              //info about inline data object which user doesn't have read
364
              //permission the info come from xml_access table
365
              previousUnreadableInlineDataObjectHash = PermissionController.
366 2292 sgarg
                            getUnReadableInlineDataIdList(docid, user,
367
                                                          groups, true);
368 2245 sgarg
369
              //info about data object which user doesn't have write permission
370
              // the info come from xml_accesss table
371
              previousUnwritableInlineDataObjectHash = PermissionController.
372 2292 sgarg
                            getUnWritableInlineDataIdList(docid, user,
373
                                                          groups, true);
374 2245 sgarg
375
            }
376
377
378
        }
379
        catch (Exception e)
380
        {
381 4661 daigle
            logMetacat.error("error in Eml200SAXHandler is " + e.getMessage());
382 2161 tao
            throw new SAXException(e.getMessage());
383
        }
384
    }
385
386 2245 sgarg
    /*
387
     * Get the top level access subtree info from xml_accesssubtree table.
388
     * If no top access subtree found, null will be return.
389
     */
390
     private AccessSection getTopAccessSubTreeFromDB()
391
                                                       throws SAXException
392
     {
393
       AccessSection topAccess = null;
394
       PreparedStatement pstmt = null;
395
       ResultSet rs = null;
396
       String sql = "SELECT subtreeid, startnodeid, endnodeid "
397
                + "FROM xml_accesssubtree WHERE docid like ? "
398
                + "AND controllevel like ?";
399 2161 tao
400
401 2245 sgarg
       try
402
       {
403
            pstmt = connection.prepareStatement(sql);
404
            // Increase DBConnection usage count
405
            connection.increaseUsageCount(1);
406
            // Bind the values to the query
407
            pstmt.setString(1, docid);
408
            pstmt.setString(2, TOPLEVEL);
409 5208 daigle
            logMetacat.debug("Eml200SAXHandler.getTopAccessSubTreeFromDB - executing SQL: " + pstmt.toString());
410 2245 sgarg
            pstmt.execute();
411 2161 tao
412 2245 sgarg
            // Get result set
413
            rs = pstmt.getResultSet();
414
            if (rs.next())
415
            {
416
                String sectionId = rs.getString(1);
417
                long startNodeId = rs.getLong(2);
418
                long endNodeId = rs.getLong(3);
419
                // create a new access section
420 2262 sgarg
                topAccess = new AccessSection();
421
                topAccess.setControlLevel(TOPLEVEL);
422
                topAccess.setDocId(docid);
423
                topAccess.setSubTreeId(sectionId);
424
                topAccess.setStartNodeId(startNodeId);
425
                topAccess.setEndNodeId(endNodeId);
426 2245 sgarg
            }
427
            pstmt.close();
428
        }//try
429
        catch (SQLException e)
430
        {
431
            throw new SAXException(
432
                    "EMLSAXHandler.getTopAccessSubTreeFromDB(): "
433
                            + e.getMessage());
434
        }//catch
435
        finally
436
        {
437
            try
438
            {
439
                pstmt.close();
440
            }
441
            catch (SQLException ee)
442
            {
443
                throw new SAXException(
444
                        "EMLSAXHandler.getTopAccessSubTreeFromDB(): "
445
                                + ee.getMessage());
446
            }
447
        }//finally
448
        return topAccess;
449 2161 tao
450 2245 sgarg
     }
451 2161 tao
452
    /*
453
     * Get the subtree node info from xml_accesssubtree table
454
     */
455 2245 sgarg
    private Vector getAdditionalAccessSubTreeListFromDB() throws Exception
456 2161 tao
    {
457
        Vector result = new Vector();
458
        PreparedStatement pstmt = null;
459
        ResultSet rs = null;
460 2245 sgarg
        String sql = "SELECT subtreeid, startnodeid, endnodeid "
461 2161 tao
                + "FROM xml_accesssubtree WHERE docid like ? "
462 2245 sgarg
                + "AND controllevel like ? "
463 2161 tao
                + "ORDER BY startnodeid ASC";
464
465 2245 sgarg
        try
466
        {
467 2161 tao
468
            pstmt = connection.prepareStatement(sql);
469
            // Increase DBConnection usage count
470
            connection.increaseUsageCount(1);
471
            // Bind the values to the query
472
            pstmt.setString(1, docid);
473 2245 sgarg
            pstmt.setString(2, DATAACCESSLEVEL);
474 2161 tao
            pstmt.execute();
475
476
            // Get result set
477
            rs = pstmt.getResultSet();
478 2245 sgarg
            while (rs.next())
479
            {
480
                String sectionId = rs.getString(1);
481
                long startNodeId = rs.getLong(2);
482
                long endNodeId = rs.getLong(3);
483 2161 tao
                // create a new access section
484
                AccessSection accessObj = new AccessSection();
485 2245 sgarg
                accessObj.setControlLevel(DATAACCESSLEVEL);
486 2161 tao
                accessObj.setDocId(docid);
487
                accessObj.setSubTreeId(sectionId);
488
                accessObj.setStartNodeId(startNodeId);
489
                accessObj.setEndNodeId(endNodeId);
490
                // add this access obj into vector
491
                result.add(accessObj);
492 2245 sgarg
493 2161 tao
            }
494
            pstmt.close();
495
        }//try
496 2245 sgarg
        catch (SQLException e)
497
        {
498 2161 tao
            throw new SAXException(
499 5166 daigle
                    "EMLSAXHandler.getadditionalAccessSubTreeListFromDB(): "
500 2161 tao
                            + e.getMessage());
501
        }//catch
502 2245 sgarg
        finally
503
        {
504
            try
505
            {
506 2161 tao
                pstmt.close();
507 2245 sgarg
            }
508
            catch (SQLException ee)
509
            {
510 2161 tao
                throw new SAXException(
511
                        "EMLSAXHandler.getAccessSubTreeListFromDB(): "
512
                                + ee.getMessage());
513
            }
514
        }//finally
515
        return result;
516
    }
517
518 2245 sgarg
   /*
519
    * Get the access subtree for referenced info from xml_accesssubtree table
520
    */
521
   private Hashtable getReferencedAccessSubTreeListFromDB() throws Exception
522
   {
523
       Hashtable result = new Hashtable();
524
       PreparedStatement pstmt = null;
525
       ResultSet rs = null;
526
       String sql = "SELECT subtreeid, startnodeid, endnodeid "
527
               + "FROM xml_accesssubtree WHERE docid like ? "
528
               + "AND controllevel like ? "
529
               + "ORDER BY startnodeid ASC";
530
531
       try
532
       {
533
534
           pstmt = connection.prepareStatement(sql);
535
           // Increase DBConnection usage count
536
           connection.increaseUsageCount(1);
537
           // Bind the values to the query
538
           pstmt.setString(1, docid);
539
           pstmt.setString(2, REFERENCEDLEVEL);
540
           pstmt.execute();
541
542
           // Get result set
543
           rs = pstmt.getResultSet();
544
           while (rs.next())
545
           {
546
               String sectionId = rs.getString(1);
547
               long startNodeId = rs.getLong(2);
548
               long endNodeId = rs.getLong(3);
549
               // create a new access section
550
               AccessSection accessObj = new AccessSection();
551
               accessObj.setControlLevel(DATAACCESSLEVEL);
552
               accessObj.setDocId(docid);
553
               accessObj.setSubTreeId(sectionId);
554
               accessObj.setStartNodeId(startNodeId);
555
               accessObj.setEndNodeId(endNodeId);
556
               // add this access obj into hastable
557
               if ( sectionId != null && !sectionId.trim().equals(""))
558
               {
559
                 result.put(sectionId, accessObj);
560
               }
561
562
           }
563
           pstmt.close();
564
       }//try
565
       catch (SQLException e)
566
       {
567
           throw new SAXException(
568
                   "EMLSAXHandler.getReferencedAccessSubTreeListFromDB(): "
569
                           + e.getMessage());
570
       }//catch
571
       finally
572
       {
573
           try
574
           {
575
               pstmt.close();
576
           }
577
           catch (SQLException ee)
578
           {
579
               throw new SAXException(
580
                       "EMLSAXHandler.getReferencedSubTreeListFromDB(): "
581
                               + ee.getMessage());
582
           }
583
       }//finally
584
       return result;
585
   }
586
587
588
589 2161 tao
    /** SAX Handler that is called at the start of each XML element */
590
    public void startElement(String uri, String localName, String qName,
591
            Attributes atts) throws SAXException
592
    {
593
        // for element <eml:eml...> qname is "eml:eml", local name is "eml"
594
        // for element <acl....> both qname and local name is "eml"
595
        // uri is namesapce
596 5208 daigle
        logMetacat.debug("Start ELEMENT(qName) " + qName);
597
        logMetacat.debug("Start ELEMENT(localName) " + localName);
598
        logMetacat.debug("Start ELEMENT(uri) " + uri);
599 2161 tao
600
        DBSAXNode parentNode = null;
601
        DBSAXNode currentNode = null;
602 2245 sgarg
        // none inline part
603
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
604
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
605
        if (!handleInlineData)
606
        {
607 2161 tao
            // Get a reference to the parent node for the id
608 2245 sgarg
            try
609
            {
610 2161 tao
                parentNode = (DBSAXNode) nodeStack.peek();
611 2245 sgarg
            }
612
            catch (EmptyStackException e)
613
            {
614 2161 tao
                parentNode = null;
615
            }
616
617
            //start handle inline data
618 2245 sgarg
            //=====================================================
619 5311 daigle
            if (qName.equals(INLINE) && !inAdditionalMetaData)
620 2245 sgarg
            {
621 2161 tao
                handleInlineData = true;
622
                inLineDataIndex++;
623
                //intitialize namespace hash for in line data
624
                inlineDataNameSpace = new Hashtable();
625
                //initialize file writer
626 5025 daigle
                String docidWithoutRev = DocumentUtil.getDocIdFromString(docid);
627 4080 daigle
                String seperator = ".";
628
                try {
629 4212 daigle
					seperator = PropertyService.getProperty("document.accNumSeparator");
630 4080 daigle
				} catch (PropertyNotFoundException pnfe) {
631
					logMetacat.error("Could not get property 'accNumSeparator'.  "
632
							+ "Setting separator to '.': "+ pnfe.getMessage());
633
				}
634 2161 tao
                // the new file name will look like docid.rev.2
635
                inlineDataFileName = docidWithoutRev + seperator + revision
636
                        + seperator + inLineDataIndex;
637 5752 leinfelder
                inlineDataFileWriter = createInlineDataFileWriter(inlineDataFileName, encoding);
638 2161 tao
                // put the inline file id into a vector. If upload failed,
639
                // metacat will
640
                // delete the inline data file
641
                inlineFileIDList.add(inlineDataFileName);
642
643 2245 sgarg
                // put distribution id and inline file id into a  hash
644
                if (distributionId != null)
645
                {
646
                  //check to see if this inline data is readable or writable to
647
                  // this user
648
                  if (!previousUnreadableInlineDataObjectHash.isEmpty() &&
649
                       previousUnreadableInlineDataObjectHash.containsKey(distributionId))
650
                  {
651
                      unReadableInlineDataObject = true;
652
                  }
653
                  if (!previousUnwritableInlineDataObjectHash.isEmpty() &&
654
                       previousUnwritableInlineDataObjectHash.containsKey(distributionId))
655
                  {
656
                     unWritableInlineDataObject = true;
657
                     numberOfHitUnWritableInlineData++;
658
                  }
659
660
661
                  // store the distributid and inlinedata filename into a hash
662
                  inlineDistributionIdList.put(distributionId, inlineDataFileName);
663
                }
664
665 2161 tao
            }
666 2245 sgarg
            //==============================================================
667 2161 tao
668 2245 sgarg
669 2161 tao
            // If hit a text node, we need write this text for current's parent
670
            // node
671
            // This will happend if the element is mixted
672 2245 sgarg
            //==============================================================
673
            if (hitTextNode && parentNode != null)
674
            {
675 2161 tao
676
677 5311 daigle
                if (needToCheckAccessModule
678
                        && (processAdditionalAccess || processOtherAccess || processTopLevelAccess)) {
679 2161 tao
                    // stored the pull out nodes into storedNode stack
680
                    NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "TEXT",
681 4698 daigle
                            null, null, MetacatUtil.normalize(textBuffer
682 2161 tao
                                    .toString()));
683
                    storedAccessNodeStack.push(nodeElement);
684
685
                }
686
687
                // write the textbuffer into db for parent node.
688
                endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer,
689
                        parentNode);
690
                // rest hitTextNode
691
                hitTextNode = false;
692
                // reset textbuffer
693
                textBuffer = null;
694
                textBuffer = new StringBuffer();
695
696
            }
697 2245 sgarg
            //==================================================================
698 2161 tao
699
            // Document representation that points to the root document node
700 2245 sgarg
            //==================================================================
701
            if (atFirstElement)
702
            {
703 2161 tao
                atFirstElement = false;
704
                // If no DOCTYPE declaration: docname = root element
705
                // doctype = root element name or name space
706
                if (docname == null) {
707
                    docname = localName;
708
                    // if uri isn't null doctype = uri(namespace)
709
                    // othewise root element
710
                    if (uri != null && !(uri.trim()).equals("")) {
711
                        doctype = uri;
712
                    } else {
713
                        doctype = docname;
714
                    }
715 2663 sgarg
                    logMetacat.info("DOCNAME-a: " + docname);
716
                    logMetacat.info("DOCTYPE-a: " + doctype);
717 2161 tao
                } else if (doctype == null) {
718
                    // because docname is not null and it is declared in dtd
719
                    // so could not be in schema, no namespace
720
                    doctype = docname;
721 2663 sgarg
                    logMetacat.info("DOCTYPE-b: " + doctype);
722 2161 tao
                }
723
                rootNode.writeNodename(docname);
724 2618 tao
                //System.out.println("here!!!!!!!!!!!!!!!!!!1");
725 2161 tao
                try {
726
                    // for validated XML Documents store a reference to XML DB
727
                    // Catalog
728
                    // Because this is select statement and it needn't to roll
729
                    // back if
730
                    // insert document action fialed.
731
                    // In order to decrease DBConnection usage count, we get a
732
                    // new
733
                    // dbconnection from pool
734 2623 tao
                    //String catalogid = null;
735 2161 tao
                    DBConnection dbConn = null;
736
                    int serialNumber = -1;
737
738
                    try {
739
                        // Get dbconnection
740
                        dbConn = DBConnectionPool
741
                                .getDBConnection("DBSAXHandler.startElement");
742
                        serialNumber = dbConn.getCheckOutSerialNumber();
743
744
                        Statement stmt = dbConn.createStatement();
745
                        ResultSet rs = stmt
746
                                .executeQuery("SELECT catalog_id FROM xml_catalog "
747
                                        + "WHERE entry_type = 'Schema' "
748
                                        + "AND public_id = '" + doctype + "'");
749
                        boolean hasRow = rs.next();
750
                        if (hasRow) {
751
                            catalogid = rs.getString(1);
752
                        }
753
                        stmt.close();
754 2618 tao
                        //System.out.println("here!!!!!!!!!!!!!!!!!!2");
755 2161 tao
                    }//try
756
                    finally {
757
                        // Return dbconnection
758
                        DBConnectionPool.returnDBConnection(dbConn,
759
                                serialNumber);
760
                    }//finally
761
762
                    //create documentImpl object by the constructor which can
763
                    // specify
764
                    //the revision
765 2608 tao
                    if (!super.getIsRevisionDoc())
766
                    {
767 5208 daigle
                       logMetacat.debug("EML200SaxHandler.startElement - creating new DocumentImple for " + docid);
768 2608 tao
                       currentDocument = new DocumentImpl(connection, rootNode
769 2161 tao
                            .getNodeID(), docname, doctype, docid, revision,
770 2623 tao
                            action, user, this.pub, catalogid, this.serverCode,
771
                            createDate, updateDate);
772 2608 tao
                    }
773 2623 tao
774 2161 tao
775
                } catch (Exception ane) {
776 5208 daigle
                    throw (new SAXException("EML200SaxHandler.startElement - error with action " +
777
                    		action + " : " + ane.getMessage()));
778 2161 tao
                }
779 2608 tao
780 2161 tao
            }
781 2245 sgarg
            //==================================================================
782 2161 tao
783 2245 sgarg
            // node
784
            //==================================================================
785 2161 tao
            // Create the current node representation
786
            currentNode = new DBSAXNode(connection, qName, localName,
787 2628 tao
                    parentNode, rootNode.getNodeID(), docid,
788
                    doctype);
789 2161 tao
            // Use a local variable to store the element node id
790
            // If this element is a start point of subtree(section), it will be
791
            // stored
792
            // otherwise, it will be discated
793
            long startNodeId = currentNode.getNodeID();
794
            // Add all of the namespaces
795
            String prefix = null;
796
            String nsuri = null;
797
            Enumeration prefixes = namespaces.keys();
798 2245 sgarg
            while (prefixes.hasMoreElements())
799
            {
800 2161 tao
                prefix = (String) prefixes.nextElement();
801
                nsuri = (String) namespaces.get(prefix);
802
                endNodeId = currentNode.setNamespace(prefix, nsuri, docid);
803
            }
804
805 2245 sgarg
            //=================================================================
806
           // attributes
807
           // Add all of the attributes
808
          for (int i = 0; i < atts.getLength(); i++)
809
          {
810
              String attributeName = atts.getQName(i);
811
              String attributeValue = atts.getValue(i);
812
              endNodeId = currentNode.setAttribute(attributeName,
813
                      attributeValue, docid);
814 2161 tao
815 2245 sgarg
              // To handle name space and schema location if the attribute
816
              // name is
817
              // xsi:schemaLocation. If the name space is in not in catalog
818
              // table
819
              // it will be regeistered.
820
              if (attributeName != null
821
                      && attributeName
822
                              .indexOf(MetaCatServlet.SCHEMALOCATIONKEYWORD) != -1) {
823
                  SchemaLocationResolver resolver = new SchemaLocationResolver(
824
                          attributeValue);
825
                  resolver.resolveNameSpace();
826 2161 tao
827 2245 sgarg
              }
828
              else if (attributeName != null && attributeName.equals(ID) &&
829
                       currentNode.getTagName().equals(DISTRIBUTION) &&
830 5311 daigle
                       !inAdditionalMetaData)
831 2245 sgarg
              {
832
                 // this is a distribution element and the id is distributionID
833
                 distributionId = attributeValue;
834
                 distributionAllIdList.put(distributionId, distributionId);
835 2161 tao
836 2245 sgarg
              }
837 2161 tao
838 2245 sgarg
          }//for
839 2161 tao
840
841 2245 sgarg
           //=================================================================
842
843 2161 tao
            // handle access stuff
844 2245 sgarg
            //==================================================================
845
            if (localName.equals(ACCESS))
846
            {
847
                //make sure the access is top level
848
                // this mean current node's parent's parent should be "eml"
849
                DBSAXNode tmpNode = (DBSAXNode) nodeStack.pop();// pop out
850 2161 tao
                                                                    // parent
851
                                                                    // node
852 2245 sgarg
                //peek out grandParentNode
853
                DBSAXNode grandParentNode = (DBSAXNode) nodeStack.peek();
854
                // put parent node back
855
                nodeStack.push(tmpNode);
856
                String grandParentTag = grandParentNode.getTagName();
857 5311 daigle
                if (grandParentTag.equals(EML) && !inAdditionalMetaData)
858 2245 sgarg
                {
859 5311 daigle
                  processTopLevelAccess = true;
860 2161 tao
861
                }
862 5311 daigle
                else if ( !inAdditionalMetaData )
863 2245 sgarg
                {
864
                  // process other access embedded into resource level
865
                  // module
866
                  processOtherAccess = true;
867
                }
868
                else
869
                {
870 5311 daigle
                  // this for access in additional data which doesn't have a
871
                  // described element. If it has a described element,
872
                  // this code won't hurt any thing
873 2245 sgarg
                  processAdditionalAccess = true;
874
                }
875
876
877 2161 tao
                // create access object
878
                accessObject = new AccessSection();
879
                // set permission order
880
                String permOrder = currentNode.getAttribute(ORDER);
881
                accessObject.setPermissionOrder(permOrder);
882
                // set access id
883
                String accessId = currentNode.getAttribute(ID);
884
                accessObject.setSubTreeId(accessId);
885 2245 sgarg
                // for additional access subtree, the  start of node id should
886
                // be describe element. We also stored the start access element
887
                // node id too.
888
                if (processAdditionalAccess)
889
                {
890 4471 daigle
                  accessObject.setStartedDescribesNodeId(firstDescribesNodeId);
891 2245 sgarg
                  accessObject.setControlLevel(DATAACCESSLEVEL);
892
                }
893 5311 daigle
                else if (processTopLevelAccess)
894 2245 sgarg
                {
895
                  accessObject.setControlLevel(TOPLEVEL);
896
                }
897
                else if (processOtherAccess)
898
                {
899
                  accessObject.setControlLevel(REFERENCEDLEVEL);
900
                }
901
902 2161 tao
                accessObject.setStartNodeId(startNodeId);
903
                accessObject.setDocId(docid);
904
905
906 2245 sgarg
907 2161 tao
            }
908
            // Set up a access rule for allow
909
            else if (parentNode.getTagName() != null
910
                    && (parentNode.getTagName()).equals(ACCESS)
911 2245 sgarg
                    && localName.equals(ALLOW))
912
           {
913 2161 tao
914
                accessRule = new AccessRule();
915
916
                //set permission type "allow"
917
                accessRule.setPermissionType(ALLOW);
918
919
            }
920
            // set up an access rule for den
921
            else if (parentNode.getTagName() != null
922
                    && (parentNode.getTagName()).equals(ACCESS)
923 2245 sgarg
                    && localName.equals(DENY))
924
           {
925 2161 tao
                accessRule = new AccessRule();
926
                //set permission type "allow"
927
                accessRule.setPermissionType(DENY);
928
            }
929
930 2245 sgarg
            //=================================================================
931
            // some other independ stuff
932
933 2161 tao
            // Add the node to the stack, so that any text data can be
934
            // added as it is encountered
935
            nodeStack.push(currentNode);
936
            // Add the node to the vector used by thread for writing XML Index
937
            nodeIndex.addElement(currentNode);
938
939
            // store access module element and attributes into stored stack
940 5311 daigle
            if (needToCheckAccessModule
941
                    && (processAdditionalAccess || processOtherAccess || processTopLevelAccess))
942 2245 sgarg
            {
943 2161 tao
                // stored the pull out nodes into storedNode stack
944
                NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "ELEMENT",
945 4698 daigle
                        localName, prefix, MetacatUtil.normalize(null));
946 2161 tao
                storedAccessNodeStack.push(nodeElement);
947
                for (int i = 0; i < atts.getLength(); i++) {
948
                    String attributeName = atts.getQName(i);
949
                    String attributeValue = atts.getValue(i);
950
                    NodeRecord nodeAttribute = new NodeRecord(-2, -2, -2,
951 4698 daigle
                            "ATTRIBUTE", attributeName, null, MetacatUtil
952 2161 tao
                                    .normalize(attributeValue));
953
                    storedAccessNodeStack.push(nodeAttribute);
954
                }
955
956
            }
957
958 2245 sgarg
            if (currentNode.getTagName().equals(ADDITIONALMETADATA))
959
            {
960 5311 daigle
              inAdditionalMetaData = true;
961 2245 sgarg
            }
962
            else if (currentNode.getTagName().equals(DESCRIBES) &&
963
                     parentNode.getTagName().equals(ADDITIONALMETADATA) &&
964
                     firstDescribesInAdditionalMetadata)
965
            {
966
              // this is first decirbes element in additional metadata
967
              firstDescribesNodeId = startNodeId;
968
              // we started process additional access rules here
969
              // because access and describe couldn't be seperated
970 2278 sgarg
              NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "ELEMENT",
971 4698 daigle
                        localName, prefix, MetacatUtil.normalize(null));
972 2278 sgarg
              storedAccessNodeStack.push(nodeElement);
973 2245 sgarg
              processAdditionalAccess = true;
974 5166 daigle
              logMetacat.info("set processAdditonalAccess true when meet describe");
975 2245 sgarg
            }
976 5311 daigle
            else if (inAdditionalMetaData && processAdditionalAccess &&
977 2245 sgarg
                     parentNode.getTagName().equals(ADDITIONALMETADATA) &&
978
                     !currentNode.getTagName().equals(DESCRIBES) &&
979
                     !currentNode.getTagName().equals(ACCESS))
980
            {
981 5166 daigle
               // we start processadditionalAccess  module when first hit describes
982 2245 sgarg
               // in additionalMetadata. So this is possible, there are
983
               // "describes" but not "access". So here is try to terminate
984
               // processAddionalAccess. In this situation, there another element
985
               // rather than "describes" or "access" as a child of additionalMetadata
986
               // so this is impossible it will have access element now.
987
               // If additionalMetadata has access element, the flag will be
988
               // terminated in endElement
989
               processAdditionalAccess = false;
990 2663 sgarg
               logMetacat.warn("set processAddtionAccess false if the there is no access in additional");
991 2245 sgarg
            }
992
            else if (currentNode.getTagName().equals(DISTRIBUTION) &&
993 5311 daigle
                     !inAdditionalMetaData)
994 2245 sgarg
            {
995
              proccessDistribution = true;
996
            }
997
998
999
             //==================================================================
1000 2161 tao
            // reset name space
1001
            namespaces = null;
1002
            namespaces = new Hashtable();
1003 2245 sgarg
1004 2161 tao
        }//not inline data
1005 2245 sgarg
        // inline data
1006
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1007
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1008
        else
1009
        {
1010 2161 tao
            // we don't buffer the inline data in characters() method
1011
            // so start character don't need to hand text node.
1012
1013
            // inline data may be the xml format.
1014
            StringBuffer inlineElements = new StringBuffer();
1015
            inlineElements.append("<").append(qName);
1016
            // append attributes
1017
            for (int i = 0; i < atts.getLength(); i++) {
1018
                String attributeName = atts.getQName(i);
1019
                String attributeValue = atts.getValue(i);
1020
                inlineElements.append(" ");
1021
                inlineElements.append(attributeName);
1022
                inlineElements.append("=\"");
1023
                inlineElements.append(attributeValue);
1024
                inlineElements.append("\"");
1025
            }
1026
            // append namespace
1027
            String prefix = null;
1028
            String nsuri = null;
1029
            Enumeration prefixes = inlineDataNameSpace.keys();
1030
            while (prefixes.hasMoreElements()) {
1031
                prefix = (String) prefixes.nextElement();
1032 2245 sgarg
                nsuri =  (String)  inlineDataNameSpace.get(prefix);
1033 2161 tao
                inlineElements.append(" ");
1034
                inlineElements.append("xmlns:");
1035
                inlineElements.append(prefix);
1036
                inlineElements.append("=\"");
1037
                inlineElements.append(nsuri);
1038
                inlineElements.append("\"");
1039
            }
1040
            inlineElements.append(">");
1041
            //reset inline data name space
1042
            inlineDataNameSpace = null;
1043
            inlineDataNameSpace = new Hashtable();
1044
            //write inline data into file
1045 2663 sgarg
            logMetacat.info("the inline element data is: "
1046
                    + inlineElements.toString());
1047 2161 tao
            writeInlineDataIntoFile(inlineDataFileWriter, inlineElements);
1048
        }//else
1049 2245 sgarg
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1050
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1051 2161 tao
1052
    }
1053
1054
1055
    /** SAX Handler that is called for each XML text node */
1056
    public void characters(char[] cbuf, int start, int len) throws SAXException
1057
    {
1058 2663 sgarg
        logMetacat.info("CHARACTERS");
1059 2161 tao
        if (!handleInlineData) {
1060
            // buffer all text nodes for same element. This is for text was
1061
            // splited
1062
            // into different nodes
1063
            textBuffer.append(new String(cbuf, start, len));
1064
            // set hittextnode true
1065
            hitTextNode = true;
1066
            // if text buffer .size is greater than max, write it to db.
1067
            // so we can save memory
1068 2245 sgarg
            if (textBuffer.length() >= MAXDATACHARS)
1069
            {
1070 2663 sgarg
                logMetacat.info("Write text into DB in charaters"
1071
                           + " when text buffer size is greater than maxmum number");
1072 2161 tao
                DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
1073
                endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer,
1074
                        currentNode);
1075 5311 daigle
                if (needToCheckAccessModule
1076
                     && (processAdditionalAccess || processOtherAccess || processTopLevelAccess))
1077 2245 sgarg
                {
1078
                     // stored the pull out nodes into storedNode stack
1079
                     NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "TEXT",
1080 4698 daigle
                       null, null, MetacatUtil.normalize(textBuffer
1081 2245 sgarg
                          .toString()));
1082
                     storedAccessNodeStack.push(nodeElement);
1083
1084
                }
1085 2161 tao
                textBuffer = null;
1086
                textBuffer = new StringBuffer();
1087
            }
1088 2245 sgarg
        }
1089
        else
1090
        {
1091 2161 tao
            // this is inline data and write file system directly
1092
            // we don't need to buffered it.
1093
            StringBuffer inlineText = new StringBuffer();
1094
            inlineText.append(new String(cbuf, start, len));
1095 2663 sgarg
            logMetacat.info(
1096 2161 tao
                    "The inline text data write into file system: "
1097 2663 sgarg
                            + inlineText.toString());
1098 2161 tao
            writeInlineDataIntoFile(inlineDataFileWriter, inlineText);
1099
        }
1100
    }
1101
1102
    /** SAX Handler that is called at the end of each XML element */
1103
    public void endElement(String uri, String localName, String qName)
1104
            throws SAXException
1105
    {
1106 2663 sgarg
        logMetacat.info("End ELEMENT " + qName);
1107 2161 tao
1108 2245 sgarg
        // when close inline element
1109
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1110
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1111
        if (localName.equals(INLINE) && handleInlineData)
1112
        {
1113 2161 tao
            // Get the node from the stack
1114
            DBSAXNode currentNode = (DBSAXNode) nodeStack.pop();
1115
            String currentTag = currentNode.getTagName();
1116 2663 sgarg
            logMetacat.info("End of inline data");
1117 2161 tao
            // close file writer
1118 2245 sgarg
            try
1119
            {
1120 2161 tao
                inlineDataFileWriter.close();
1121
                handleInlineData = false;
1122 2245 sgarg
            }
1123
            catch (IOException ioe)
1124
            {
1125 2161 tao
                throw new SAXException(ioe.getMessage());
1126
            }
1127
1128
            //check if user changed inine data or not if user doesn't have
1129 2245 sgarg
            // write permission for this inline block
1130
            // if some error happends, we would delete the inline data file here,
1131
            // we will call a method named deletedInlineFiles in DocumentImple
1132
            if (unWritableInlineDataObject)
1133
            {
1134
                if (unReadableInlineDataObject)
1135
                {
1136
                  // now user just got a empty string in linline part
1137
                  // so if the user send back a empty string is fine and we will
1138
                  // copy the old file to new file. If he send something else,
1139
                  // the document will be rejected
1140
                  if (inlineDataIsEmpty(inlineDataFileName))
1141
                  {
1142
                    copyInlineFile(distributionId, inlineDataFileName);
1143
                  }
1144
                  else
1145
                  {
1146 2663 sgarg
                    logMetacat.info(
1147 2245 sgarg
                               "inline data was changed by a user"
1148 2663 sgarg
                                       + " who doesn't have permission");
1149 2245 sgarg
                    throw new SAXException(PERMISSIONERROR);
1150
1151
                  }
1152
                }//if
1153
                else
1154
                {
1155
                  // user get the inline data
1156
                  if (modifiedInlineData(distributionId, inlineDataFileName))
1157
                  {
1158 2663 sgarg
                    logMetacat.info(
1159 2161 tao
                                "inline data was changed by a user"
1160 2663 sgarg
                                        + " who doesn't have permission");
1161 2161 tao
                    throw new SAXException(PERMISSIONERROR);
1162 2245 sgarg
                  }//if
1163
                }//else
1164
            }//if
1165
            else
1166
            {
1167
               //now user can update file.
1168
               if (unReadableInlineDataObject)
1169
               {
1170
                  // now user just got a empty string in linline part
1171
                  // so if the user send back a empty string is fine and we will
1172
                  // copy the old file to new file. If he send something else,
1173
                  // the new inline data will overwite the old one(here we need
1174
                  // do nothing because the new inline data already existed
1175
                  if (inlineDataIsEmpty(inlineDataFileName))
1176
                  {
1177
                    copyInlineFile(distributionId, inlineDataFileName);
1178
                  }
1179
                }//if
1180 2161 tao
1181 2245 sgarg
            }//else
1182
            // put inline data file name into text buffer (without path)
1183 2161 tao
            textBuffer = new StringBuffer(inlineDataFileName);
1184
            // write file name into db
1185
            endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer,
1186
                    currentNode);
1187
            // reset textbuff
1188
            textBuffer = null;
1189
            textBuffer = new StringBuffer();
1190 2245 sgarg
            // resetinlinedata file name
1191
            inlineDataFileName = null;
1192
            unWritableInlineDataObject = false;
1193
            unReadableInlineDataObject = false;
1194 2161 tao
            return;
1195
        }
1196 2245 sgarg
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1197
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1198 2161 tao
1199 2245 sgarg
1200
1201
        // close element which is not in inline data
1202
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1203
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1204
        if (!handleInlineData)
1205
        {
1206 2161 tao
            // Get the node from the stack
1207
            DBSAXNode currentNode = (DBSAXNode) nodeStack.pop();
1208
            String currentTag = currentNode.getTagName();
1209
1210
            // If before the end element, the parser hit text nodes and store
1211
            // them
1212
            // into the buffer, write the buffer to data base. The reason we
1213
            // put
1214
            // write database here is for xerces some time split text node
1215 2245 sgarg
            if (hitTextNode)
1216
            {
1217 2161 tao
                // get access value
1218
                String data = null;
1219
                // add principal
1220 2245 sgarg
                if (currentTag.equals(PRINCIPAL) && accessRule != null)
1221
                {
1222 2161 tao
                    data = (textBuffer.toString()).trim();
1223
                    accessRule.addPrincipal(data);
1224
1225 2245 sgarg
                }
1226
                else if (currentTag.equals(PERMISSION) && accessRule != null)
1227
                {
1228 2161 tao
                    data = (textBuffer.toString()).trim();
1229
                    // we conbine different a permission into one value
1230
                    int permission = accessRule.getPermission();
1231
                    // add permision
1232 2245 sgarg
                    if (data.toUpperCase().equals(READSTRING))
1233
                    {
1234 2161 tao
                        permission = permission | READ;
1235 2245 sgarg
                    }
1236
                    else if (data.toUpperCase().equals(WRITESTRING))
1237
                    {
1238 2161 tao
                        permission = permission | WRITE;
1239 2245 sgarg
                    }
1240
                    else if (data.toUpperCase().equals(CHMODSTRING))
1241
                    {
1242 2161 tao
                        permission = permission | CHMOD;
1243 2245 sgarg
                    }
1244
                    else if (data.toUpperCase().equals(ALLSTRING))
1245
                    {
1246 2161 tao
                        permission = permission | ALL;
1247
                    }
1248
                    accessRule.setPermission(permission);
1249
                }
1250
                // put additionalmetadata/describes into vector
1251 2245 sgarg
                else if (currentTag.equals(DESCRIBES))
1252
                {
1253 2161 tao
                    data = (textBuffer.toString()).trim();
1254
                    describesId.add(data);
1255 2245 sgarg
                    //firstDescribesInAdditionalMetadata = false;
1256
                    //firstDescribesNodeId = 0;
1257
                }
1258
                else if (currentTag.equals(REFERENCES)
1259 5311 daigle
                        && (processTopLevelAccess || processAdditionalAccess || processOtherAccess))
1260 2245 sgarg
                {
1261 2161 tao
                    // get reference
1262
                    data = (textBuffer.toString()).trim();
1263
                    // put reference id into accessSection
1264
                    accessObject.setReferences(data);
1265
1266 2245 sgarg
                }
1267
                else if (currentTag.equals(REFERENCES) && proccessDistribution)
1268
                {
1269
                  // get reference for distribution
1270
                  data = (textBuffer.toString()).trim();
1271
                  // we only stored the distribution reference which itself
1272
                  // has a id
1273
                  if (distributionId != null)
1274
                  {
1275
                    distributionReferenceList.put(distributionId, data);
1276
                  }
1277
1278
                }
1279 5311 daigle
                else if (currentTag.equals(URL) && !inAdditionalMetaData)
1280 2245 sgarg
                {
1281 2161 tao
                    //handle online data, make sure its'parent is online
1282
                    DBSAXNode parentNode = (DBSAXNode) nodeStack.peek();
1283
                    if (parentNode != null && parentNode.getTagName() != null
1284 2245 sgarg
                            && parentNode.getTagName().equals(ONLINE))
1285
                    {
1286 2161 tao
                        data = (textBuffer.toString()).trim();
1287 2245 sgarg
                        if (distributionId != null)
1288
                        {
1289
                          onlineURLDistributionIdList.put(distributionId, data);
1290
                        }
1291
                        else
1292
                        {
1293 4501 daigle
                          onlineURLDistributionListWithoutId.add(data);
1294 2245 sgarg
                        }
1295 2161 tao
                    }//if
1296
                }//else if
1297
                // write text to db if it is not inline data
1298 2245 sgarg
1299 2663 sgarg
                logMetacat.info(
1300
                            "Write text into DB in End Element");
1301 2245 sgarg
1302
                 // write text node into db
1303
                 endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer,
1304 2161 tao
                            currentNode);
1305 2245 sgarg
1306 5311 daigle
                if (needToCheckAccessModule
1307
                        && (processAdditionalAccess || processOtherAccess || processTopLevelAccess)) {
1308 2161 tao
                    // stored the pull out nodes into storedNode stack
1309
                    NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "TEXT",
1310 4698 daigle
                            null, null, MetacatUtil.normalize(textBuffer
1311 2161 tao
                                    .toString()));
1312
                    storedAccessNodeStack.push(nodeElement);
1313
1314
                }
1315 2245 sgarg
            }//if handle text node
1316 2161 tao
1317
1318 2245 sgarg
1319 2161 tao
            //set hitText false
1320
            hitTextNode = false;
1321
            // reset textbuff
1322
            textBuffer = null;
1323
            textBuffer = new StringBuffer();
1324
1325
1326
            // access stuff
1327 2245 sgarg
            if (currentTag.equals(ALLOW) || currentTag.equals(DENY))
1328
            {
1329 2161 tao
                // finish parser a ccess rule and assign it to new one
1330
                AccessRule newRule = accessRule;
1331
                //add the new rule to access section object
1332
                accessObject.addAccessRule(newRule);
1333
                // reset access rule
1334
                accessRule = null;
1335 2245 sgarg
            }// ALLOW or DENY
1336
            else if (currentTag.equals(ACCESS))
1337
            {
1338
                // finish parse a access setction and stored them into different
1339
                // places
1340 2161 tao
1341
                accessObject.setEndNodeId(endNodeId);
1342
                AccessSection newAccessObject = accessObject;
1343 2245 sgarg
                newAccessObject.setStoredTmpNodeStack(storedAccessNodeStack);
1344
                if (newAccessObject != null)
1345
                {
1346 2161 tao
1347 5311 daigle
                    if (processTopLevelAccess)
1348 2245 sgarg
                    {
1349
                       topAccessSection = newAccessObject;
1350 2161 tao
1351
                    }//if
1352 2245 sgarg
                    else if (processAdditionalAccess)
1353
                    {
1354 2161 tao
                        // for additional control
1355 2245 sgarg
                        // put discribesId into the accessobject and put this
1356
                        // access object into vector
1357
                        newAccessObject.setDescribedIdList(describesId);
1358 5166 daigle
                        additionalAccessVector.add(newAccessObject);
1359 2161 tao
1360
                    }//if
1361 2245 sgarg
                    else if (processOtherAccess)
1362
                    {
1363
                      // we only stored the access object which has a id
1364
                      // because only the access object which has a id can
1365
                      // be reference
1366
                      if (newAccessObject.getSubTreeId() != null &&
1367
                          !newAccessObject.getSubTreeId().trim().equals(""))
1368
                      {
1369
                         possibleReferencedAccessHash.
1370
                           put(newAccessObject.getSubTreeId(), newAccessObject);
1371
                      }
1372
                    }
1373 2161 tao
1374
                }//if
1375
                //reset access section object
1376
                accessObject = null;
1377
1378
                // reset tmp stored node stack
1379
                storedAccessNodeStack = null;
1380
                storedAccessNodeStack = new Stack();
1381
1382
                // reset flag
1383
                processAdditionalAccess = false;
1384 5311 daigle
                processTopLevelAccess = false;
1385 2161 tao
                processOtherAccess = false;
1386
1387 2245 sgarg
            }//access element
1388
            else if (currentTag.equals(ADDITIONALMETADATA))
1389
            {
1390 2161 tao
                //reset describesId
1391
                describesId = null;
1392
                describesId = new Vector();
1393 5311 daigle
                inAdditionalMetaData = false;
1394 2278 sgarg
                firstDescribesNodeId = -1;
1395
                // reset tmp stored node stack
1396
                storedAccessNodeStack = null;
1397
                storedAccessNodeStack = new Stack();
1398 2245 sgarg
1399 2278 sgarg
1400 2161 tao
            }
1401 5311 daigle
            else if (currentTag.equals(DISTRIBUTION) && !inAdditionalMetaData)
1402 2245 sgarg
            {
1403
               //reset distribution id
1404
               distributionId = null;
1405
               proccessDistribution = false;
1406
            }
1407 5311 daigle
            else if (currentTag.equals(OFFLINE) && !inAdditionalMetaData)
1408 2245 sgarg
            {
1409
               if (distributionId != null)
1410
               {
1411
                 offlineDistributionIdList.put(distributionId, distributionId);
1412
               }
1413
            }
1414
            else if ((currentTag.equals(CONNECTION) || currentTag.equals(CONNECTIONDEFINITION))
1415 5311 daigle
                     && !inAdditionalMetaData)
1416 2245 sgarg
            {
1417
              //handle online data, make sure its'parent is online
1418
                 DBSAXNode parentNode = (DBSAXNode) nodeStack.peek();
1419
                 if (parentNode != null && parentNode.getTagName() != null
1420
                         && parentNode.getTagName().equals(ONLINE))
1421
                 {
1422
                     if (distributionId != null)
1423
                     {
1424
                        onlineOtherDistributionIdList.put(distributionId, distributionId);
1425
                     }
1426
                 }//if
1427
1428
            }//else if
1429
            else if (currentTag.equals(DESCRIBES))
1430
            {
1431
                firstDescribesInAdditionalMetadata = false;
1432 2278 sgarg
1433 2245 sgarg
            }
1434
1435
1436
1437
        }
1438
        // close elements which are in inline data (inline data can be xml doc)
1439
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1440
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1441
        else
1442
        {
1443 2161 tao
            // this is in inline part
1444
            StringBuffer endElement = new StringBuffer();
1445
            endElement.append("</");
1446
            endElement.append(qName);
1447
            endElement.append(">");
1448 2663 sgarg
            logMetacat.info("inline endElement: "
1449
                    + endElement.toString());
1450 2161 tao
            writeInlineDataIntoFile(inlineDataFileWriter, endElement);
1451
        }
1452 2245 sgarg
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1453
        //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1454 2161 tao
    }
1455
1456 2245 sgarg
1457
    /*
1458
     * Method to check if the new line data is as same as the old one
1459
     */
1460
     private boolean modifiedInlineData(String inlineDistributionId,
1461 4080 daigle
			String newInlineInternalFileName) throws SAXException {
1462 2245 sgarg
       boolean modified = true;
1463
       if (inlineDistributionId == null || newInlineInternalFileName == null)
1464
       {
1465
         return modified;
1466
       }
1467
       String oldInlineInternalFileName =
1468
            (String)previousUnwritableInlineDataObjectHash.get(inlineDistributionId);
1469
       if (oldInlineInternalFileName == null ||
1470
           oldInlineInternalFileName.trim().equals(""))
1471
       {
1472
         return modified;
1473
       }
1474 2663 sgarg
       logMetacat.info("in handle inline data");
1475
       logMetacat.info("the inline data file name from xml_access is: "
1476
                                    + oldInlineInternalFileName);
1477 2245 sgarg
1478
       try
1479
       {
1480
         if (!compareInlineDataFiles(oldInlineInternalFileName,
1481
                                     newInlineInternalFileName))
1482
         {
1483
           modified = true;
1484
1485
         }
1486
         else
1487
         {
1488
           modified = false;
1489
         }
1490
       }
1491
       catch(Exception e)
1492
       {
1493
         modified = true;
1494
       }
1495
1496
       // delete the inline data file already in file system
1497
       if (modified)
1498
       {
1499
         deleteInlineDataFile(newInlineInternalFileName);
1500
1501
       }
1502
       return modified;
1503
     }
1504
1505
     /*
1506
      * A method to check if a line file is empty
1507
      */
1508
     private boolean inlineDataIsEmpty(String fileName) throws SAXException
1509
     {
1510
        boolean isEmpty = true;
1511
        if ( fileName == null)
1512
        {
1513
          throw new SAXException("The inline file name is null");
1514
        }
1515 4080 daigle
1516
        try {
1517
			String path = PropertyService.getProperty("application.inlinedatafilepath");
1518
			// the new file name will look like path/docid.rev.2
1519
			File inlineDataDirectory = new File(path);
1520
			File inlineDataFile = new File(inlineDataDirectory, fileName);
1521 2245 sgarg
1522 5752 leinfelder
			Reader inlineFileReader = new InputStreamReader(new FileInputStream(inlineDataFile), encoding);
1523 4080 daigle
			BufferedReader inlineStringReader = new BufferedReader(inlineFileReader);
1524
			String string = inlineStringReader.readLine();
1525
			// at the end oldstring will be null
1526
			while (string != null) {
1527
				string = inlineStringReader.readLine();
1528
				if (string != null && !string.trim().equals("")) {
1529
					isEmpty = false;
1530
					break;
1531
				}
1532
			}
1533 2245 sgarg
1534 4080 daigle
		} catch (Exception e) {
1535
			throw new SAXException(e.getMessage());
1536
		}
1537
		return isEmpty;
1538
1539 2245 sgarg
     }
1540
1541
1542 2161 tao
    /**
1543 4080 daigle
	 * SAX Handler that receives notification of comments in the DTD
1544
	 */
1545 2161 tao
    public void comment(char[] ch, int start, int length) throws SAXException
1546
    {
1547 2663 sgarg
        logMetacat.info("COMMENT");
1548 2161 tao
        if (!handleInlineData) {
1549
            if (!processingDTD) {
1550
                DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
1551
                String str = new String(ch, start, length);
1552
1553
                //compare comment if need
1554 2245 sgarg
                /*if (startCriticalSubTree) {
1555 2161 tao
                    compareCommentNode(currentUnChangedableSubtreeNodeStack,
1556
                            str, PERMISSIONERROR);
1557 2245 sgarg
                }//if*/
1558 2161 tao
                //compare top level access module
1559 5311 daigle
                if (processTopLevelAccess && needToCheckAccessModule) {
1560 2245 sgarg
                    /*compareCommentNode(currentUnchangableAccessModuleNodeStack,
1561
                            str, UPDATEACCESSERROR);*/
1562 2161 tao
                }
1563
                endNodeId = currentNode.writeChildNodeToDB("COMMENT", null,
1564
                        str, docid);
1565 5311 daigle
                if (needToCheckAccessModule
1566
                        && (processAdditionalAccess || processOtherAccess || processTopLevelAccess)) {
1567 2161 tao
                    // stored the pull out nodes into storedNode stack
1568
                    NodeRecord nodeElement = new NodeRecord(-2, -2, -2,
1569 4698 daigle
                            "COMMENT", null, null, MetacatUtil.normalize(str));
1570 2161 tao
                    storedAccessNodeStack.push(nodeElement);
1571
1572
                }
1573
            }
1574
        } else {
1575
            // inline data comment
1576
            StringBuffer inlineComment = new StringBuffer();
1577
            inlineComment.append("<!--");
1578
            inlineComment.append(new String(ch, start, length));
1579
            inlineComment.append("-->");
1580 2663 sgarg
            logMetacat.info("inline data comment: "
1581
                    + inlineComment.toString());
1582 2161 tao
            writeInlineDataIntoFile(inlineDataFileWriter, inlineComment);
1583
        }
1584
    }
1585
1586
1587 2245 sgarg
1588 2161 tao
    /**
1589
     * SAX Handler called once for each processing instruction found: node that
1590
     * PI may occur before or after the root element.
1591
     */
1592
    public void processingInstruction(String target, String data)
1593
            throws SAXException
1594
    {
1595 2663 sgarg
        logMetacat.info("PI");
1596 2161 tao
        if (!handleInlineData) {
1597
            DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
1598
            endNodeId = currentNode.writeChildNodeToDB("PI", target, data,
1599
                    docid);
1600
        } else {
1601
            StringBuffer inlinePI = new StringBuffer();
1602
            inlinePI.append("<?");
1603
            inlinePI.append(target);
1604
            inlinePI.append(" ");
1605
            inlinePI.append(data);
1606
            inlinePI.append("?>");
1607 2663 sgarg
            logMetacat.info("inline data pi is: "
1608
                    + inlinePI.toString());
1609 2161 tao
            writeInlineDataIntoFile(inlineDataFileWriter, inlinePI);
1610
        }
1611
    }
1612
1613
    /** SAX Handler that is called at the start of Namespace */
1614
    public void startPrefixMapping(String prefix, String uri)
1615
            throws SAXException
1616
    {
1617 2663 sgarg
        logMetacat.info("NAMESPACE");
1618
        logMetacat.info("NAMESPACE prefix "+prefix);
1619
        logMetacat.info("NAMESPACE uri "+uri);
1620 2161 tao
        if (!handleInlineData) {
1621
            namespaces.put(prefix, uri);
1622
        } else {
1623
            inlineDataNameSpace.put(prefix, uri);
1624
        }
1625
    }
1626
1627
    /**
1628
     * SAX Handler that is called for each XML text node that is Ignorable
1629
     * white space
1630
     */
1631
    public void ignorableWhitespace(char[] cbuf, int start, int len)
1632
            throws SAXException
1633
    {
1634
        // When validation is turned "on", white spaces are reported here
1635
        // When validation is turned "off" white spaces are not reported here,
1636
        // but through characters() callback
1637 2663 sgarg
        logMetacat.info("IGNORABLEWHITESPACE");
1638 2161 tao
        if (!handleInlineData) {
1639
            DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
1640 5208 daigle
            String data = new String(cbuf, start, len);
1641 2161 tao
1642
                //compare whitespace in access top module
1643 5311 daigle
                if (processTopLevelAccess && needToCheckAccessModule) {
1644 2245 sgarg
                    /*compareWhiteSpace(currentUnchangableAccessModuleNodeStack,
1645
                            data, UPDATEACCESSERROR);*/
1646 2161 tao
                }
1647
                // Write the content of the node to the database
1648 5311 daigle
                if (needToCheckAccessModule
1649
                        && (processAdditionalAccess || processOtherAccess || processTopLevelAccess)) {
1650 2161 tao
                    // stored the pull out nodes into storedNode stack
1651
                    NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "TEXT",
1652 4698 daigle
                            null, null, MetacatUtil.normalize(data));
1653 2161 tao
                    storedAccessNodeStack.push(nodeElement);
1654
1655
                }
1656
                endNodeId = currentNode.writeChildNodeToDB("TEXT", null, data,
1657
                        docid);
1658
        } else {
1659
            //This is inline data write to file directly
1660
            StringBuffer inlineWhiteSpace = new StringBuffer(new String(cbuf,
1661
                    start, len));
1662
            writeInlineDataIntoFile(inlineDataFileWriter, inlineWhiteSpace);
1663
        }
1664
1665
    }
1666
1667
1668
    /** SAX Handler that receives notification of end of the document */
1669
    public void endDocument() throws SAXException
1670
    {
1671 2663 sgarg
        logMetacat.info("end Document");
1672 5311 daigle
        if (needToCheckAccessModule)
1673 2245 sgarg
        {
1674
          compareAllAccessModules();
1675 2161 tao
        }
1676
1677 2245 sgarg
        // user deleted some inline block which it counldn't delete
1678
        if (numberOfHitUnWritableInlineData !=
1679
            previousUnwritableInlineDataObjectHash.size())
1680
        {
1681
          throw new SAXException("user deleted some inline block it couldn't");
1682
        }
1683
1684 2608 tao
        if (!super.getIsRevisionDoc())
1685
        {
1686
          // write access rule to xml_access table which include both top level
1687
          // and additional level(data access level). It also write access subtree
1688
          // info into xml_accesssubtree about the top access, additional access
1689
          // and some third place access modules which are referenced by top
1690
          // level or additional level
1691
          writeAccessRuleToDB();
1692 2161 tao
1693 2608 tao
          //delete relation table
1694
          deleteRelations();
1695
          //write relations
1696
           for (int i = 0; i < onlineDataFileIdInRelationVector.size(); i++) {
1697 2165 tao
            String id = (String) onlineDataFileIdInRelationVector.elementAt(i);
1698 2161 tao
            writeOnlineDataFileIdIntoRelationTable(id);
1699 2608 tao
           }
1700 2161 tao
        }
1701
1702 2245 sgarg
        // clean the subtree record
1703
        accessSubTreeAlreadyWriteDBList = new Hashtable();
1704 2161 tao
    }
1705
1706
1707 2245 sgarg
1708
    /* The method will compare all access modules in eml document -
1709
     * topLevel, additionalLevel(data access) and referenced access module*/
1710
    private void compareAllAccessModules() throws SAXException
1711 2161 tao
    {
1712 2245 sgarg
      //compare top level
1713 5311 daigle
      compareAccessSubtree(topAccessSubTreeFromDB, topAccessSection);
1714 2161 tao
1715 2245 sgarg
      //compare additional level
1716 5311 daigle
      int oldSize = additionalAccessSubTreeListFromDB.size();
1717 5166 daigle
      int newSize = additionalAccessVector.size();
1718 2245 sgarg
      // if size is different, use deleted or added rules, so throw a exception
1719
      if (oldSize != newSize)
1720
      {
1721
        throw new SAXException(UPDATEACCESSERROR);
1722
      }
1723
      //because access modules are both ordered in ASC in vectors, so we can
1724
      // compare one bye one
1725
      for ( int i = 0; i < newSize; i++)
1726
      {
1727
        AccessSection fromDB = (AccessSection)
1728 5311 daigle
                          additionalAccessSubTreeListFromDB.elementAt(i);
1729 2245 sgarg
        AccessSection fromParser = (AccessSection)
1730 5166 daigle
                                additionalAccessVector.elementAt(i);
1731 2245 sgarg
        compareAccessSubtree(fromDB, fromParser);
1732
      }
1733 2161 tao
1734 2245 sgarg
      //compare referenced level
1735 5311 daigle
      Enumeration em = referencedAccessSubTreeListFromDB.keys();
1736 2245 sgarg
      while (em.hasMoreElements())
1737
      {
1738
        String id = (String)em.nextElement();
1739
        AccessSection fromDB = (AccessSection)
1740 5311 daigle
                               referencedAccessSubTreeListFromDB.get(id);
1741 2245 sgarg
        AccessSection fromParser = (AccessSection)
1742
                               possibleReferencedAccessHash.get(id);
1743
        compareAccessSubtree(fromDB, fromParser);
1744
      }
1745
    }
1746 2161 tao
1747 2245 sgarg
    /* The method will compare two access subtree. Currently they compare to
1748
     * nodes one by one. It also can be changed to parse the node first, then
1749
     * compare the parsed result
1750
     */
1751
    private void compareAccessSubtree(AccessSection fromDBTable,
1752
                                       AccessSection fromParser)
1753
                                      throws SAXException
1754
    {
1755
       if (fromDBTable == null || fromParser == null)
1756
       {
1757
         throw new SAXException(UPDATEACCESSERROR);
1758
       }
1759
       Stack nodeStackFromDBTable = fromDBTable.getSubTreeNodeStack();
1760
       Stack nodeStackFromParser  = fromParser.getStoredTmpNodeStack();
1761 2262 sgarg
1762
       Stack tempStack = new Stack();
1763
       while(!nodeStackFromDBTable.isEmpty()){
1764
           tempStack.push(nodeStackFromDBTable.pop());
1765
       }
1766
       comparingNodeStacks(tempStack, nodeStackFromParser);
1767 2245 sgarg
    }
1768 2161 tao
1769 2245 sgarg
    /* Compare two node stacks to see if they are same */
1770
  private void comparingNodeStacks(Stack stack1, Stack stack2)
1771
          throws SAXException
1772
  {
1773
      // make sure stack1 and stack2 are not empty
1774
      if (stack1.isEmpty() || stack2.isEmpty()) {
1775 2663 sgarg
          logMetacat.info("Because stack is empty!");
1776 2245 sgarg
          throw new SAXException(UPDATEACCESSERROR);
1777
      }
1778
      // go throw two stacks and compare every element
1779
      while (!stack1.isEmpty()) {
1780
          // Pop an element from stack1
1781
          NodeRecord record1 = (NodeRecord) stack1.pop();
1782 2278 sgarg
1783 2245 sgarg
          // Pop an element from stack2(stack 2 maybe empty)
1784
          NodeRecord record2 = null;
1785
          try {
1786
              record2 = (NodeRecord) stack2.pop();
1787
          } catch (EmptyStackException ee) {
1788 2278 sgarg
1789 2663 sgarg
              logMetacat.error(
1790
                      "Node stack2 is empty but stack1 isn't!");
1791 2245 sgarg
              throw new SAXException(UPDATEACCESSERROR);
1792
          }
1793
          // if two records are not same throw a exception
1794
          if (!record1.contentEquals(record2)) {
1795 2663 sgarg
              logMetacat.info("Two records from new and old stack are not "
1796
                                      + "same!" + record1 + "--" +record2);
1797 2245 sgarg
              throw new SAXException(UPDATEACCESSERROR);
1798
          }//if
1799
      }//while
1800 2165 tao
1801 2245 sgarg
      // now stack1 is empty and we should make sure stack2 is empty too
1802
      if (!stack2.isEmpty()) {
1803 2278 sgarg
1804 2663 sgarg
          logMetacat.info(
1805 2278 sgarg
                  "stack2 still have some elements while stack1 "
1806 2663 sgarg
                          + "is empty! ");
1807 2245 sgarg
          throw new SAXException(UPDATEACCESSERROR);
1808
      }//if
1809
  }//comparingNodeStacks
1810 2161 tao
1811
1812 2245 sgarg
    /* The method to write all access rule into db */
1813
    private void writeAccessRuleToDB() throws SAXException
1814
    {
1815
        // delete xml_accesssubtree table record for this docid
1816
        deleteAccessSubTreeRecord(docid);
1817
        //write additional access rule, and old records in xml_access will be
1818
        //deleted too
1819 2618 tao
        //System.out.println("before write additional access rules");
1820 5166 daigle
        writeadditionalAccessRuleToDB();
1821 2618 tao
        //System.out.println("after write additional access rules");
1822 2245 sgarg
        //write top leve access rule, and old records in xml_access will be
1823
        //deleted too
1824 2248 sgarg
1825
        if (topAccessSection != null){
1826
          writeTopLevelAccessRuleToDB();
1827
        }
1828 2618 tao
        //System.out.println("after write top access rules");
1829 2245 sgarg
    }//writeAccessRuleToDB
1830 2161 tao
1831
1832 2245 sgarg
    /* The method will figure out access reference for given access section -
1833
     * return a new AccessSection which contain access rules that be referenced.
1834
     * And will write the access subtree into xml_access table.
1835
     * this is a recursive method
1836
     */
1837
   private AccessSection resolveAccessRuleReference(AccessSection access)
1838
                                                    throws SAXException
1839
   {
1840
     if (access == null)
1841
     {
1842 2663 sgarg
       logMetacat.info("access module is null in " +
1843
                                "resolveAccessRulesReference");
1844 2245 sgarg
       throw new SAXException("An access modules is null");
1845
     }
1846
     String subTreeId = access.getSubTreeId();
1847
     if (subTreeId == null ||
1848
         (subTreeId != null && !accessSubTreeAlreadyWriteDBList.contains(subTreeId)))
1849
     {
1850
        // we should record this access subtree into accesssubtree table.
1851
        // subtreeId is null means it can't be referenced. So this tree couldn't
1852
        // be stored twise in the table. Subtree is not null, but it is in
1853
        // hash yet, so it is new one.
1854
        writeAccessSubTreeIntoDB(access);
1855
        if (subTreeId != null)
1856
        {
1857
          accessSubTreeAlreadyWriteDBList.put(subTreeId, subTreeId);
1858 2161 tao
        }
1859 2245 sgarg
     }
1860 2161 tao
1861 2245 sgarg
     String reference = access.getReferences();
1862
     if (reference != null)
1863
     {
1864
       // find the reference in top level
1865
       String topSubtreeId = topAccessSection.getSubTreeId();
1866
       if (topSubtreeId != null && topSubtreeId.equals(reference))
1867
       {
1868
          return resolveAccessRuleReference(topAccessSection);
1869
       }
1870
       else
1871
       {
1872
           // search it the additional access
1873 5166 daigle
           for ( int i = 0; i <additionalAccessVector.size(); i++)
1874 2245 sgarg
           {
1875
             AccessSection additionalAccess = (AccessSection)
1876 5166 daigle
                           additionalAccessVector.elementAt(i);
1877 2245 sgarg
             String additionId = additionalAccess.getSubTreeId();
1878
             if (additionId != null && additionId.equals(reference))
1879
             {
1880
               return resolveAccessRuleReference(additionalAccess);
1881
             }// if
1882
           }// for
1883 2161 tao
1884 2245 sgarg
           // search possible referenced access hashtable
1885
           if (possibleReferencedAccessHash.containsKey(reference))
1886
           {
1887
             AccessSection referenceAccess = (AccessSection)
1888
                         possibleReferencedAccessHash.get(reference);
1889
             return resolveAccessRuleReference(referenceAccess);
1890
           }
1891 2161 tao
1892 2245 sgarg
           // if hit here, this means you don't find any id match the reference
1893
           // throw a exception
1894
           throw new SAXException("No access module's id match the reference id");
1895
       }
1896
     }
1897
     else
1898
     {
1899
       // base line reference == null
1900
       AccessSection newAccessSection = new AccessSection();
1901
       access.copyPermOrderAndAccessRules(newAccessSection);
1902
       return newAccessSection;
1903
     }
1904
   }//resolveAccessRuleReference
1905 2161 tao
1906 2245 sgarg
   /* This method will return a id which points a real distribution block if
1907
    *  given a distribution id which is a reference. If the given id is a real
1908
    *  distribution the id itself will be returned.
1909
    *  Here is segment of eml
1910
    *   <distribution id ="100"><online><url>abc</url></online></distribution>
1911
    *   <distribution id ="200"><reference>100</reference></distribution>
1912
    * if the given value is 200, 100 will be returned.
1913
    * if the given value is 100, 100 will be returned.
1914
    */
1915
   private String resolveDistributionReference(String givenId)
1916
   {
1917
      if (givenId == null )
1918
      {
1919
        return null;
1920
      }
1921
      if (!distributionReferenceList.containsKey(givenId))
1922
      {
1923
        //this is not reference distribution block, return given id
1924
        return givenId;
1925
      }
1926
      else
1927
      {
1928
         String referencedId = (String) distributionReferenceList.get(givenId);
1929
         // search util the referenced id is not in dsitribtionReferenceList
1930
         while (distributionReferenceList.containsKey(referencedId))
1931
         {
1932
           referencedId = (String) distributionReferenceList.get(referencedId);
1933
         }
1934
         return referencedId;
1935
      }
1936
   }
1937 2161 tao
1938
1939 2245 sgarg
  /* The method to write top level access rule into db. The old rules will be
1940
   * deleted
1941
   * If no describedId in the access object, this access rules will be ingorned
1942
   */
1943 5166 daigle
  private void writeadditionalAccessRuleToDB() throws SAXException
1944 2245 sgarg
  {
1945 5166 daigle
     //System.out.println("in write additional");
1946 2245 sgarg
     // we should delete all inline access rules in xml_access if
1947
     // user has all permission
1948 5311 daigle
     if (!needToCheckAccessModule)
1949 2245 sgarg
     {
1950
       deleteAllInlineDataAccessRules();
1951
     }
1952 5166 daigle
     for (int i=0; i < additionalAccessVector.size(); i++)
1953 2245 sgarg
     {
1954 5166 daigle
       //System.out.println("in for loop of write additional");
1955
       AccessSection access = (AccessSection)additionalAccessVector.elementAt(i);
1956 2245 sgarg
       Vector describeIdList = access.getDescribedIdList();
1957
       // if this access is a reference, a new access object will be created
1958
       // which contains the real access rules referenced. Also, each access tree
1959
       // will be write into xml_accesssubtee table
1960
       AccessSection newAccess = resolveAccessRuleReference(access);
1961
       String permOrder = newAccess.getPermissionOrder();
1962
       Vector accessRule = newAccess.getAccessRules();
1963 2161 tao
1964 2245 sgarg
       if (describeIdList == null || describeIdList.isEmpty())
1965
       {
1966
         continue;
1967
       }
1968 2161 tao
1969 2245 sgarg
       for (int j = 0; j < describeIdList.size(); j++)
1970
       {
1971
         String subreeid = (String)describeIdList.elementAt(j);
1972 2663 sgarg
         logMetacat.info("describe id in additional access " +
1973
                                  subreeid);
1974 2245 sgarg
         // we need to figure out the real id if this subreeid is points to
1975
         // a distribution reference.
1976
         subreeid = resolveDistributionReference(subreeid);
1977
         if (subreeid != null && !subreeid.trim().equals(""))
1978
         {
1979 2663 sgarg
           logMetacat.info("subtree id is "+ subreeid +
1980
                                    " after resolve reference id" );
1981 2245 sgarg
           // if this id is for line data, we need to delete the records first
1982
           // then add new records. The key for deleting is subtee id
1983
           if (inlineDistributionIdList.containsKey(subreeid))
1984
           {
1985
             String inlineFileName = (String)
1986
                                        inlineDistributionIdList.get(subreeid);
1987
             deleteSubtreeAccessRule(subreeid);
1988 2663 sgarg
             logMetacat.info("Write inline data access into " +
1989
                                   "xml_access table for"+ inlineFileName);
1990 2245 sgarg
             writeGivenAccessRuleIntoDB(permOrder, accessRule,
1991
                                        inlineFileName, subreeid);
1992
           }
1993
           else if (onlineURLDistributionIdList.containsKey(subreeid))
1994
           {
1995
             String url = (String)onlineURLDistributionIdList.get(subreeid);
1996
             //this method will extrace data file id from url. It also will
1997
             // check if user can change the access rules for the data file id.
1998
             // if couldn't, it will throw a exception. Morover, the docid will
1999
             // be to relation id vector too.
2000
             // for online data, the subtree id we set is null.
2001
             // So in xml_access, only the inline data subteeid is not null
2002
             String dataFileName = handleOnlineUrlDataFile(url);
2003 2663 sgarg
             logMetacat.info("The data fileName in online url " +
2004
                                      dataFileName);
2005 2245 sgarg
             if (dataFileName != null)
2006
             {
2007
               deletePermissionsInAccessTableForDoc(dataFileName);
2008
               writeGivenAccessRuleIntoDB(permOrder, accessRule,
2009
                                          dataFileName, null);
2010 2663 sgarg
               logMetacat.info("Write online data access into " +
2011
                                   "xml_access table for " + dataFileName);
2012 2245 sgarg
               // put the id into a hashtalbe. So when we run wirtetop level
2013
               // access, those id will be ignored because they already has
2014
               // additional access rules
2015 5166 daigle
               onlineURLIdHasadditionalAccess.put(subreeid, subreeid);
2016 2245 sgarg
             }
2017
           }//elseif
2018
         }//if
2019
       }//for
2020
     }//for
2021 2161 tao
2022 2245 sgarg
   }//writeAdditonalLevelAccessRuletoDB
2023 2161 tao
2024
2025 5166 daigle
    /* The method to write additional access rule into db. */
2026 2245 sgarg
    private void writeTopLevelAccessRuleToDB() throws SAXException
2027 2161 tao
    {
2028 2245 sgarg
       // if top access is reference, we need figure out the real access rules
2029
       // it points to
2030 2618 tao
       //System.out.println("permorder in top level" + topAccessSection.getPermissionOrder());
2031 2245 sgarg
       AccessSection newAccess = resolveAccessRuleReference(topAccessSection);
2032 2618 tao
       //System.out.println("permorder in new level" + newAccess.getPermissionOrder());
2033 2245 sgarg
       String permOrder = newAccess.getPermissionOrder();
2034
       Vector accessRule = newAccess.getAccessRules();
2035
       String subtree     = null;
2036
       // document itself
2037
       deletePermissionsInAccessTableForDoc(docid);
2038
       writeGivenAccessRuleIntoDB(permOrder, accessRule, docid, subtree);
2039
       // for online data, it includes with id and without id.
2040
       // 1. for the data with subtree id, we should ignore the ones already in
2041
       // the hash - onlineURLIdHasAddionalAccess.
2042
       // 2. for those without subreeid, it couldn't have additional access and we
2043
       // couldn't ignore it.
2044
       // 3. for inline data, we need do nothing because if it doesn't have
2045
       // additional access, it default value is the top one.
2046 2161 tao
2047 2245 sgarg
       // here is the online url with id
2048
       Enumeration em = onlineURLDistributionIdList.keys();
2049
       while (em.hasMoreElements())
2050
       {
2051
         String onlineSubtreeId = (String)em.nextElement();
2052 5166 daigle
         if (!onlineURLIdHasadditionalAccess.containsKey(onlineSubtreeId))
2053 2245 sgarg
         {
2054
            String url =
2055
                       (String)onlineURLDistributionIdList.get(onlineSubtreeId);
2056
            String onlineDataId = handleOnlineUrlDataFile(url);
2057
            if (onlineDataId != null)
2058
            {
2059
              deletePermissionsInAccessTableForDoc(onlineDataId);
2060
              writeGivenAccessRuleIntoDB(permOrder, accessRule,
2061
                                         onlineDataId, subtree);
2062 2161 tao
            }
2063
2064 2245 sgarg
         }
2065
       }//while
2066 2161 tao
2067 2245 sgarg
       // here is the onlineURL without id
2068 4501 daigle
       for (int i= 0; i < onlineURLDistributionListWithoutId.size(); i++)
2069 2245 sgarg
       {
2070 4501 daigle
         String url = (String)onlineURLDistributionListWithoutId.elementAt(i);
2071 2245 sgarg
         String onlineDataId = handleOnlineUrlDataFile(url);
2072
         if (onlineDataId != null)
2073
         {
2074
           deletePermissionsInAccessTableForDoc(onlineDataId);
2075
           writeGivenAccessRuleIntoDB(permOrder, accessRule,
2076
                                         onlineDataId, subtree);
2077
         }
2078
       }//for
2079
    }//writeTopAccessRuletoDB
2080 2161 tao
2081
    /* Write a gaven access rule into db */
2082 6019 leinfelder
    private void writeGivenAccessRuleIntoDB(String permOrder, Vector accessRules,
2083 2245 sgarg
                     String dataId, String subTreeId) throws SAXException
2084 2161 tao
    {
2085 2245 sgarg
      if (permOrder == null || permOrder.trim().equals("") || dataId == null ||
2086
          dataId.trim().equals("") || accessRules == null ||
2087
          accessRules.isEmpty())
2088
      {
2089 2663 sgarg
        logMetacat.info("The access object is null and tried to " +
2090
                                  " write to xml_access table");
2091 2245 sgarg
        throw new SAXException("The access object is null");
2092
      }
2093 6019 leinfelder
       // get rid of rev from dataId
2094
       //dataId = MetacatUtil.getDocIdFromString(dataId);
2095
       //String permOrder = accessSection.getPermissionOrder();
2096
       String sql = null;
2097
       PreparedStatement pstmt = null;
2098
       sql = "INSERT INTO xml_access (docid, principal_name, permission, "
2099
               + "perm_type, perm_order, accessfileid, subtreeid) VALUES "
2100
               + " (?, ?, ?, ?, ?, ?, ?)";
2101
2102
       try
2103
       {
2104
2105
           pstmt = connection.prepareStatement(sql);
2106
           // Increase DBConnection usage count
2107
           connection.increaseUsageCount(1);
2108
           // Bind the values to the query
2109
           pstmt.setString(1, dataId);
2110
           logMetacat.info("Docid in accesstable: " + docid);
2111
           pstmt.setString(6, docid);
2112
           logMetacat.info("Accessfileid in accesstable: " + docid);
2113
           pstmt.setString(5, permOrder);
2114
           logMetacat.info("PermOder in accesstable: " + permOrder);
2115
           pstmt.setString(7, subTreeId);
2116
           logMetacat.info("subtree id in accesstable: " + subTreeId);
2117
           // if it is not top level, set s id
2118
2119
           //Vector accessRules = accessSection.getAccessRules();
2120 2245 sgarg
           // go through every rule
2121 6019 leinfelder
           for (int i = 0; i < accessRules.size(); i++)
2122
           {
2123
               AccessRule rule = (AccessRule) accessRules.elementAt(i);
2124 2245 sgarg
               String permType = rule.getPermissionType();
2125
               int permission = rule.getPermission();
2126 6019 leinfelder
               pstmt.setInt(3, permission);
2127
               logMetacat.info("permission in accesstable: "
2128
                       + permission);
2129
               pstmt.setString(4, permType);
2130
               logMetacat.info(
2131
                       "Permtype in accesstable: " + permType);
2132 2245 sgarg
               // go through every principle in rule
2133
               Vector nameVector = rule.getPrincipal();
2134 6019 leinfelder
               for (int j = 0; j < nameVector.size(); j++)
2135
               {
2136 2245 sgarg
                   String prName = (String) nameVector.elementAt(j);
2137 6019 leinfelder
                   pstmt.setString(2, prName);
2138
                   logMetacat.info("Principal in accesstable: "
2139
                           + prName);
2140
                   logMetacat.debug("running sql: " + pstmt.toString());
2141
                   pstmt.execute();
2142 2245 sgarg
               }//for
2143
           }//for
2144 6019 leinfelder
           pstmt.close();
2145 2245 sgarg
       }//try
2146 6019 leinfelder
       catch (SQLException e)
2147
       {
2148 2245 sgarg
           throw new SAXException("EMLSAXHandler.writeAccessRuletoDB(): "
2149
                   + e.getMessage());
2150
       }//catch
2151 6019 leinfelder
       finally
2152
       {
2153
           try
2154
           {
2155
               pstmt.close();
2156
           }
2157
           catch (SQLException ee)
2158
           {
2159
               throw new SAXException("EMLSAXHandler.writeAccessRuletoDB(): "
2160
                       + ee.getMessage());
2161
           }
2162
       }//finally
2163 2161 tao
2164 2245 sgarg
    }//writeGivenAccessRuleIntoDB
2165 2161 tao
2166 2245 sgarg
2167
    /* Delete from db all permission for resources related to @docid if any. */
2168
    private void deletePermissionsInAccessTableForDoc(String docid)
2169 2161 tao
            throws SAXException
2170
    {
2171
        Statement stmt = null;
2172
        try {
2173
            // delete all acl records for resources related to @aclid if any
2174
            stmt = connection.createStatement();
2175
            // Increase DBConnection usage count
2176
            connection.increaseUsageCount(1);
2177 2245 sgarg
            stmt.execute("DELETE FROM xml_access WHERE docid = '"
2178
                    + docid + "'");
2179 2161 tao
2180
        } catch (SQLException e) {
2181
            throw new SAXException(e.getMessage());
2182
        } finally {
2183
            try {
2184
                stmt.close();
2185
            } catch (SQLException ee) {
2186
                throw new SAXException(ee.getMessage());
2187
            }
2188
        }
2189
    }//deletePermissionsInAccessTable
2190
2191 2245 sgarg
    /* Delete access rules from xml_access for a subtee id */
2192
    private void deleteSubtreeAccessRule(String subtreeid) throws SAXException
2193
    {
2194
      Statement stmt = null;
2195
       try
2196
       {
2197
           stmt = connection.createStatement();
2198
           // Increase DBConnection usage count
2199
           connection.increaseUsageCount(1);
2200
           stmt.execute("DELETE FROM xml_access WHERE accessfileid = '"
2201
                   + docid + "' AND subtreeid ='" + subtreeid +"'");
2202
       }
2203
       catch (SQLException e)
2204
       {
2205
           throw new SAXException(e.getMessage());
2206
       }
2207
       finally
2208
       {
2209
           try
2210
           {
2211
               stmt.close();
2212
           }
2213
           catch (SQLException ee)
2214
           {
2215
               throw new SAXException(ee.getMessage());
2216
           }
2217
       }
2218
2219
    }
2220
2221
    private void deleteAllInlineDataAccessRules() throws SAXException
2222
    {
2223
      Statement stmt = null;
2224
       try
2225
       {
2226
           stmt = connection.createStatement();
2227
           // Increase DBConnection usage count
2228
           connection.increaseUsageCount(1);
2229
           stmt.execute("DELETE FROM xml_access WHERE accessfileid = '"
2230
                   + docid + "' AND subtreeid IS NOT NULL");
2231
       }
2232
       catch (SQLException e)
2233
       {
2234
           throw new SAXException(e.getMessage());
2235
       }
2236
       finally
2237
       {
2238
           try
2239
           {
2240
               stmt.close();
2241
           }
2242
           catch (SQLException ee)
2243
           {
2244
               throw new SAXException(ee.getMessage());
2245
           }
2246
       }
2247
2248
    }
2249
2250 2161 tao
    /*
2251
     * In order to make sure only usr has "all" permission can update access
2252
     * subtree in eml document we need to keep access subtree info in
2253
     * xml_accesssubtree table, such as docid, version, startnodeid, endnodeid
2254
     */
2255 2245 sgarg
    private void writeAccessSubTreeIntoDB(AccessSection accessSection)
2256
                                          throws SAXException
2257 2161 tao
    {
2258 2245 sgarg
        if (accessSection == null)
2259
        {
2260 2161 tao
2261 2663 sgarg
          logMetacat.info("Access object is null and tried to write "+
2262
                                   "into access subtree table");
2263 2245 sgarg
          throw new SAXException("The access object is null to write access " +
2264
                                 "sbutree");
2265
        }
2266
2267 2161 tao
        String sql = null;
2268
        PreparedStatement pstmt = null;
2269
        sql = "INSERT INTO xml_accesssubtree (docid, rev, controllevel, "
2270
                + "subtreeid, startnodeid, endnodeid) VALUES "
2271
                + " (?, ?, ?, ?, ?, ?)";
2272 2245 sgarg
        try
2273
        {
2274 2161 tao
2275
            pstmt = connection.prepareStatement(sql);
2276
            // Increase DBConnection usage count
2277
            connection.increaseUsageCount(1);
2278 2245 sgarg
            String level = accessSection.getControlLevel();
2279
            long startNodeId = -1;
2280
            if (level != null && level.equals(DATAACCESSLEVEL))
2281
            {
2282 5166 daigle
              // for additional access module the start node id should be
2283 2245 sgarg
              // descirbes element id
2284
              startNodeId = accessSection.getStartedDescribesNodeId();
2285
              // if in additional access, there is not describes element,
2286
              // in this senario, describesNodeId will be -1. Then we should
2287
              // the start access element id
2288
              if (startNodeId == -1)
2289
              {
2290
                startNodeId = accessSection.getStartNodeId();
2291
              }
2292
            }
2293
            else
2294
            {
2295
                startNodeId = accessSection.getStartNodeId();
2296
            }
2297
2298 2161 tao
            long endNodeId = accessSection.getEndNodeId();
2299
            String sectionId = accessSection.getSubTreeId();
2300 2245 sgarg
2301
            if (startNodeId ==-1 || endNodeId == -1)
2302
            {
2303
              throw new SAXException("Don't find start node or end node id " +
2304
                                      "for the access subtee");
2305
2306
            }
2307
2308 2161 tao
            // Bind the values to the query
2309
            pstmt.setString(1, docid);
2310 2663 sgarg
            logMetacat.info("Docid in access-subtreetable: " + docid);
2311 2608 tao
            pstmt.setInt(2, (new Integer(revision)).intValue());
2312 2663 sgarg
            logMetacat.info("rev in accesssubtreetable: " + revision);
2313 2161 tao
            pstmt.setString(3, level);
2314 2663 sgarg
            logMetacat.info("contorl level in access-subtree table: "
2315
                    + level);
2316 2161 tao
            pstmt.setString(4, sectionId);
2317 2663 sgarg
            logMetacat.info("Subtree id in access-subtree table: "
2318
                    + sectionId);
2319 2161 tao
            pstmt.setLong(5, startNodeId);
2320 2663 sgarg
            logMetacat.info("Start node id is: " + startNodeId);
2321 2161 tao
            pstmt.setLong(6, endNodeId);
2322 2663 sgarg
            logMetacat.info("End node id is: " + endNodeId);
2323 5208 daigle
            logMetacat.debug("Eml200SAXHandler.writeAccessSubTreeIntoDB - executing SQL: " + pstmt.toString());
2324 2161 tao
            pstmt.execute();
2325
            pstmt.close();
2326
        }//try
2327 2245 sgarg
        catch (SQLException e)
2328
        {
2329 2161 tao
            throw new SAXException("EMLSAXHandler.writeAccessSubTreeIntoDB(): "
2330
                    + e.getMessage());
2331
        }//catch
2332 2245 sgarg
        finally
2333
        {
2334
            try
2335
            {
2336 2161 tao
                pstmt.close();
2337 2245 sgarg
            }
2338
            catch (SQLException ee)
2339
            {
2340 2161 tao
                throw new SAXException(
2341
                        "EMLSAXHandler.writeAccessSubTreeIntoDB(): "
2342
                                + ee.getMessage());
2343
            }
2344
        }//finally
2345
2346
    }//writeAccessSubtreeIntoDB
2347
2348
    /* Delete every access subtree record from xml_accesssubtree. */
2349
    private void deleteAccessSubTreeRecord(String docId) throws SAXException
2350
    {
2351
        Statement stmt = null;
2352
        try {
2353
            // delete all acl records for resources related to @aclid if any
2354
            stmt = connection.createStatement();
2355
            // Increase DBConnection usage count
2356 4140 daigle
            connection.increaseUsageCount(1);
2357
            logMetacat.debug("running sql: DELETE FROM xml_accesssubtree WHERE docid = '"
2358
                    + docId + "'");
2359 2161 tao
            stmt.execute("DELETE FROM xml_accesssubtree WHERE docid = '"
2360
                    + docId + "'");
2361
2362
        } catch (SQLException e) {
2363
            throw new SAXException(e.getMessage());
2364
        } finally {
2365
            try {
2366
                stmt.close();
2367
            } catch (SQLException ee) {
2368
                throw new SAXException(ee.getMessage());
2369
            }
2370
        }
2371
    }//deleteAccessSubTreeRecord
2372
2373
    // open a file writer for writing inline data to file
2374 5752 leinfelder
    private Writer createInlineDataFileWriter(String fileName, String encoding)
2375 2161 tao
            throws SAXException
2376
    {
2377 5752 leinfelder
        Writer writer = null;
2378 4080 daigle
        String path;
2379
        try {
2380
        	 path = PropertyService.getProperty("application.inlinedatafilepath");
2381
        } catch (PropertyNotFoundException pnfe) {
2382
            throw new SAXException(pnfe.getMessage());
2383
        }
2384 2161 tao
        /*
2385
         * File inlineDataDirectory = new File(path);
2386
         */
2387
        String newFile = path + "/" + fileName;
2388 2663 sgarg
        logMetacat.info("inline file name: " + newFile);
2389 2161 tao
        try {
2390
            // true means append
2391 5752 leinfelder
        	writer = new OutputStreamWriter(new FileOutputStream(newFile, true), encoding);
2392 2161 tao
        } catch (IOException ioe) {
2393
            throw new SAXException(ioe.getMessage());
2394
        }
2395
        return writer;
2396
    }
2397
2398
    // write inline data into file system and return file name(without path)
2399 5752 leinfelder
    private void writeInlineDataIntoFile(Writer writer, StringBuffer data)
2400 2161 tao
            throws SAXException
2401
    {
2402
        try {
2403
            writer.write(data.toString());
2404
            writer.flush();
2405
        } catch (Exception e) {
2406
            throw new SAXException(e.getMessage());
2407
        }
2408
    }
2409
2410 2245 sgarg
2411
2412 2161 tao
    /*
2413
     * In eml2, the inline data wouldn't store in db, it store in file system
2414
     * The db stores file name(without path). We got the old file name from db
2415
     * and compare to the new in line data file
2416
     */
2417
    public boolean compareInlineDataFiles(String oldFileName, String newFileName)
2418
            throws McdbException
2419
    {
2420
        // this method need to be testing
2421
        boolean same = true;
2422
        String data = null;
2423
        try {
2424 4080 daigle
        	String path = PropertyService.getProperty("application.inlinedatafilepath");
2425
			// the new file name will look like path/docid.rev.2
2426
			File inlineDataDirectory = new File(path);
2427
			File oldDataFile = new File(inlineDataDirectory, oldFileName);
2428
			File newDataFile = new File(inlineDataDirectory, newFileName);
2429
2430 5752 leinfelder
            Reader oldFileReader = new InputStreamReader(new FileInputStream(oldDataFile), encoding);
2431 2161 tao
            BufferedReader oldStringReader = new BufferedReader(oldFileReader);
2432 5752 leinfelder
            Reader newFileReader = new InputStreamReader(new FileInputStream(newDataFile), encoding);
2433 2161 tao
            BufferedReader newStringReader = new BufferedReader(newFileReader);
2434
            // read first line of data
2435
            String oldString = oldStringReader.readLine();
2436
            String newString = newStringReader.readLine();
2437
2438
            // at the end oldstring will be null
2439
            while (oldString != null) {
2440
                oldString = oldStringReader.readLine();
2441
                newString = newStringReader.readLine();
2442
                if (!oldString.equals(newString)) {
2443
                    same = false;
2444
                    break;
2445
                }
2446
            }
2447
2448
            // if oldString is null but newString is not null, they are same
2449
            if (same) {
2450
                if (newString != null) {
2451
                    same = false;
2452
                }
2453
            }
2454
2455
        } catch (Exception e) {
2456
            throw new McdbException(e.getMessage());
2457
        }
2458 2663 sgarg
        logMetacat.info("the inline data retrieve from file: " + data);
2459 2161 tao
        return same;
2460
    }
2461
2462 2245 sgarg
   /*
2463 4080 daigle
	 * Copy a old line file to a new inline file
2464
	 */
2465
	public void copyInlineFile(String inlineDistributionId, String newFileName)
2466
			throws SAXException {
2467
		if (inlineDistributionId == null || newFileName == null) {
2468
			throw new SAXException("Could not copy inline file from old one to new "
2469
					+ "one!");
2470
		}
2471
		// get old file id from previousUnreadable data object
2472
		String oldInlineInternalFileName = (String) previousUnreadableInlineDataObjectHash
2473
				.get(inlineDistributionId);
2474 2278 sgarg
2475 4080 daigle
		if (oldInlineInternalFileName == null
2476
				|| oldInlineInternalFileName.trim().equals("")) {
2477
			throw new SAXException("Could not copy inline file from old one to new "
2478
					+ "one because can't find old file name");
2479
		}
2480
		logMetacat.info("in handle inline data");
2481
		logMetacat.info("the inline data file name from xml_access is: "
2482
				+ oldInlineInternalFileName);
2483 2245 sgarg
2484 5752 leinfelder
		InputStream oldFileReader = null;
2485
		OutputStream newFileWriter = null;
2486 4080 daigle
		try {
2487
			String path = PropertyService.getProperty("application.inlinedatafilepath");
2488
			// the new file name will look like path/docid.rev.2
2489
			File inlineDataDirectory = new File(path);
2490
			File oldDataFile = new File(inlineDataDirectory, oldInlineInternalFileName);
2491
			File newDataFile = new File(inlineDataDirectory, newFileName);
2492 2245 sgarg
2493 5752 leinfelder
			oldFileReader = new FileInputStream(oldDataFile);
2494
			newFileWriter = new FileOutputStream(newDataFile);
2495
			byte[] buf = new byte[4 * 1024]; // 4K buffer
2496 4080 daigle
			int b = oldFileReader.read(buf);
2497
			while (b != -1) {
2498
				newFileWriter.write(buf, 0, b);
2499
				b = oldFileReader.read(buf);
2500
			}
2501
		} catch (Exception e) {
2502
			throw new SAXException(e.getMessage());
2503
		} finally {
2504
			if (oldFileReader != null) {
2505
				try {
2506
					oldFileReader.close();
2507
				} catch (Exception ee) {
2508
					throw new SAXException(ee.getMessage());
2509
				}
2510 2245 sgarg
2511 4080 daigle
			}
2512
			if (newFileWriter != null) {
2513
				try {
2514
					newFileWriter.close();
2515
				} catch (Exception ee) {
2516
					throw new SAXException(ee.getMessage());
2517
				}
2518 2245 sgarg
2519 4080 daigle
			}
2520
		}
2521
	}
2522 2245 sgarg
2523
2524 2161 tao
    // if xml file failed to upload, we need to call this method to delete
2525
    // the inline data already in file system
2526 4080 daigle
    public void deleteInlineFiles() throws SAXException
2527 2161 tao
    {
2528
        if (!inlineFileIDList.isEmpty()) {
2529
            for (int i = 0; i < inlineFileIDList.size(); i++) {
2530
                String fileName = (String) inlineFileIDList.elementAt(i);
2531
                deleteInlineDataFile(fileName);
2532
            }
2533
        }
2534
    }
2535
2536
    /* delete the inline data file */
2537 4080 daigle
    private void deleteInlineDataFile(String fileName) throws SAXException
2538 2161 tao
    {
2539 4080 daigle
    	String path;
2540
    	try {
2541
    		path = PropertyService.getProperty("application.inlinedatafilepath");
2542
    	} catch (PropertyNotFoundException pnfe) {
2543
    		throw new SAXException ("Could not find inline data file path: "
2544
    				+ pnfe.getMessage());
2545
    	}
2546 2161 tao
        File inlineDataDirectory = new File(path);
2547
        File newFile = new File(inlineDataDirectory, fileName);
2548
        newFile.delete();
2549
2550
    }
2551
2552
    /*
2553 4080 daigle
	 * In eml2, the inline data wouldn't store in db, it store in file system
2554
	 * The db stores file name(without path).
2555
	 */
2556 5752 leinfelder
	public static Reader readInlineDataFromFileSystem(String fileName, String encoding)
2557 4080 daigle
			throws McdbException {
2558
		// BufferedReader stringReader = null;
2559 5752 leinfelder
		Reader fileReader = null;
2560 4080 daigle
		try {
2561
			String path = PropertyService.getProperty("application.inlinedatafilepath");
2562
			// the new file name will look like path/docid.rev.2
2563
			File inlineDataDirectory = new File(path);
2564
			File dataFile = new File(inlineDataDirectory, fileName);
2565 2161 tao
2566 5752 leinfelder
			fileReader = new InputStreamReader(new FileInputStream(dataFile), encoding);
2567 4080 daigle
			// stringReader = new BufferedReader(fileReader);
2568
		} catch (Exception e) {
2569
			throw new McdbException(e.getMessage());
2570
		}
2571
		// return stringReader;
2572
		return fileReader;
2573
	}
2574
2575 2161 tao
    /* Delete relations */
2576
    private void deleteRelations() throws SAXException
2577
    {
2578
        PreparedStatement pStmt = null;
2579
        String sql = "DELETE FROM xml_relation where docid =?";
2580
        try {
2581
            pStmt = connection.prepareStatement(sql);
2582
            //bind variable
2583
            pStmt.setString(1, docid);
2584
            //execute query
2585 5208 daigle
            logMetacat.debug("Eml200SAXHandler.deleteRelations - executing SQL: " + pStmt.toString());
2586 2161 tao
            pStmt.execute();
2587
            pStmt.close();
2588
        }//try
2589
        catch (SQLException e) {
2590
            throw new SAXException("EMLSAXHandler.deleteRelations(): "
2591
                    + e.getMessage());
2592
        }//catch
2593
        finally {
2594
            try {
2595
                pStmt.close();
2596
            }//try
2597
            catch (SQLException ee) {
2598
                throw new SAXException("EMLSAXHandler.deleteRelations: "
2599
                        + ee.getMessage());
2600
            }//catch
2601
        }//finally
2602
    }
2603
2604 2165 tao
    /* Write an online data file id into xml_relation table. The dataId shouldnot
2605
     * have the revision
2606
     */
2607 2161 tao
    private void writeOnlineDataFileIdIntoRelationTable(String dataId)
2608
            throws SAXException
2609
    {
2610
        PreparedStatement pStmt = null;
2611
        String sql = "INSERT into xml_relation (docid, packagetype, subject, "
2612
                + "relationship, object) values (?, ?, ?, ?, ?)";
2613
        try {
2614
            pStmt = connection.prepareStatement(sql);
2615
            //bind variable
2616
            pStmt.setString(1, docid);
2617 2397 tao
            pStmt.setString(2, doctype);
2618 2161 tao
            pStmt.setString(3, docid);
2619
            pStmt.setString(4, RELATION);
2620
            pStmt.setString(5, dataId);
2621
            //execute query
2622 5208 daigle
            logMetacat.debug("Eml200SAXHandler.writeOnlineDataFileIdIntoRelationTable - executing SQL: " + pStmt.toString());
2623 2161 tao
            pStmt.execute();
2624
            pStmt.close();
2625
        }//try
2626
        catch (SQLException e) {
2627
            throw new SAXException(
2628
                    "EMLSAXHandler.writeOnlineDataFileIdIntoRelationTable(): "
2629
                            + e.getMessage());
2630
        }//catch
2631
        finally {
2632
            try {
2633
                pStmt.close();
2634
            }//try
2635
            catch (SQLException ee) {
2636
                throw new SAXException(
2637
                        "EMLSAXHandler.writeOnlineDataFileIdIntoRelationTable(): "
2638
                                + ee.getMessage());
2639
            }//catch
2640
        }//finally
2641
2642
    }//writeOnlineDataFileIdIntoRelationTable
2643
2644 2165 tao
    /*
2645
     * This method will handle data file in online url. If the data file is in
2646 2245 sgarg
     * ecogrid protocol, then the datafile identifier(without rev) be returned.
2647
     * otherwise, null will be returned.
2648 2165 tao
     * If the data file doesn't exsit in xml_documents or
2649
     * xml_revision table, or the user has all permission to the data file if
2650 2245 sgarg
     * the docid already existed, the data file id (without rev)will be returned
2651 2165 tao
     * NEED to do:
2652
     * We should also need to implement http and ftp. Those
2653
     * external files should be download and assign a data file id to it.
2654
     */
2655 2245 sgarg
    private String handleOnlineUrlDataFile(String url) throws SAXException
2656 2165 tao
    {
2657 2663 sgarg
      logMetacat.warn("The url is "+ url);
2658 2245 sgarg
      String docid = null;
2659 2165 tao
      // if the url is not a ecogrid protocol, null will be getten
2660
      String accessionNumber =
2661 5025 daigle
    	  DocumentUtil.getAccessionNumberFromEcogridIdentifier(url);
2662 2165 tao
      if (accessionNumber != null)
2663
      {
2664
        // handle ecogrid protocol
2665
        // get rid of revision number to get the docid.
2666 5025 daigle
        docid = DocumentUtil.getDocIdFromAccessionNumber(accessionNumber);
2667 2165 tao
        onlineDataFileIdInRelationVector.add(docid);
2668
        try
2669
        {
2670
2671
          if (!AccessionNumber.accNumberUsed(docid))
2672
          {
2673 2245 sgarg
            return docid;
2674 2165 tao
          }
2675
          PermissionController controller = new
2676
              PermissionController(accessionNumber);
2677
          if (controller.hasPermission(
2678
              user, groups, AccessControlInterface.ALLSTRING))
2679
          {
2680 2245 sgarg
            return docid;
2681 2165 tao
          }
2682 2245 sgarg
          else
2683
          {
2684 4856 daigle
            throw new SAXException("User: " + user + " does not have permission to update " +
2685
                  "access rules for data file "+ docid);
2686 2245 sgarg
          }
2687 2165 tao
        }//try
2688
        catch(Exception e)
2689
        {
2690 2663 sgarg
          logMetacat.error("Error in " +
2691 2165 tao
                                "Eml200SAXHanlder.handleOnlineUrlDataFile is " +
2692 2663 sgarg
                                 e.getMessage());
2693 2165 tao
          throw new SAXException(e.getMessage());
2694
        }
2695
      }
2696 2245 sgarg
      return docid;
2697 2165 tao
    }
2698
2699 2245 sgarg
    private void compareElementNameSpaceAttributes(Stack unchangableNodeStack,
2700
            Hashtable nameSpaces, Attributes attributes, String localName,
2701
            String error) throws SAXException
2702
    {
2703
        //Get element subtree node stack (element node)
2704
        NodeRecord elementNode = null;
2705
        try {
2706
            elementNode = (NodeRecord) unchangableNodeStack.pop();
2707
        } catch (EmptyStackException ee) {
2708 2663 sgarg
            logMetacat.error("Node stack is empty for element data");
2709 2245 sgarg
            throw new SAXException(error);
2710
        }
2711 2663 sgarg
        logMetacat.info("current node type from xml is ELEMENT");
2712
        logMetacat.info("node type from stack: "
2713
                + elementNode.getNodeType());
2714
        logMetacat.info("node name from xml document: " + localName);
2715
        logMetacat.info("node name from stack: "
2716
                + elementNode.getNodeName());
2717
        logMetacat.info("node data from stack: "
2718
                + elementNode.getNodeData());
2719
        logMetacat.info("node id is: " + elementNode.getNodeId());
2720 2245 sgarg
        // if this node is not element or local name not equal or name space
2721
        // not
2722
        // equals, throw an exception
2723
        if (!elementNode.getNodeType().equals("ELEMENT")
2724
                || !localName.equals(elementNode.getNodeName()))
2725
        //  (uri != null && !uri.equals(elementNode.getNodePrefix())))
2726
        {
2727 2663 sgarg
            logMetacat.info("Inconsistence happend: ");
2728
            logMetacat.info("current node type from xml is ELEMENT");
2729
            logMetacat.info("node type from stack: "
2730
                    + elementNode.getNodeType());
2731
            logMetacat.info("node name from xml document: "
2732
                    + localName);
2733
            logMetacat.info("node name from stack: "
2734
                    + elementNode.getNodeName());
2735
            logMetacat.info("node data from stack: "
2736
                    + elementNode.getNodeData());
2737
            logMetacat.info("node id is: " + elementNode.getNodeId());
2738 2245 sgarg
            throw new SAXException(error);
2739
        }
2740
2741
        //compare namespace
2742
        Enumeration nameEn = nameSpaces.keys();
2743
        while (nameEn.hasMoreElements()) {
2744
            //Get namespacke node stack (element node)
2745
            NodeRecord nameNode = null;
2746
            try {
2747
                nameNode = (NodeRecord) unchangableNodeStack.pop();
2748
            } catch (EmptyStackException ee) {
2749 2663 sgarg
                logMetacat.error(
2750
                        "Node stack is empty for namespace data");
2751 2245 sgarg
                throw new SAXException(error);
2752
            }
2753
2754
            String prefixName = (String) nameEn.nextElement();
2755
            String nameSpaceUri = (String) nameSpaces.get(prefixName);
2756
            if (!nameNode.getNodeType().equals("NAMESPACE")
2757
                    || !prefixName.equals(nameNode.getNodeName())
2758
                    || !nameSpaceUri.equals(nameNode.getNodeData())) {
2759 2663 sgarg
                logMetacat.info("Inconsistence happend: ");
2760
                logMetacat.info(
2761
                        "current node type from xml is NAMESPACE");
2762
                logMetacat.info("node type from stack: "
2763
                        + nameNode.getNodeType());
2764
                logMetacat.info("current node name from xml is: "
2765
                        + prefixName);
2766
                logMetacat.info("node name from stack: "
2767
                        + nameNode.getNodeName());
2768
                logMetacat.info("current node data from xml is: "
2769
                        + nameSpaceUri);
2770
                logMetacat.info("node data from stack: "
2771
                        + nameNode.getNodeData());
2772
                logMetacat.info("node id is: " + nameNode.getNodeId());
2773 2245 sgarg
                throw new SAXException(error);
2774
            }
2775
2776
        }//while
2777
2778
        //compare attributes
2779
        for (int i = 0; i < attributes.getLength(); i++) {
2780
            NodeRecord attriNode = null;
2781
            try {
2782
                attriNode = (NodeRecord) unchangableNodeStack.pop();
2783
2784
            } catch (EmptyStackException ee) {
2785 2663 sgarg
                logMetacat.error(
2786
                        "Node stack is empty for attribute data");
2787 2245 sgarg
                throw new SAXException(error);
2788
            }
2789
            String attributeName = attributes.getQName(i);
2790
            String attributeValue = attributes.getValue(i);
2791 2663 sgarg
            logMetacat.info(
2792
                    "current node type from xml is ATTRIBUTE ");
2793
            logMetacat.info("node type from stack: "
2794
                    + attriNode.getNodeType());
2795
            logMetacat.info("current node name from xml is: "
2796
                    + attributeName);
2797
            logMetacat.info("node name from stack: "
2798
                    + attriNode.getNodeName());
2799
            logMetacat.info("current node data from xml is: "
2800
                    + attributeValue);
2801
            logMetacat.info("node data from stack: "
2802
                    + attriNode.getNodeData());
2803
            logMetacat.info("node id  is: " + attriNode.getNodeId());
2804 2245 sgarg
2805
            if (!attriNode.getNodeType().equals("ATTRIBUTE")
2806
                    || !attributeName.equals(attriNode.getNodeName())
2807
                    || !attributeValue.equals(attriNode.getNodeData())) {
2808 2663 sgarg
                logMetacat.info("Inconsistence happend: ");
2809
                logMetacat.info(
2810
                        "current node type from xml is ATTRIBUTE ");
2811
                logMetacat.info("node type from stack: "
2812
                        + attriNode.getNodeType());
2813
                logMetacat.info("current node name from xml is: "
2814
                        + attributeName);
2815
                logMetacat.info("node name from stack: "
2816
                        + attriNode.getNodeName());
2817
                logMetacat.info("current node data from xml is: "
2818
                        + attributeValue);
2819
                logMetacat.info("node data from stack: "
2820
                        + attriNode.getNodeData());
2821
                logMetacat.info("node is: " + attriNode.getNodeId());
2822 2245 sgarg
                throw new SAXException(error);
2823
            }
2824
        }//for
2825
2826
    }
2827
2828
    /* mehtod to compare current text node and node in db */
2829
    private void compareTextNode(Stack nodeStack, StringBuffer text,
2830
            String error) throws SAXException
2831
    {
2832
        NodeRecord node = null;
2833
        //get node from current stack
2834
        try {
2835
            node = (NodeRecord) nodeStack.pop();
2836
        } catch (EmptyStackException ee) {
2837 2663 sgarg
            logMetacat.error(
2838
                    "Node stack is empty for text data in startElement");
2839 2245 sgarg
            throw new SAXException(error);
2840
        }
2841 2663 sgarg
        logMetacat.info(
2842
                "current node type from xml is TEXT in start element");
2843
        logMetacat.info("node type from stack: " + node.getNodeType());
2844
        logMetacat.info("current node data from xml is: "
2845
                + text.toString());
2846
        logMetacat.info("node data from stack: " + node.getNodeData());
2847
        logMetacat.info("node name from stack: " + node.getNodeName());
2848
        logMetacat.info("node is: " + node.getNodeId());
2849 2245 sgarg
        if (!node.getNodeType().equals("TEXT")
2850
                || !(text.toString()).equals(node.getNodeData())) {
2851 2663 sgarg
            logMetacat.info("Inconsistence happend: ");
2852
            logMetacat.info(
2853
                    "current node type from xml is TEXT in start element");
2854
            logMetacat.info("node type from stack: "
2855
                    + node.getNodeType());
2856
            logMetacat.info("current node data from xml is: "
2857
                    + text.toString());
2858
            logMetacat.info("node data from stack: "
2859
                    + node.getNodeData());
2860
            logMetacat.info("node name from stack: "
2861
                    + node.getNodeName());
2862
            logMetacat.info("node is: " + node.getNodeId());
2863 2245 sgarg
            throw new SAXException(error);
2864
        }//if
2865
    }
2866
2867
    /* Comparet comment from xml and db */
2868
    private void compareCommentNode(Stack nodeStack, String string, String error)
2869
            throws SAXException
2870
    {
2871
        NodeRecord node = null;
2872
        try {
2873
            node = (NodeRecord) nodeStack.pop();
2874
        } catch (EmptyStackException ee) {
2875 2663 sgarg
            logMetacat.error("the stack is empty for comment data");
2876 2245 sgarg
            throw new SAXException(error);
2877
        }
2878 2663 sgarg
        logMetacat.info("current node type from xml is COMMENT");
2879
        logMetacat.info("node type from stack: " + node.getNodeType());
2880
        logMetacat.info("current node data from xml is: " + string);
2881
        logMetacat.info("node data from stack: " + node.getNodeData());
2882
        logMetacat.info("node is from stack: " + node.getNodeId());
2883 2245 sgarg
        // if not consistent terminate program and throw a exception
2884
        if (!node.getNodeType().equals("COMMENT")
2885
                || !string.equals(node.getNodeData())) {
2886 2663 sgarg
            logMetacat.info("Inconsistence happend: ");
2887
            logMetacat.info("current node type from xml is COMMENT");
2888
            logMetacat.info("node type from stack: "
2889
                    + node.getNodeType());
2890
            logMetacat.info(
2891
                    "current node data from xml is: " + string);
2892
            logMetacat.info("node data from stack: "
2893
                    + node.getNodeData());
2894
            logMetacat.info("node is from stack: " + node.getNodeId());
2895 2245 sgarg
            throw new SAXException(error);
2896
        }//if
2897
    }
2898
2899
    /* Compare whitespace from xml and db */
2900
   private void compareWhiteSpace(Stack nodeStack, String string, String error)
2901
           throws SAXException
2902
   {
2903
       NodeRecord node = null;
2904
       try {
2905
           node = (NodeRecord) nodeStack.pop();
2906
       } catch (EmptyStackException ee) {
2907 2663 sgarg
           logMetacat.error("the stack is empty for whitespace data");
2908 2245 sgarg
           throw new SAXException(error);
2909
       }
2910
       if (!node.getNodeType().equals("TEXT")
2911
               || !string.equals(node.getNodeData())) {
2912 2663 sgarg
           logMetacat.info("Inconsistence happend: ");
2913
           logMetacat.info(
2914
                   "current node type from xml is WHITESPACE TEXT");
2915
           logMetacat.info("node type from stack: "
2916
                   + node.getNodeType());
2917
           logMetacat.info(
2918
                   "current node data from xml is: " + string);
2919
           logMetacat.info("node data from stack: "
2920
                   + node.getNodeData());
2921
           logMetacat.info("node is from stack: " + node.getNodeId());
2922 2245 sgarg
           throw new SAXException(error);
2923
       }//if
2924
   }
2925
2926
2927
2928 2161 tao
}