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