Project

General

Profile

« Previous | Next » 

Revision 4678

Added by daigle over 15 years ago

Use a distributionSection object to hold a distribution and it's access.

View differences:

src/edu/ucsb/nceas/metacat/Eml210SAXHandler.java
55 55
 * A database aware Class implementing callback methods for the SAX parser to
56 56
 * call when processing the XML stream and generating events
57 57
 */
58
public class Eml210SAXHandler extends DBSAXHandler implements
59
        AccessControlInterface
60
{
58
public class Eml210SAXHandler extends DBSAXHandler implements AccessControlInterface {
61 59

  
62
    private boolean processTopLevelAccess = false;
60
	private boolean processTopLevelAccess = false;
63 61

  
64
    private boolean processAdditionalAccess = false;
62
	private boolean processAdditionalAccess = false;
65 63

  
66
    private boolean processOtherAccess = false;
64
	private boolean processOtherAccess = false;
67 65

  
68
    private AccessSection accessObject = null;
66
	private AccessSection accessObject = null;
69 67

  
70
    private AccessRule accessRule = null;
68
	private AccessRule accessRule = null;
71 69

  
72
    private Vector<AccessSection> accessObjectList = new Vector<AccessSection>(); // store every access rule
70
	private Vector<AccessSection> accessObjectList = new Vector<AccessSection>(); // store
71
																					// every
72
																					// access
73
																					// rule
73 74

  
74
    private Hashtable<String,AccessSection> topLevelAccessControlMap = new Hashtable<String,AccessSection>();
75
	private Hashtable<String, AccessSection> topLevelAccessControlMap = new Hashtable<String, AccessSection>();
75 76

  
76
    private Hashtable<String,AccessSection> additionalAccessControlMap = new Hashtable<String,AccessSection>();// store
77
	private Hashtable<String, AccessSection> additionalAccessControlMap = new Hashtable<String, AccessSection>();// store
77 78

  
78
    //subtree access for single additionalmetacat
79
    private Vector<Hashtable<String,AccessSection>> additionalAccessMapList = new Vector<Hashtable<String,AccessSection>>();// store maps for
79
	// subtree access for single additionalmetacat
80
	private Vector<Hashtable<String, AccessSection>> additionalAccessMapList = new Vector<Hashtable<String, AccessSection>>();// store
81
																																// maps
82
																																// for
80 83

  
81
    // every additionalmetadata
82
    private Vector<String> describesId = new Vector<String>(); // store the ids in
84
	// every additionalmetadata
85
	private Vector<String> describesId = new Vector<String>(); // store the ids
86
																// in
83 87

  
84
    //additionalmetadata/describes
85
    private Stack<SubTree> subTreeInfoStack = new Stack<SubTree>();
88
	// additionalmetadata/describes
89
	private Stack<SubTree> subTreeInfoStack = new Stack<SubTree>();
86 90

  
87
    private Vector<SubTree> subTreeList = new Vector<SubTree>();// store the final subtree
91
	private Vector<SubTree> subTreeList = new Vector<SubTree>();// store the
92
																// final subtree
88 93

  
89
    // MCD - Removed the following lines.  They are used for node level access control
90
    // which is not yet implemented in EML 2.1.0
91
	// private Hashtable<String,SubTree> unChangeableSubTreeHash = new Hashtable<String,SubTree>();
92
	// private Stack<NodeRecord> currentUnChangeableSubtreeNodeStack = new Stack<NodeRecord>();
94
	// MCD - Removed the following lines. They are used for node level access
95
	// control
96
	// which is not yet implemented in EML 2.1.0
97
	// private Hashtable<String,SubTree> unChangeableSubTreeHash = new
98
	// Hashtable<String,SubTree>();
99
	// private Stack<NodeRecord> currentUnChangeableSubtreeNodeStack = new
100
	// Stack<NodeRecord>();
93 101
	// private boolean startCriticalSubTree = false;
94
    // private boolean firstElementForCriticalSubTree = false;
95
    // private String firstElementNameForCriticalSubTree;
102
	// private boolean firstElementForCriticalSubTree = false;
103
	// private String firstElementNameForCriticalSubTree;
104
	
105
	private boolean needToCheckAccessModule = false;
96 106

  
97
    private boolean needToCheckAccessModule = false;
107
	private Vector<AccessSection> unChangeableAccessSubTreeVector = new Vector<AccessSection>();
98 108

  
99
    private Vector<AccessSection> unChangeableAccessSubTreeVector = new Vector<AccessSection>();
109
	private Stack<NodeRecord> currentUnchangeableAccessModuleNodeStack = new Stack<NodeRecord>();
100 110

  
101
    private Stack<NodeRecord> currentUnchangeableAccessModuleNodeStack = new Stack<NodeRecord>();
111
	private AccessSection topAccessSection;
102 112

  
103
    private AccessSection topAccessSection;
113
	// we need an another stack to store the access node which we pull out just
114
	// from xml. If a reference happened, we can use the stack the compare nodes
115
	private Stack<NodeRecord> storedAccessNodeStack = new Stack<NodeRecord>();
104 116

  
105
    // we need an another stack to store the access node which we pull out just
106
    // from xml. If a reference happened, we can use the stack the compare nodes
107
    private Stack<NodeRecord> storedAccessNodeStack = new Stack<NodeRecord>();
117
	// vector stored the data file id which will be write into relation table
118
	private Vector<String> onlineDataFileIdInRelationVector = new Vector<String>();
108 119

  
109
    // vector stored the data file id which will be write into relation table
110
    private Vector<String> onlineDataFileIdInRelationVector = new Vector<String>();
120
	// vector stored the data file id which will be write top access rules to
121
	// access table
122
	private Vector<String> onlineDataFileIdInTopAccessVector = new Vector<String>();
111 123

  
112
    // vector stored the data file id which will be write top access rules to
113
   // access table
114
    private Vector<String> onlineDataFileIdInTopAccessVector = new Vector<String>();
124
	// Indicator of inline data
125
	private boolean handleInlineData = false;
115 126

  
116
    // Indicator of inline data
117
    private boolean handleInlineData = false;
127
	private Hashtable<String, String> inlineDataNameSpace = null;
118 128

  
119
    private Hashtable<String,String> inlineDataNameSpace = null;
129
	private FileWriter inlineDataFileWriter = null;
120 130

  
121
    private FileWriter inlineDataFileWriter = null;
131
	private String inlineDataFileName = null;
122 132

  
123
    private String inlineDataFileName = null;
133
	DistributionSection currentDistributionSection = null;
124 134

  
125
    // This variable keeps a counter of each distribution element.  This index will
126
    // be used to name the inline data file that gets written to disk, and to strip
127
    // inline data from the metadata document on file if the user does not have read
128
    // access.
135
	Vector<DistributionSection> allDistributionSections = new Vector<DistributionSection>();
136

  
137
	// This variable keeps a counter of each distribution element. This index
138
	// will be used to name the inline data file that gets written to disk, and to
139
	// strip inline data from the metadata document on file if the user does not have
140
	// read access.
129 141
	private int distributionIndex = 0;
130 142

  
143
	// private String distributionOnlineFileName = null;
144

  
131 145
	// This is used to delete inline files if the xml does not parse correctly.
132
    private Vector<String> inlineFileIdList = new Vector<String>();
146
	private Vector<String> inlineFileIdList = new Vector<String>();
133 147

  
134
    // Constant
135
    private static final String EML = "eml";
136
    
137
    private static final String DISTRIBUTION = "distribution";
148
	// Constant
149
	private static final String EML = "eml";
138 150

  
139
    private static final String ORDER = "order";
151
	private static final String DISTRIBUTION = "distribution";
140 152

  
141
    private static final String ID = "id";
153
	private static final String ORDER = "order";
142 154

  
143
    private static final String REFERENCES = "references";
155
	private static final String ID = "id";
144 156

  
145
    public static final String INLINE = "inline";
157
	private static final String REFERENCES = "references";
146 158

  
147
    private static final String ONLINE = "online";
159
	public static final String INLINE = "inline";
148 160

  
149
    private static final String URL = "url";
161
	private static final String ONLINE = "online";
150 162

  
151
    // private static final String PERMISSIONERROR = "User tried to update a subtree "
152
    //        + "when they don't have write permission!";
163
	private static final String URL = "url";
153 164

  
154
    private static final String UPDATEACCESSERROR = "User tried to update an "
155
            + "access module when they don't have \"ALL\" permission!";
165
	// private static final String PERMISSIONERROR = "User tried to update a
166
	// subtree "
167
	// + "when they don't have write permission!";
156 168

  
157
    private static final String TOPLEVEL = "top";
169
	private static final String UPDATEACCESSERROR = "User tried to update an "
170
			+ "access module when they don't have \"ALL\" permission!";
158 171

  
159
    private static final String SUBTREELEVEL = "subtree";
172
	private static final String TOPLEVEL = "top";
160 173

  
161
    private static final String RELATION = "Provides info for";
174
	private static final String SUBTREELEVEL = "subtree";
162 175

  
163
    private Logger logMetacat = Logger.getLogger(Eml210SAXHandler.class);   	   	
176
	private static final String RELATION = "Provides info for";
164 177

  
165
    /**
166
     * Construct an instance of the handler class In this constructor, user can
167
     * specify the version need to update
168
     *
169
     * @param conn the JDBC connection to which information is written
170
     * @param action - "INSERT" or "UPDATE"
171
     * @param docid to be inserted or updated into JDBC connection
172
     * @param revision, the user specified the revision need to be update
173
     * @param user the user connected to MetaCat servlet and owns the document
174
     * @param groups the groups to which user belongs
175
     * @param pub flag for public "read" access on document
176
     * @param serverCode the serverid from xml_replication on which this
177
     *            document resides.
178
     *
179
     */
180
    public Eml210SAXHandler(DBConnection conn, String action, String docid,
181
            String revision, String user, String[] groups, String pub,
182
            int serverCode, String createDate, String updateDate) throws SAXException
183
    {
184
        super(conn, action, docid, revision, user, groups, pub, 
185
                serverCode, createDate, updateDate);
186
        // Get the unchangeable subtrees (user doesn't have write permission)
187
        try {
188
            PermissionController control = new PermissionController(docid
189
                    + PropertyService.getProperty("document.accNumSeparator") + revision);
190
            //unChangableSubTreeHash = getUnchangableSubTree(control, user,
191
            // groups);
178
	private Logger logMetacat = Logger.getLogger(Eml210SAXHandler.class);
192 179

  
193
            //If the action is update and user doesn't have "ALL" permission
194
            // we need to check if user can update access subtree
195
            if (action.equals("UPDATE")
196
                    && !control.hasPermission(user, groups,
197
                            AccessControlInterface.ALLSTRING)) {
198
                needToCheckAccessModule = true;
199
                unChangeableAccessSubTreeVector = getAccessSubTreeListFromDB();
200
            }
201
        } catch (Exception e) {
202
            throw new SAXException(e.getMessage());
203
        }
204
    }
180
	/**
181
	 * Construct an instance of the handler class In this constructor, user can
182
	 * specify the version need to update
183
	 * 
184
	 * @param conn
185
	 *            the JDBC connection to which information is written
186
	 * @param action -
187
	 *            "INSERT" or "UPDATE"
188
	 * @param docid
189
	 *            to be inserted or updated into JDBC connection
190
	 * @param revision,
191
	 *            the user specified the revision need to be update
192
	 * @param user
193
	 *            the user connected to MetaCat servlet and owns the document
194
	 * @param groups
195
	 *            the groups to which user belongs
196
	 * @param pub
197
	 *            flag for public "read" access on document
198
	 * @param serverCode
199
	 *            the serverid from xml_replication on which this document
200
	 *            resides.
201
	 * 
202
	 */
203
	public Eml210SAXHandler(DBConnection conn, String action, String docid,
204
			String revision, String user, String[] groups, String pub, int serverCode,
205
			String createDate, String updateDate) throws SAXException {
206
		super(conn, action, docid, revision, user, groups, pub, serverCode, createDate,
207
				updateDate);
208
		// Get the unchangeable subtrees (user doesn't have write permission)
209
		try {
210
			PermissionController control = new PermissionController(docid
211
					+ PropertyService.getProperty("document.accNumSeparator") + revision);
212
			// unChangableSubTreeHash = getUnchangableSubTree(control, user,
213
			// groups);
205 214

  
206
    // MCD - Removed the following method.  It is used for node level access control
207
    // which is not yet implemented in EML 2.1.0
208
    //    /* Pass a permission control and get the list of unchangable subtree */
209
    //    private Hashtable getUnchangableSubTree(PermissionController controller,
210
    //            String user, String[] groups) throws Exception
211
    //    {
212
    //        Hashtable list = null;
213
    //        Hashtable result = new Hashtable();
214
    //        // get unwritable sutree from controller
215
    //        list = null;
216
    //        // changed after old code removal
217
    //        //controller.hasUnaccessableSubTree(user, groups,
218
    //        //        AccessControlInterface.WRITESTRING);
219
    //        if (list != null) {
215
			// If the action is update and user doesn't have "ALL" permission
216
			// we need to check if user can update access subtree			
217
			if (!control.hasPermission(user, groups, AccessControlInterface.ALLSTRING)
218
					&& action != null && action.equals("UPDATE")) {
219
				needToCheckAccessModule = true;
220
				unChangeableAccessSubTreeVector = getAccessSubTreeListFromDB();
221
			}
222

  
223
		} catch (Exception e) {
224
			throw new SAXException(e.getMessage());
225
		}
226
	}
227

  
228
	// MCD - Removed the following method. It is used for node level access
229
	// control
230
	// which is not yet implemented in EML 2.1.0
231
	// /* Pass a permission control and get the list of unchangable subtree */
232
	// private Hashtable getUnchangableSubTree(PermissionController controller,
233
	// String user, String[] groups) throws Exception
234
	// {
235
	// Hashtable list = null;
236
	// Hashtable result = new Hashtable();
237
	// // get unwritable sutree from controller
238
	// list = null;
239
	// // changed after old code removal
240
	// //controller.hasUnaccessableSubTree(user, groups,
241
	// // AccessControlInterface.WRITESTRING);
242
	// if (list != null) {
220 243
	//
221
    //            Enumeration en = list.elements();
222
    //            while (en.hasMoreElements()) {
223
    //                // Get a subtree without node record list
224
    //                SubTree treeWithoutStack = (SubTree) en.nextElement();
225
    //                String subTreeId = treeWithoutStack.getSubTreeId();
226
    //                logMetacat.info(
227
    //                        "unchangable subtree id: " + subTreeId);
228
    //                long startNodeId = treeWithoutStack.getStartNodeId();
229
    //                logMetacat.info("unchangable subtree startnodeid: "
230
    //                        + startNodeId);
231
    //                long endNodeId = treeWithoutStack.getEndNodeId();
232
    //                logMetacat.info("unchangable subtree endnodeid: "
233
    //                        + endNodeId);
234
    //                // Get a subtree has the nodelist
235
    //                SubTree tree = new SubTree(docid, subTreeId, startNodeId,
236
    //                        endNodeId);
237
    //                // add this tree to the result
238
    //                result.put(subTreeId, tree);
239
    //
240
    //            }//while
241
    //
242
    //        }//if
243
    //
244
    //        return result;
245
    //    }
244
	// Enumeration en = list.elements();
245
	// while (en.hasMoreElements()) {
246
	// // Get a subtree without node record list
247
	// SubTree treeWithoutStack = (SubTree) en.nextElement();
248
	// String subTreeId = treeWithoutStack.getSubTreeId();
249
	// logMetacat.info(
250
	// "unchangable subtree id: " + subTreeId);
251
	// long startNodeId = treeWithoutStack.getStartNodeId();
252
	// logMetacat.info("unchangable subtree startnodeid: "
253
	// + startNodeId);
254
	// long endNodeId = treeWithoutStack.getEndNodeId();
255
	// logMetacat.info("unchangable subtree endnodeid: "
256
	// + endNodeId);
257
	// // Get a subtree has the nodelist
258
	// SubTree tree = new SubTree(docid, subTreeId, startNodeId,
259
	// endNodeId);
260
	// // add this tree to the result
261
	// result.put(subTreeId, tree);
262
	//
263
	// }//while
264
	//
265
	// }//if
266
	//
267
	// return result;
268
	// }
246 269

  
247
    /*
248
     * Get the subtree node info from xml_accesssubtree table
249
     */
250
    private Vector<AccessSection> getAccessSubTreeListFromDB() throws Exception
251
    {
252
        Vector<AccessSection> result = new Vector<AccessSection>();
253
        PreparedStatement pstmt = null;
254
        ResultSet rs = null;
255
        String sql = "SELECT controllevel, subtreeid, startnodeid, endnodeid "
256
                + "FROM xml_accesssubtree WHERE docid like ? "
257
                + "ORDER BY startnodeid ASC";
270
	/*
271
	 * Get the subtree node info from xml_accesssubtree table
272
	 */
273
	private Vector<AccessSection> getAccessSubTreeListFromDB() throws Exception {
274
		Vector<AccessSection> result = new Vector<AccessSection>();
275
		PreparedStatement pstmt = null;
276
		ResultSet rs = null;
277
		String sql = "SELECT controllevel, subtreeid, startnodeid, endnodeid "
278
				+ "FROM xml_accesssubtree WHERE docid like ? "
279
				+ "ORDER BY startnodeid ASC";
258 280

  
259
        try {
281
		try {
260 282

  
261
            pstmt = connection.prepareStatement(sql);
262
            // Increase DBConnection usage count
263
            connection.increaseUsageCount(1);
264
            // Bind the values to the query
265
            pstmt.setString(1, docid);
266
            pstmt.execute();
283
			pstmt = connection.prepareStatement(sql);
284
			// Increase DBConnection usage count
285
			connection.increaseUsageCount(1);
286
			// Bind the values to the query
287
			pstmt.setString(1, docid);
288
			pstmt.execute();
267 289

  
268
            // Get result set
269
            rs = pstmt.getResultSet();
270
            while (rs.next()) {
271
                String level = rs.getString(1);
272
                String sectionId = rs.getString(2);
273
                long startNodeId = rs.getLong(3);
274
                long endNodeId = rs.getLong(4);
275
                // create a new access section
276
                AccessSection accessObj = new AccessSection();
277
                accessObj.setControlLevel(level);
278
                accessObj.setDocId(docid);
279
                accessObj.setSubTreeId(sectionId);
280
                accessObj.setStartNodeId(startNodeId);
281
                accessObj.setEndNodeId(endNodeId);
282
                Stack<NodeRecord> nodeStack = accessObj.getSubTreeNodeStack();
283
                accessObj.setSubTreeNodeStack(nodeStack);
284
                // add this access obj into vector
285
                result.add(accessObj);
286
                // Get the top level access subtree control
287
                if (level != null && level.equals(TOPLEVEL)) {
288
                    topAccessSection = accessObj;
289
                }
290
            }
291
            pstmt.close();
292
        }//try
293
        catch (SQLException e) {
294
            throw new SAXException(
295
                    "EMLSAXHandler.getAccessSubTreeListFromDB(): "
296
                            + e.getMessage());
297
        }//catch
298
        finally {
299
            try {
300
                pstmt.close();
301
            } catch (SQLException ee) {
302
                throw new SAXException(
303
                        "EMLSAXHandler.getAccessSubTreeListFromDB(): "
304
                                + ee.getMessage());
305
            }
306
        }//finally
307
        return result;
308
    }
290
			// Get result set
291
			rs = pstmt.getResultSet();
292
			while (rs.next()) {
293
				String level = rs.getString(1);
294
				String sectionId = rs.getString(2);
295
				long startNodeId = rs.getLong(3);
296
				long endNodeId = rs.getLong(4);
297
				// create a new access section
298
				AccessSection accessObj = new AccessSection();
299
				accessObj.setControlLevel(level);
300
				accessObj.setDocId(docid);
301
				accessObj.setSubTreeId(sectionId);
302
				accessObj.setStartNodeId(startNodeId);
303
				accessObj.setEndNodeId(endNodeId);
304
				Stack<NodeRecord> nodeStack = accessObj.getSubTreeNodeStack();
305
				accessObj.setSubTreeNodeStack(nodeStack);
306
				// add this access obj into vector
307
				result.add(accessObj);
308
				// Get the top level access subtree control
309
				if (level != null && level.equals(TOPLEVEL)) {
310
					topAccessSection = accessObj;
311
				}
312
			}
313
			pstmt.close();
314
		}// try
315
		catch (SQLException e) {
316
			throw new SAXException("EMLSAXHandler.getAccessSubTreeListFromDB(): "
317
					+ e.getMessage());
318
		}// catch
319
		finally {
320
			try {
321
				pstmt.close();
322
			} catch (SQLException ee) {
323
				throw new SAXException("EMLSAXHandler.getAccessSubTreeListFromDB(): "
324
						+ ee.getMessage());
325
			}
326
		}// finally
327
		return result;
328
	}
309 329

  
310
    /** SAX Handler that is called at the start of each XML element */
311
    public void startElement(String uri, String localName, String qName,
312
            Attributes atts) throws SAXException
313
    {
314
        // for element <eml:eml...> qname is "eml:eml", local name is "eml"
315
        // for element <acl....> both qname and local name is "eml"
316
        // uri is namesapce
317
        logMetacat.debug("Start ELEMENT(qName) " + qName);
318
        logMetacat.debug("Start ELEMENT(localName) " + localName);
319
        logMetacat.debug("Start ELEMENT(uri) " + uri);
330
	/** SAX Handler that is called at the start of each XML element */
331
	public void startElement(String uri, String localName, String qName, Attributes atts)
332
			throws SAXException {
333
		// for element <eml:eml...> qname is "eml:eml", local name is "eml"
334
		// for element <acl....> both qname and local name is "eml"
335
		// uri is namesapce
336
		logMetacat.debug("Start ELEMENT(qName) " + qName);
337
		logMetacat.debug("Start ELEMENT(localName) " + localName);
338
		logMetacat.debug("Start ELEMENT(uri) " + uri);
320 339

  
321
        DBSAXNode parentNode = null;
322
        DBSAXNode currentNode = null;
340
		DBSAXNode parentNode = null;
341
		DBSAXNode currentNode = null;
323 342

  
324
        if (!handleInlineData) {
325
            // Get a reference to the parent node for the id
326
            try {
327
                parentNode = (DBSAXNode) nodeStack.peek();
328
            } catch (EmptyStackException e) {
329
                parentNode = null;
330
            }
343
		if (!handleInlineData) {
344
			// Get a reference to the parent node for the id
345
			try {
346
				parentNode = (DBSAXNode) nodeStack.peek();
347
			} catch (EmptyStackException e) {
348
				parentNode = null;
349
			}
331 350

  
332
            //start handle inline data
333
            if (localName.equals(INLINE)) {
334
                handleInlineData = true;
335
                //initialize namespace hash for in line data
336
                inlineDataNameSpace = new Hashtable<String,String>();
337
                //initialize file writer
338
                String docidWithoutRev = MetaCatUtil.getDocIdFromString(docid);
339
                String seperator = ".";
340
                try {
341
                seperator = PropertyService.getProperty("document.accNumSeparator");
342
                } catch (PropertyNotFoundException pnfe) {
343
                	logMetacat.error("Could not fing property 'accNumSeparator'. " 
344
                			+ "Setting separator to '.': " + pnfe.getMessage());
345
                }
346
                // the new file name will look like docid.rev.2
347
                inlineDataFileName = docidWithoutRev + seperator + revision + seperator
351
			// start handle inline data
352
			if (localName.equals(INLINE)) {
353
				handleInlineData = true;
354
				// initialize namespace hash for in line data
355
				inlineDataNameSpace = new Hashtable<String, String>();
356
				// initialize file writer
357
				String docidWithoutRev = MetaCatUtil.getDocIdFromString(docid);
358
				String seperator = ".";
359
				try {
360
					seperator = PropertyService.getProperty("document.accNumSeparator");
361
				} catch (PropertyNotFoundException pnfe) {
362
					logMetacat.error("Could not fing property 'accNumSeparator'. "
363
							+ "Setting separator to '.': " + pnfe.getMessage());
364
				}
365
				// the new file name will look like docid.rev.2
366
				inlineDataFileName = docidWithoutRev + seperator + revision + seperator
348 367
						+ distributionIndex;
349
                inlineDataFileWriter = createInlineDataFileWriter(inlineDataFileName);
350
                // put the inline file id into a vector. If upload failed,
351
                // metacat will delete the inline data file
352
                inlineFileIdList.add(inlineDataFileName);
368
				inlineDataFileWriter = createInlineDataFileWriter(inlineDataFileName);
369
				// put the inline file id into a vector. If upload failed,
370
				// metacat will delete the inline data file
371
				inlineFileIdList.add(inlineDataFileName);
372
				
373
				currentDistributionSection.setDistributionType(DistributionSection.INLINE_DATA_DISTRIBUTION);
374
				currentDistributionSection.setDataFileName(inlineDataFileName);
353 375

  
354
            }
376
			}
355 377

  
356
            // If hit a text node, we need write this text for current's parent
357
            // node This will happen if the element is mixed
358
            if (hitTextNode && parentNode != null) {
359
                // MCD - Removed the following method.  It is used for node level access control
360
                // which is not yet implemented in EML 2.1.0
361
                // //compare text node data for unchangeablesubtree
362
            	// if (startCriticalSubTree) {
363
            	//     compareTextNode(currentUnChangeableSubtreeNodeStack,
364
            	//             textBuffer, PERMISSIONERROR);
365
            	// }//if
378
			// If hit a text node, we need write this text for current's parent
379
			// node This will happen if the element is mixed
380
			if (hitTextNode && parentNode != null) {
381
				// MCD - Removed the following method. It is used for node level
382
				// access control
383
				// which is not yet implemented in EML 2.1.0
384
				// //compare text node data for unchangeablesubtree
385
				// if (startCriticalSubTree) {
386
				// compareTextNode(currentUnChangeableSubtreeNodeStack,
387
				// textBuffer, PERMISSIONERROR);
388
				// }//if
366 389

  
367
                //compare top level access module
368
                if (processTopLevelAccess && needToCheckAccessModule) {
369
                    compareTextNode(currentUnchangeableAccessModuleNodeStack,
370
                            textBuffer, UPDATEACCESSERROR);
371
                }
390
				// compare top level access module
391
				if (processTopLevelAccess && needToCheckAccessModule) {
392
					compareTextNode(currentUnchangeableAccessModuleNodeStack, textBuffer,
393
							UPDATEACCESSERROR);
394
				}
372 395

  
373
                if (needToCheckAccessModule
374
                        && (processAdditionalAccess || processOtherAccess || processTopLevelAccess)) {
375
                    // stored the pull out nodes into storedNode stack
376
                    NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "TEXT",
377
                            null, null, MetaCatUtil.normalize(textBuffer
378
                                    .toString()));
379
                    storedAccessNodeStack.push(nodeElement);
396
				if (needToCheckAccessModule
397
						&& (processAdditionalAccess || processOtherAccess || processTopLevelAccess)) {
398
					// stored the pull out nodes into storedNode stack
399
					NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "TEXT", null,
400
							null, MetaCatUtil.normalize(textBuffer.toString()));
401
					storedAccessNodeStack.push(nodeElement);
380 402

  
381
                }
403
				}
382 404

  
383
                // write the textbuffer into db for parent node.
384
                endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer,
385
                        parentNode);
386
                // rest hitTextNode
387
                hitTextNode = false;
388
                // reset textbuffer
389
                textBuffer = null;
390
                textBuffer = new StringBuffer();
405
				// write the textbuffer into db for parent node.
406
				endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer, parentNode);
407
				// rest hitTextNode
408
				hitTextNode = false;
409
				// reset textbuffer
410
				textBuffer = null;
411
				textBuffer = new StringBuffer();
391 412

  
392
            }
413
			}
393 414

  
394
            // Document representation that points to the root document node
395
            if (atFirstElement) {
396
                atFirstElement = false;
397
                // If no DOCTYPE declaration: docname = root element
398
                // doctype = root element name or name space
399
                if (docname == null) {
400
                    docname = localName;
401
                    // if uri isn't null doctype = uri(namespace)
402
                    // othewise root element
403
                    if (uri != null && !(uri.trim()).equals("")) {
404
                        doctype = uri;
405
                    } else {
406
                        doctype = docname;
407
                    }
408
                    logMetacat.debug("DOCNAME-a: " + docname);
409
                    logMetacat.debug("DOCTYPE-a: " + doctype);
410
                } else if (doctype == null) {
411
                    // because docname is not null and it is declared in dtd
412
                    // so could not be in schema, no namespace
413
                    doctype = docname;
414
                    logMetacat.debug("DOCTYPE-b: " + doctype);
415
                }
416
                rootNode.writeNodename(docname);
417
                try {
418
                    // for validated XML Documents store a reference to XML DB
419
                    // Catalog. Because this is select statement and it needn't 
420
                	// roll back if insert document action failed. In order to 
421
                	// decrease DBConnection usage count, we get a new
422
                    // dbconnection from pool String catalogid = null;
423
                    DBConnection dbConn = null;
424
                    int serialNumber = -1;
415
			// Document representation that points to the root document node
416
			if (atFirstElement) {
417
				atFirstElement = false;
418
				// If no DOCTYPE declaration: docname = root element
419
				// doctype = root element name or name space
420
				if (docname == null) {
421
					docname = localName;
422
					// if uri isn't null doctype = uri(namespace)
423
					// othewise root element
424
					if (uri != null && !(uri.trim()).equals("")) {
425
						doctype = uri;
426
					} else {
427
						doctype = docname;
428
					}
429
					logMetacat.debug("DOCNAME-a: " + docname);
430
					logMetacat.debug("DOCTYPE-a: " + doctype);
431
				} else if (doctype == null) {
432
					// because docname is not null and it is declared in dtd
433
					// so could not be in schema, no namespace
434
					doctype = docname;
435
					logMetacat.debug("DOCTYPE-b: " + doctype);
436
				}
437
				rootNode.writeNodename(docname);
438
				try {
439
					// for validated XML Documents store a reference to XML DB
440
					// Catalog. Because this is select statement and it needn't
441
					// roll back if insert document action failed. In order to
442
					// decrease DBConnection usage count, we get a new
443
					// dbconnection from pool String catalogid = null;
444
					DBConnection dbConn = null;
445
					int serialNumber = -1;
425 446

  
426
                    try {
427
                        // Get dbconnection
428
                        dbConn = DBConnectionPool
429
                                .getDBConnection("DBSAXHandler.startElement");
430
                        serialNumber = dbConn.getCheckOutSerialNumber();
447
					try {
448
						// Get dbconnection
449
						dbConn = DBConnectionPool
450
								.getDBConnection("DBSAXHandler.startElement");
451
						serialNumber = dbConn.getCheckOutSerialNumber();
431 452

  
432
                        Statement stmt = dbConn.createStatement();
433
                        ResultSet rs = stmt
434
                                .executeQuery("SELECT catalog_id FROM xml_catalog "
435
                                        + "WHERE entry_type = 'Schema' "
436
                                        + "AND public_id = '" + doctype + "'");
437
                        boolean hasRow = rs.next();
438
                        if (hasRow) {
439
                            catalogid = rs.getString(1);
440
                        }
441
                        stmt.close();
442
                    }//try
443
                    finally {
444
                        // Return dbconnection
445
                        DBConnectionPool.returnDBConnection(dbConn,
446
                                serialNumber);
447
                    }//finally
453
						Statement stmt = dbConn.createStatement();
454
						ResultSet rs = stmt
455
								.executeQuery("SELECT catalog_id FROM xml_catalog "
456
										+ "WHERE entry_type = 'Schema' "
457
										+ "AND public_id = '" + doctype + "'");
458
						boolean hasRow = rs.next();
459
						if (hasRow) {
460
							catalogid = rs.getString(1);
461
						}
462
						stmt.close();
463
					}// try
464
					finally {
465
						// Return dbconnection
466
						DBConnectionPool.returnDBConnection(dbConn, serialNumber);
467
					}// finally
448 468

  
449
                    //create documentImpl object by the constructor which can
450
                    // specify the revision
451
                    if (!super.getIsRevisionDoc())
452
                    {
453
                       currentDocument = new DocumentImpl(connection, rootNode
454
                            .getNodeID(), docname, doctype, docid, revision,
455
                            action, user, this.pub, catalogid, this.serverCode, 
456
                            createDate, updateDate);
457
                    }
458
                   
459
                } catch (Exception ane) {
460
                    throw (new SAXException(
461
                            "Error in EMLSaxHandler.startElement " + action,
462
                            ane));
463
                }
464
            }
469
					// create documentImpl object by the constructor which can
470
					// specify the revision
471
					if (!super.getIsRevisionDoc()) {
472
						currentDocument = new DocumentImpl(connection, rootNode
473
								.getNodeID(), docname, doctype, docid, revision, action,
474
								user, this.pub, catalogid, this.serverCode, createDate,
475
								updateDate);
476
					}
465 477

  
466
            // Create the current node representation
467
            currentNode = new DBSAXNode(connection, qName, localName,
468
                    parentNode, rootNode.getNodeID(), docid, doctype);
469
            // Use a local variable to store the element node id
470
            // If this element is a start point of subtree(section), it will be
471
            // stored otherwise, it will be discarded
472
            long startNodeId = currentNode.getNodeID();
473
            // Add all of the namespaces
474
            String prefix = null;
475
            String nsuri = null;
476
            Enumeration<String> prefixes = namespaces.keys();
477
            while (prefixes.hasMoreElements()) {
478
                prefix = prefixes.nextElement();
479
                nsuri = namespaces.get(prefix);
480
                endNodeId = currentNode.setNamespace(prefix, nsuri, docid);
481
            }
478
				} catch (Exception ane) {
479
					throw (new SAXException("Error in EMLSaxHandler.startElement "
480
							+ action, ane));
481
				}
482
			}
482 483

  
483
            // Add all of the attributes
484
            for (int i = 0; i < atts.getLength(); i++) {
485
                String attributeName = atts.getQName(i);
486
                String attributeValue = atts.getValue(i);
487
                endNodeId = currentNode.setAttribute(attributeName,
488
                        attributeValue, docid);
484
			// Create the current node representation
485
			currentNode = new DBSAXNode(connection, qName, localName, parentNode,
486
					rootNode.getNodeID(), docid, doctype);
487
			// Use a local variable to store the element node id
488
			// If this element is a start point of subtree(section), it will be
489
			// stored otherwise, it will be discarded
490
			long startNodeId = currentNode.getNodeID();
491
			// Add all of the namespaces
492
			String prefix = null;
493
			String nsuri = null;
494
			Enumeration<String> prefixes = namespaces.keys();
495
			while (prefixes.hasMoreElements()) {
496
				prefix = prefixes.nextElement();
497
				nsuri = namespaces.get(prefix);
498
				endNodeId = currentNode.setNamespace(prefix, nsuri, docid);
499
			}
489 500

  
490
                // To handle name space and schema location if the attribute
491
                // name is xsi:schemaLocation. If the name space is in not 
492
                // in catalog table it will be registered.
493
                if (attributeName != null
494
                        && attributeName
495
                                .indexOf(MetaCatServlet.SCHEMALOCATIONKEYWORD) != -1) {
496
                    SchemaLocationResolver resolver = new SchemaLocationResolver(
497
                            attributeValue);
498
                    resolver.resolveNameSpace();
501
			// Add all of the attributes
502
			for (int i = 0; i < atts.getLength(); i++) {
503
				String attributeName = atts.getQName(i);
504
				String attributeValue = atts.getValue(i);
505
				endNodeId = currentNode
506
						.setAttribute(attributeName, attributeValue, docid);
499 507

  
500
                } else if (attributeName != null && attributeName.equals(ID)) {
501
                    // MCD - Removed the following code.  It is used for node level access 
502
                	// control which is not yet implemented in EML 2.1.0
503
                    // // check unchangeable subtree hash if contains this
504
                	// // subtree id
505
                	// if (unChangeableSubTreeHash.containsKey(attributeValue)) {
506
                	//     // this subtree couldn't be changed by the user and
507
                	//     // move it from hash
508
                	//     SubTree currentUnChangedableSubtree = unChangeableSubTreeHash
509
                	//             .remove(attributeValue);
510
                	//     currentUnChangeableSubtreeNodeStack = currentUnChangedableSubtree
511
                	//             .getSubTreeNodeStack();
512
                	//     startCriticalSubTree = true;
513
                	//     firstElementForCriticalSubTree = true;
514
                	// }
515
                }
516
            }//for
508
				// To handle name space and schema location if the attribute
509
				// name is xsi:schemaLocation. If the name space is in not
510
				// in catalog table it will be registered.
511
				if (attributeName != null
512
						&& attributeName.indexOf(MetaCatServlet.SCHEMALOCATIONKEYWORD) != -1) {
513
					SchemaLocationResolver resolver = new SchemaLocationResolver(
514
							attributeValue);
515
					resolver.resolveNameSpace();
517 516

  
518
            // handle access stuff
519
            if (localName.equals(ACCESS)) {
520
            	if (parentNode.getTagName().equals(EML)) {
517
				} else if (attributeName != null && attributeName.equals(ID)) {
518
					// MCD - Removed the following code. It is used for node
519
					// level access
520
					// control which is not yet implemented in EML 2.1.0
521
					// // check unchangeable subtree hash if contains this
522
					// // subtree id
523
					// if (unChangeableSubTreeHash.containsKey(attributeValue))
524
					// {
525
					// // this subtree couldn't be changed by the user and
526
					// // move it from hash
527
					// SubTree currentUnChangedableSubtree =
528
					// unChangeableSubTreeHash
529
					// .remove(attributeValue);
530
					// currentUnChangeableSubtreeNodeStack =
531
					// currentUnChangedableSubtree
532
					// .getSubTreeNodeStack();
533
					// startCriticalSubTree = true;
534
					// firstElementForCriticalSubTree = true;
535
					// }
536
				}
537
			}// for
538

  
539
			// handle access stuff
540
			if (localName.equals(ACCESS)) {
541
				if (parentNode.getTagName().equals(EML)) {
521 542
					processTopLevelAccess = true;
522 543
				} else if (parentNode.getTagName() == DISTRIBUTION) {
523 544
					processAdditionalAccess = true;
......
526 547
					// module
527 548
					processOtherAccess = true;
528 549
				}
529
                // create access object
530
                accessObject = new AccessSection();
531
                // set permission order
532
                String permOrder = currentNode.getAttribute(ORDER);
533
                accessObject.setPermissionOrder(permOrder);
534
                // set access id
535
                String accessId = currentNode.getAttribute(ID);
536
                accessObject.setSubTreeId(accessId);
537
                accessObject.setStartNodeId(startNodeId);
538
                accessObject.setDocId(docid);
539
                if (processAdditionalAccess) {
540
                	accessObject.setInlineDataFileName(inlineDataFileName);
541
                }
550
				// create access object
551
				accessObject = new AccessSection();
552
				// set permission order
553
				String permOrder = currentNode.getAttribute(ORDER);
554
				accessObject.setPermissionOrder(permOrder);
555
				// set access id
556
				String accessId = currentNode.getAttribute(ID);
557
				accessObject.setSubTreeId(accessId);
558
				accessObject.setStartNodeId(startNodeId);
559
				accessObject.setDocId(docid);
560
				if (processAdditionalAccess) {
561
					accessObject.setDataFileName(inlineDataFileName);
562
				}
542 563

  
543
                // load top level node stack to
544
                // currentUnchangableAccessModuleNodeStack
545
                if (processTopLevelAccess && needToCheckAccessModule) {
546
                    // get the node stack for
547
                    currentUnchangeableAccessModuleNodeStack = topAccessSection
548
                            .getSubTreeNodeStack();
549
                }
550
            }
551
            else if (localName.equals(DISTRIBUTION)) {
552
            	distributionIndex++;    
553
            	
554
              // handle subtree info
555
              SubTree subTree = new SubTree();
556
              // set sub tree id
557
              subTree.setSubTreeId(String.valueOf(distributionIndex));
558
              // set sub tree start element name
559
              subTree.setStartElementName(currentNode.getTagName());
560
              // set start node number
561
              subTree.setStartNodeId(startNodeId);
562
              // add to stack, but it didn't get end node id yet
563
              subTreeInfoStack.push(subTree);
564
            }
565
            // Set up a access rule for allow
566
            else if (parentNode.getTagName() != null
567
                    && (parentNode.getTagName()).equals(ACCESS)
568
                    && localName.equals(ALLOW)) {
564
				// load top level node stack to
565
				// currentUnchangableAccessModuleNodeStack
566
				if (processTopLevelAccess && needToCheckAccessModule) {
567
					// get the node stack for
568
					currentUnchangeableAccessModuleNodeStack = topAccessSection
569
							.getSubTreeNodeStack();
570
				}
571
			} else if (localName.equals(DISTRIBUTION)) {
572
				distributionIndex++;
573
				currentDistributionSection = new DistributionSection(distributionIndex);
569 574

  
570
                accessRule = new AccessRule();
575
				// handle subtree info
576
				SubTree subTree = new SubTree();
577
				// set sub tree id
578
				subTree.setSubTreeId(String.valueOf(distributionIndex));
579
				// set sub tree start element name
580
				subTree.setStartElementName(currentNode.getTagName());
581
				// set start node number
582
				subTree.setStartNodeId(startNodeId);
583
				// add to stack, but it didn't get end node id yet
584
				subTreeInfoStack.push(subTree);
585
			}
586
			// Set up a access rule for allow
587
			else if (parentNode.getTagName() != null
588
					&& (parentNode.getTagName()).equals(ACCESS)
589
					&& localName.equals(ALLOW)) {
571 590

  
572
                //set permission type "allow"
573
                accessRule.setPermissionType(ALLOW);
591
				accessRule = new AccessRule();
574 592

  
575
            }
576
            // set up an access rule for deny
577
            else if (parentNode.getTagName() != null
578
                    && (parentNode.getTagName()).equals(ACCESS)
579
                    && localName.equals(DENY)) {
580
                accessRule = new AccessRule();
581
                //set permission type "allow"
582
                accessRule.setPermissionType(DENY);
583
            }
593
				// set permission type "allow"
594
				accessRule.setPermissionType(ALLOW);
584 595

  
585
            // Add the node to the stack, so that any text data can be
586
            // added as it is encountered
587
            nodeStack.push(currentNode);
588
            // Add the node to the vector used by thread for writing XML Index
589
            nodeIndex.addElement(currentNode);
590
            
591
            // MCD - Removed the following code.  It is used for node level access 
592
        	// control which is not yet implemented in EML 2.1.0
593
            // // handle critical subtree
594
            // if (startCriticalSubTree && firstElementForCriticalSubTree) {
595
            //     //store the element name
596
            //     firstElementNameForCriticalSubTree = qName;
597
            //     firstElementForCriticalSubTree = false;
598
            // }//for first element
599
            //
600
            // // handle critical subtree
601
            // if (startCriticalSubTree) {
602
            //     compareElementNameSpaceAttributes(
603
            //             currentUnChangeableSubtreeNodeStack, namespaces, atts,
604
            //             localName, PERMISSIONERROR);
605
            // 
606
            // }
607
            
608
            //compare top access level module
609
            if (processTopLevelAccess && needToCheckAccessModule) {
610
                compareElementNameSpaceAttributes(
611
                        currentUnchangeableAccessModuleNodeStack, namespaces,
612
                        atts, localName, UPDATEACCESSERROR);
596
			}
597
			// set up an access rule for deny
598
			else if (parentNode.getTagName() != null
599
					&& (parentNode.getTagName()).equals(ACCESS) && localName.equals(DENY)) {
600
				accessRule = new AccessRule();
601
				// set permission type "allow"
602
				accessRule.setPermissionType(DENY);
603
			}
613 604

  
614
            }
605
			// Add the node to the stack, so that any text data can be
606
			// added as it is encountered
607
			nodeStack.push(currentNode);
608
			// Add the node to the vector used by thread for writing XML Index
609
			nodeIndex.addElement(currentNode);
615 610

  
616
            // store access module element and attributes into stored stack
617
            if (needToCheckAccessModule
618
                    && (processAdditionalAccess || processOtherAccess || processTopLevelAccess)) {
619
                // stored the pull out nodes into storedNode stack
620
                NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "ELEMENT",
621
                        localName, prefix, MetaCatUtil.normalize(null));
622
                storedAccessNodeStack.push(nodeElement);
623
                for (int i = 0; i < atts.getLength(); i++) {
624
                    String attributeName = atts.getQName(i);
625
                    String attributeValue = atts.getValue(i);
626
                    NodeRecord nodeAttribute = new NodeRecord(-2, -2, -2,
627
                            "ATTRIBUTE", attributeName, null, MetaCatUtil
628
                                    .normalize(attributeValue));
629
                    storedAccessNodeStack.push(nodeAttribute);
630
                }
611
			// MCD - Removed the following code. It is used for node level
612
			// access
613
			// control which is not yet implemented in EML 2.1.0
614
			// // handle critical subtree
615
			// if (startCriticalSubTree && firstElementForCriticalSubTree) {
616
			// //store the element name
617
			// firstElementNameForCriticalSubTree = qName;
618
			// firstElementForCriticalSubTree = false;
619
			// }//for first element
620
			//
621
			// // handle critical subtree
622
			// if (startCriticalSubTree) {
623
			// compareElementNameSpaceAttributes(
624
			// currentUnChangeableSubtreeNodeStack, namespaces, atts,
625
			// localName, PERMISSIONERROR);
626
			// 
627
			// }
631 628

  
632
            }
629
			// compare top access level module
630
			if (processTopLevelAccess && needToCheckAccessModule) {
631
				compareElementNameSpaceAttributes(
632
						currentUnchangeableAccessModuleNodeStack, namespaces, atts,
633
						localName, UPDATEACCESSERROR);
633 634

  
634
            // reset name space
635
            namespaces = null;
636
            namespaces = new Hashtable<String, String>();
637
        }//not inline data
638
        else {
639
            // we don't buffer the inline data in characters() method
640
            // so start character don't need to hand text node.
635
			}
641 636

  
642
            // inline data may be the xml format.
643
            StringBuffer inlineElements = new StringBuffer();
644
            inlineElements.append("<").append(qName);
645
            // append attributes
646
            for (int i = 0; i < atts.getLength(); i++) {
647
                String attributeName = atts.getQName(i);
648
                String attributeValue = atts.getValue(i);
649
                inlineElements.append(" ");
650
                inlineElements.append(attributeName);
651
                inlineElements.append("=\"");
652
                inlineElements.append(attributeValue);
653
                inlineElements.append("\"");
654
            }
655
            // append namespace
656
            String prefix = null;
657
            String nsuri = null;
658
            Enumeration<String> prefixes = inlineDataNameSpace.keys();
659
            while (prefixes.hasMoreElements()) {
660
                prefix = prefixes.nextElement();
661
                nsuri = namespaces.get(prefix);
662
                inlineElements.append(" ");
663
                inlineElements.append("xmlns:");
664
                inlineElements.append(prefix);
665
                inlineElements.append("=\"");
666
                inlineElements.append(nsuri);
667
                inlineElements.append("\"");
668
            }
669
            inlineElements.append(">");
670
            //reset inline data name space
671
            inlineDataNameSpace = null;
672
            inlineDataNameSpace = new Hashtable<String, String>();
673
            //write inline data into file
674
            logMetacat.debug("the inline element data is: "
675
                    + inlineElements.toString());
676
            writeInlineDataIntoFile(inlineDataFileWriter, inlineElements);
677
        }//else
637
			// store access module element and attributes into stored stack
638
			if (needToCheckAccessModule
639
					&& (processAdditionalAccess || processOtherAccess || processTopLevelAccess)) {
640
				// stored the pull out nodes into storedNode stack
641
				NodeRecord nodeElement = new NodeRecord(-2, -2, -2, "ELEMENT", localName,
642
						prefix, MetaCatUtil.normalize(null));
643
				storedAccessNodeStack.push(nodeElement);
644
				for (int i = 0; i < atts.getLength(); i++) {
645
					String attributeName = atts.getQName(i);
646
					String attributeValue = atts.getValue(i);
647
					NodeRecord nodeAttribute = new NodeRecord(-2, -2, -2, "ATTRIBUTE",
648
							attributeName, null, MetaCatUtil.normalize(attributeValue));
649
					storedAccessNodeStack.push(nodeAttribute);
650
				}
678 651

  
679
    }
652
			}
