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