680 653

  
681
    private void compareElementNameSpaceAttributes(Stack<NodeRecord> unchangeableNodeStack,
682
            Hashtable<String,String> nameSpaces, Attributes attributes, String localName,
683
            String error) throws SAXException
684
    {
685
        //Get element subtree node stack (element node)
686
        NodeRecord elementNode = null;
687
        try {
688
            elementNode = unchangeableNodeStack.pop();
689
        } catch (EmptyStackException ee) {
690
            logMetacat.error("Node stack is empty for element data");
691
            throw new SAXException(error);
692
        }
693
        logMetacat.debug("current node type from xml is ELEMENT");
694
        logMetacat.debug("node type from stack: "
695
                + elementNode.getNodeType());
696
        logMetacat.debug("node name from xml document: " + localName);
697
        logMetacat.debug("node name from stack: "
698
                + elementNode.getNodeName());
699
        logMetacat.debug("node data from stack: "
700
                + elementNode.getNodeData());
701
        logMetacat.debug("node id is: " + elementNode.getNodeId());
702
        // if this node is not element or local name not equal or name space
703
        // not equals, throw an exception
704
        if (!elementNode.getNodeType().equals("ELEMENT")
705
                || !localName.equals(elementNode.getNodeName()))
706
        //  (uri != null && !uri.equals(elementNode.getNodePrefix())))
707
        {
708
            logMetacat.error("Inconsistence happened: ");
709
            logMetacat.error("current node type from xml is ELEMENT");
710
            logMetacat.error("node type from stack: "
711
                    + elementNode.getNodeType());
712
            logMetacat.error("node name from xml document: "
713
                    + localName);
714
            logMetacat.error("node name from stack: "
715
                    + elementNode.getNodeName());
716
            logMetacat.error("node data from stack: "
717
                    + elementNode.getNodeData());
718
            logMetacat.error("node id is: " + elementNode.getNodeId());
719
            throw new SAXException(error);
720
        }
654
			// reset name space
655
			namespaces = null;
656
			namespaces = new Hashtable<String, String>();
657
		}// not inline data
658
		else {
659
			// we don't buffer the inline data in characters() method
660
			// so start character don't need to hand text node.
721 661

  
722
        //compare namespace
723
        Enumeration<String> nameEn = nameSpaces.keys();
724
        while (nameEn.hasMoreElements()) {
725
            //Get namespacke node stack (element node)
726
            NodeRecord nameNode = null;
727
            try {
728
                nameNode = unchangeableNodeStack.pop();
729
            } catch (EmptyStackException ee) {
730
                logMetacat.error(
731
                        "Node stack is empty for namespace data");
732
                throw new SAXException(error);
733
            }
662
			// inline data may be the xml format.
663
			StringBuffer inlineElements = new StringBuffer();
664
			inlineElements.append("<").append(qName);
665
			// append attributes
666
			for (int i = 0; i < atts.getLength(); i++) {
667
				String attributeName = atts.getQName(i);
668
				String attributeValue = atts.getValue(i);
669
				inlineElements.append(" ");
670
				inlineElements.append(attributeName);
671
				inlineElements.append("=\"");
672
				inlineElements.append(attributeValue);
673
				inlineElements.append("\"");
674
			}
675
			// append namespace
676
			String prefix = null;
677
			String nsuri = null;
678
			Enumeration<String> prefixes = inlineDataNameSpace.keys();
679
			while (prefixes.hasMoreElements()) {
680
				prefix = prefixes.nextElement();
681
				nsuri = namespaces.get(prefix);
682
				inlineElements.append(" ");
683
				inlineElements.append("xmlns:");
684
				inlineElements.append(prefix);
685
				inlineElements.append("=\"");
686
				inlineElements.append(nsuri);
687
				inlineElements.append("\"");
688
			}
689
			inlineElements.append(">");
690
			// reset inline data name space
691
			inlineDataNameSpace = null;
692
			inlineDataNameSpace = new Hashtable<String, String>();
693
			// write inline data into file
694
			logMetacat.debug("the inline element data is: " + inlineElements.toString());
695
			writeInlineDataIntoFile(inlineDataFileWriter, inlineElements);
696
		}// else
734 697

  
735
            String prefixName = nameEn.nextElement();
736
            String nameSpaceUri = nameSpaces.get(prefixName);
737
            if (!nameNode.getNodeType().equals("NAMESPACE")
738
                    || !prefixName.equals(nameNode.getNodeName())
739
                    || !nameSpaceUri.equals(nameNode.getNodeData())) {
740
                logMetacat.error("Inconsistence happened: ");
741
                logMetacat.error(
742
                        "current node type from xml is NAMESPACE");
743
                logMetacat.error("node type from stack: "
744
                        + nameNode.getNodeType());
745
                logMetacat.error("current node name from xml is: "
746
                        + prefixName);
747
                logMetacat.error("node name from stack: "
748
                        + nameNode.getNodeName());
749
                logMetacat.error("current node data from xml is: "
750
                        + nameSpaceUri);
751
                logMetacat.error("node data from stack: "
752
                        + nameNode.getNodeData());
753
                logMetacat.error("node id is: " + nameNode.getNodeId());
754
                throw new SAXException(error);
755
            }
698
	}
756 699

  
757
        }//while
700
	private void compareElementNameSpaceAttributes(
701
			Stack<NodeRecord> unchangeableNodeStack,
702
			Hashtable<String, String> nameSpaces, Attributes attributes,
703
			String localName, String error) throws SAXException {
704
		// Get element subtree node stack (element node)
705
		NodeRecord elementNode = null;
706
		try {
707
			elementNode = unchangeableNodeStack.pop();
708
		} catch (EmptyStackException ee) {
709
			logMetacat.error("Node stack is empty for element data");
710
			throw new SAXException(error);
711
		}
712
		logMetacat.debug("current node type from xml is ELEMENT");
713
		logMetacat.debug("node type from stack: " + elementNode.getNodeType());
714
		logMetacat.debug("node name from xml document: " + localName);
715
		logMetacat.debug("node name from stack: " + elementNode.getNodeName());
716
		logMetacat.debug("node data from stack: " + elementNode.getNodeData());
717
		logMetacat.debug("node id is: " + elementNode.getNodeId());
718
		// if this node is not element or local name not equal or name space
719
		// not equals, throw an exception
720
		if (!elementNode.getNodeType().equals("ELEMENT")
721
				|| !localName.equals(elementNode.getNodeName()))
722
		// (uri != null && !uri.equals(elementNode.getNodePrefix())))
723
		{
724
			logMetacat.error("Inconsistence happened: ");
725
			logMetacat.error("current node type from xml is ELEMENT");
726
			logMetacat.error("node type from stack: " + elementNode.getNodeType());
727
			logMetacat.error("node name from xml document: " + localName);
728
			logMetacat.error("node name from stack: " + elementNode.getNodeName());
729
			logMetacat.error("node data from stack: " + elementNode.getNodeData());
730
			logMetacat.error("node id is: " + elementNode.getNodeId());
731
			throw new SAXException(error);
732
		}
758 733

  
759
        //compare attributes
760
        for (int i = 0; i < attributes.getLength(); i++) {
761
            NodeRecord attriNode = null;
762
            try {
763
                attriNode = unchangeableNodeStack.pop();
734
		// compare namespace
735
		Enumeration<String> nameEn = nameSpaces.keys();
736
		while (nameEn.hasMoreElements()) {
737
			// Get namespacke node stack (element node)
738
			NodeRecord nameNode = null;
739
			try {
740
				nameNode = unchangeableNodeStack.pop();
741
			} catch (EmptyStackException ee) {
742
				logMetacat.error("Node stack is empty for namespace data");
743
				throw new SAXException(error);
744
			}
764 745

  
765
            } catch (EmptyStackException ee) {
766
                logMetacat.error("Node stack is empty for attribute data");
767
                throw new SAXException(error);
768
            }
769
            String attributeName = attributes.getQName(i);
770
            String attributeValue = attributes.getValue(i);
771
            logMetacat.debug(
772
                    "current node type from xml is ATTRIBUTE ");
773
            logMetacat.debug("node type from stack: "
774
                    + attriNode.getNodeType());
775
            logMetacat.debug("current node name from xml is: "
776
                    + attributeName);
777
            logMetacat.debug("node name from stack: "
778
                    + attriNode.getNodeName());
779
            logMetacat.debug("current node data from xml is: "
780
                    + attributeValue);
781
            logMetacat.debug("node data from stack: "
782
                    + attriNode.getNodeData());
783
            logMetacat.debug("node id  is: " + attriNode.getNodeId());
746
			String prefixName = nameEn.nextElement();
747
			String nameSpaceUri = nameSpaces.get(prefixName);
748
			if (!nameNode.getNodeType().equals("NAMESPACE")
749
					|| !prefixName.equals(nameNode.getNodeName())
750
					|| !nameSpaceUri.equals(nameNode.getNodeData())) {
751
				logMetacat.error("Inconsistence happened: ");
752
				logMetacat.error("current node type from xml is NAMESPACE");
753
				logMetacat.error("node type from stack: " + nameNode.getNodeType());
754
				logMetacat.error("current node name from xml is: " + prefixName);
755
				logMetacat.error("node name from stack: " + nameNode.getNodeName());
756
				logMetacat.error("current node data from xml is: " + nameSpaceUri);
757
				logMetacat.error("node data from stack: " + nameNode.getNodeData());
758
				logMetacat.error("node id is: " + nameNode.getNodeId());
759
				throw new SAXException(error);
760
			}
784 761

  
785
            if (!attriNode.getNodeType().equals("ATTRIBUTE")
786
                    || !attributeName.equals(attriNode.getNodeName())
787
                    || !attributeValue.equals(attriNode.getNodeData())) {
788
                logMetacat.error("Inconsistence happened: ");
789
                logMetacat.error(
790
                        "current node type from xml is ATTRIBUTE ");
791
                logMetacat.error("node type from stack: "
792
                        + attriNode.getNodeType());
793
                logMetacat.error("current node name from xml is: "
794
                        + attributeName);
795
                logMetacat.error("node name from stack: "
796
                        + attriNode.getNodeName());
797
                logMetacat.error("current node data from xml is: "
798
                        + attributeValue);
799
                logMetacat.error("node data from stack: "
800
                        + attriNode.getNodeData());
801
                logMetacat.error("node is: " + attriNode.getNodeId());
802
                throw new SAXException(error);
803
            }
804
        }//for
762
		}// while
805 763

  
806
    }
764
		// compare attributes
765
		for (int i = 0; i < attributes.getLength(); i++) {
766
			NodeRecord attriNode = null;
767
			try {
768
				attriNode = unchangeableNodeStack.pop();
807 769

  
808
    /* method to compare current text node and node in db */
809
    private void compareTextNode(Stack<NodeRecord> nodeStack, StringBuffer text,
810
            String error) throws SAXException
811
    {
812
        NodeRecord node = null;
813
        //get node from current stack
814
        try {
815
            node = nodeStack.pop();
816
        } catch (EmptyStackException ee) {
817
            logMetacat.error(
818
                    "Node stack is empty for text data in startElement");
819
            throw new SAXException(error);
820
        }
821
        logMetacat.debug(
822
                "current node type from xml is TEXT in start element");
823
        logMetacat.debug("node type from stack: " + node.getNodeType());
824
        logMetacat.debug("current node data from xml is: "
825
                + text.toString());
826
        logMetacat.debug("node data from stack: " + node.getNodeData());
827
        logMetacat.debug("node name from stack: " + node.getNodeName());
828
        logMetacat.debug("node is: " + node.getNodeId());
829
        if (!node.getNodeType().equals("TEXT")
830
                || !(text.toString()).equals(node.getNodeData())) {
831
            logMetacat.error("Inconsistence happened: ");
832
            logMetacat.error(
833
                    "current node type from xml is TEXT in start element");
834
            logMetacat.error("node type from stack: "
835
                    + node.getNodeType());
836
            logMetacat.error("current node data from xml is: "
837
                    + text.toString());
838
            logMetacat.error("node data from stack: "
839
                    + node.getNodeData());
840
            logMetacat.error("node name from stack: "
841
                    + node.getNodeName());
842
            logMetacat.error("node is: " + node.getNodeId());
843
            throw new SAXException(error);
844
        }//if
845
    }
770
			} catch (EmptyStackException ee) {
771
				logMetacat.error("Node stack is empty for attribute data");
772
				throw new SAXException(error);
773
			}
774
			String attributeName = attributes.getQName(i);
775
			String attributeValue = attributes.getValue(i);
776
			logMetacat.debug("current node type from xml is ATTRIBUTE ");
777
			logMetacat.debug("node type from stack: " + attriNode.getNodeType());
778
			logMetacat.debug("current node name from xml is: " + attributeName);
779
			logMetacat.debug("node name from stack: " + attriNode.getNodeName());
780
			logMetacat.debug("current node data from xml is: " + attributeValue);
781
			logMetacat.debug("node data from stack: " + attriNode.getNodeData());
782
			logMetacat.debug("node id  is: " + attriNode.getNodeId());
846 783

  
847
    /** SAX Handler that is called for each XML text node */
848
    public void characters(char[] cbuf, int start, int len) throws SAXException
849
    {
850
        logMetacat.debug("CHARACTERS");
851
        if (!handleInlineData) {
852
            // buffer all text nodes for same element. This is for if text was
853
            // split into different nodes
854
            textBuffer.append(new String(cbuf, start, len));
855
            // set hittextnode true
856
            hitTextNode = true;
857
            // if text buffer .size is greater than max, write it to db.
858
            // so we can save memory
859
            if (textBuffer.length() > MAXDATACHARS) {
860
                logMetacat.debug("Write text into DB in charaters"
861
                       + " when text buffer size is greater than maxmum number");
862
                DBSAXNode currentNode = (DBSAXNode) nodeStack.peek();
863
                endNodeId = writeTextForDBSAXNode(endNodeId, textBuffer,
864
                        currentNode);
865
                textBuffer = null;
866
                textBuffer = new StringBuffer();
867
            }
868
        } else {
869
            // this is inline data and write file system directly
870
            // we don't need to buffer it.
871
            StringBuffer inlineText = new StringBuffer();
872
            inlineText.append(new String(cbuf, start, len));
873
            logMetacat.debug(
874
                    "The inline text data write into file system: "
875
                            + inlineText.toString());
876
            writeInlineDataIntoFile(inlineDataFileWriter, inlineText);
877
        }
878
    }
784
			if (!attriNode.getNodeType().equals("ATTRIBUTE")
785
					|| !attributeName.equals(attriNode.getNodeName())
786
					|| !attributeValue.equals(attriNode.getNodeData())) {
787
				logMetacat.error("Inconsistence happened: ");
788
				logMetacat.error("current node type from xml is ATTRIBUTE ");
789
				logMetacat.error("node type from stack: " + attriNode.getNodeType());
790
				logMetacat.error("current node name from xml is: " + attributeName);
791
				logMetacat.error("node name from stack: " + attriNode.getNodeName());
792
				logMetacat.error("current node data from xml is: " + attributeValue);
793
				logMetacat.error("node data from stack: " + attriNode.getNodeData());
794
				logMetacat.error("node is: " + attriNode.getNodeId());
795
				throw new SAXException(error);
796
			}
797
		}// for
879 798

  
880
    /** SAX Handler that is called at the end of each XML element */
881
    public void endElement(String uri, String localName, String qName)
882
            throws SAXException
883
    {
884
        logMetacat.debug("End ELEMENT " + qName);
799
	}
885 800

  
886
        if (localName.equals(INLINE) && handleInlineData) {
887
            // Get the node from the stack
888
            DBSAXNode currentNode = (DBSAXNode) nodeStack.pop();
889
            logMetacat.debug("End of inline data");
890
            // close file writer
891
            try {
892
                inlineDataFileWriter.close();
893
                handleInlineData = false;
894
            } catch (IOException ioe) {
895
                throw new SAXException(ioe.getMessage());
896
            }
897
            // MCD - Removed the following code.  It is used for node level access 
898
        	// control which is not yet implemented in EML 2.1.0
899
            // //check if user changed inline data or not if user doesn't have
900
            // // write permission
901
            // if (startCriticalSubTree) {
902
            //    NodeRecord node = null;
903
            //    try {
904
            //        node = currentUnChangeableSubtreeNodeStack.pop();
905
            //        // get file name from db
906
            //        String fileName = node.getNodeData();
907
            //            logMetacat.info("in handle inline data");
908
            //      logMetacat.info(
909
            //             "the inline data file name from node is: "
910
            //                    + fileName);
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff