Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that manages database access of xml access  
4
 *             information.
5
 *  Copyright: 2009 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Michael Daigle
8
 * 
9
 *   '$Author: daigle $'
10
 *     '$Date: 2009-03-23 13:56:56 -0800 (Mon, 23 Mar 2009) $'
11
 * '$Revision: 4854 $'
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.accesscontrol;
29

    
30
import java.sql.PreparedStatement;
31
import java.sql.ResultSet;
32
import java.sql.SQLException;
33
import java.util.Vector;
34

    
35
import org.apache.log4j.Logger;
36

    
37
import edu.ucsb.nceas.metacat.database.DBConnection;
38
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
39
import edu.ucsb.nceas.metacat.shared.AccessException;
40
import edu.ucsb.nceas.metacat.shared.BaseAccess;
41

    
42
public class XMLAccessAccess extends BaseAccess {
43
	
44
	private Logger logMetacat = Logger.getLogger(XMLAccessAccess.class);
45
	
46
	// Constructor
47
	public XMLAccessAccess() throws AccessException {
48
		super("XMLAccessAccess");
49
	}
50
	
51
	/**
52
	 * Get all xml access for a document
53
	 * 
54
	 * @param docId
55
	 *            the id of the document
56
	 * @return an xml access DAO list
57
	 */ 
58
	public Vector<XMLAccessDAO> getXMLAccessForDoc(String docId) throws AccessException {
59

    
60
		Vector<XMLAccessDAO> xmlAccessList = new Vector<XMLAccessDAO>();
61
		
62
		if (docId == null) {
63
			throw new AccessException("XMLAccessAccess.getXMLAccessForDoc - doc id " + 
64
					"must be specified when selecting xml_access record");
65
		}
66
			
67
		// first get the job from the db and put it into a DAO
68
		PreparedStatement pstmt = null;
69
		try {
70
			String sql = "SELECT * FROM xml_access WHERE docid = ?";
71
			pstmt = conn.prepareStatement(sql);
72

    
73
			pstmt.setString(1, docId);
74
			
75
			String sqlReport = "XMLAccessAccess.getXMLAccessForDoc - SQL: " + sql;
76
			sqlReport += " [" + docId + "]";
77
			
78
			logMetacat.info(sqlReport);
79
			
80
			pstmt.execute();
81
			
82
			ResultSet resultSet = pstmt.getResultSet();
83
			while (resultSet.next()) {
84
				XMLAccessDAO xmlAccessDAO = populateDAO(resultSet);
85
				xmlAccessList.add(xmlAccessDAO);
86
			}
87
						
88
			validateDocXMLAccessList(xmlAccessList);
89
			
90
			return xmlAccessList;
91
			
92
		} catch (SQLException sqle) {
93
			throw new AccessException("XMLAccessAccess.getXMLAccessForDoc - SQL error when getting access " + 
94
					" for doc id: " + docId  + " : "  + sqle.getMessage());
95
		} catch (PermOrderException poe) {
96
			String errorStr = "XMLAccessAccess.getXMLAccessForDoc - Permission order error when getting " + 
97
				"access record for doc id: " + docId + " : "  + poe.getMessage();
98
			logMetacat.error(errorStr);
99
			throw new AccessException(errorStr);
100
		} finally {
101
			try {
102
				if (pstmt != null) {
103
					pstmt.close();
104
				}
105
			} catch (SQLException sqle) {
106
				logMetacat.error("XMLAccessAccess.getXMLAccessForDoc - An error occurred " 
107
						+ "closing prepared statement: " + sqle.getMessage());
108
			} 
109
		}		
110
	}
111
	
112
	/**
113
	 * Get all xml access for a principal for a certain document
114
	 * 
115
	 * @param docId
116
	 *            the id of the document
117
	 * @param principalName
118
	 *            the credentials of the principal in the database
119
	 * @return an xml access DAO list
120
	 */ 
121
	public Vector<XMLAccessDAO> getXMLAccessForPrincipal(String docId, String principalName) 
122
			throws AccessException {
123

    
124
		Vector<XMLAccessDAO> xmlAccessList = new Vector<XMLAccessDAO>();
125
		
126
		if (docId == null) { 
127
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - doc id " + 
128
					"must be specified when selecting xml_access record");
129
		}
130
		if (principalName == null) { 
131
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - doc id " + 
132
					"must be specified when selecting xml_access record");
133
		}
134
			
135
		// first get the job from the db and put it into a DAO
136
		PreparedStatement pstmt = null;
137
		try {
138
			String sql = "SELECT * FROM xml_access WHERE docid = ? AND principal_name = ?";
139
			pstmt = conn.prepareStatement(sql);
140

    
141
			pstmt.setString(1, docId);
142
			pstmt.setString(2, principalName);
143
			
144
			String sqlReport = "XMLAccessAccess.getXMLAccessForPrincipal - SQL: " + sql;
145
			sqlReport += " [" + docId + "," + principalName + "]";
146
			
147
			logMetacat.info(sqlReport);
148
			
149
			pstmt.execute();
150
			
151
			ResultSet resultSet = pstmt.getResultSet();
152
			while (resultSet.next()) {
153
				XMLAccessDAO xmlAccessDAO = populateDAO(resultSet);
154
				xmlAccessList.add(xmlAccessDAO);
155
			}
156
			
157
			validatePrincipalXMLAccessList(xmlAccessList);
158
			
159
			return xmlAccessList;
160
			
161
		} catch (SQLException sqle) {
162
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - SQL error when getting access " + 
163
					" for doc id: " + docId + ", principal: " + principalName  + " : "  + sqle.getMessage());
164
		} catch (PermOrderException poe) {
165
			String errorStr = "XMLAccessAccess.getXMLAccessForPrincipal - Permission order error when getting " + 
166
				"access record for doc id: " + docId + ", principal: " + principalName + " : "  + poe.getMessage();
167
			logMetacat.error(errorStr);
168
			throw new AccessException(errorStr);
169
		} finally {
170
			try {
171
				if (pstmt != null) {
172
					pstmt.close();
173
				}
174
			} catch (SQLException sqle) {
175
				logMetacat.error("XMLAccessAccess.getXMLAccessForPrincipal - An error occurred " 
176
						+ "closing prepared statement: " + sqle.getMessage());
177
			} 
178
		}		
179
	}
180
	
181
	/**
182
	 * Get all xml access for a principal for a certain document
183
	 * 
184
	 * @param docId
185
	 *            the id of the document
186
	 * @param principalName
187
	 *            the credentials of the principal in the database
188
	 * @return an xml access DAO list
189
	 */ 
190
	public Vector<XMLAccessDAO> getXMLAccessForPrincipal(String docId, String principalName, String permType, String permOrder) 
191
			throws AccessException {
192

    
193
		Vector<XMLAccessDAO> xmlAccessList = new Vector<XMLAccessDAO>();
194
		
195
		if (docId == null) { 
196
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - doc id " + 
197
					"must be specified when selecting xml_access record");
198
		}
199
		if (principalName == null) { 
200
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - doc id " + 
201
					"must be specified when selecting xml_access record");
202
		}
203
		if (permType == null) { 
204
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - permission type " + 
205
					"must be specified when selecting xml_access record");
206
		}
207
		if (permOrder == null) { 
208
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - permission order " + 
209
					"must be specified when selecting xml_access record");
210
		}
211
					
212
		// first get the job from the db and put it into a DAO
213
		PreparedStatement pstmt = null;
214
		try {
215
			String sql = "SELECT * FROM xml_access WHERE docid = ? AND principal_name = ? " + 
216
				"AND perm_type = ? AND perm_order = ?";
217
			pstmt = conn.prepareStatement(sql);
218

    
219
			pstmt.setString(1, docId);
220
			pstmt.setString(2, principalName);
221
			pstmt.setString(3, permType);			
222
			pstmt.setString(4, permOrder);
223
			
224
			String sqlReport = "XMLAccessAccess.getXMLAccessForPrincipal - SQL: " + sql;
225
			sqlReport += " [" + docId + "," + principalName + "," +  permType + "," + permOrder + "]";
226
			
227
			logMetacat.info(sqlReport);
228
			
229
			pstmt.execute();
230
			
231
			ResultSet resultSet = pstmt.getResultSet();
232
			while (resultSet.next()) {
233
				XMLAccessDAO xmlAccessDAO = populateDAO(resultSet);
234
				xmlAccessList.add(xmlAccessDAO);
235
			}
236
			
237
			validatePrincipalXMLAccessList(xmlAccessList);
238
			
239
			return xmlAccessList;
240
			
241
		} catch (SQLException sqle) {
242
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - SQL error when getting access " + 
243
					" for doc id: " + docId + ", principal: " + principalName  + " : "  + sqle.getMessage());
244
		} catch (PermOrderException poe) {
245
			String errorStr = "XMLAccessAccess.getXMLAccessForPrincipal - Permission order error when getting " + 
246
				"access record for doc id: " + docId + ", principal: " + principalName + " : "  + poe.getMessage();
247
			logMetacat.error(errorStr);
248
			throw new AccessException(errorStr);
249
		} finally {
250
			try {
251
				if (pstmt != null) {
252
					pstmt.close();
253
				}
254
			} catch (SQLException sqle) {
255
				logMetacat.error("XMLAccessAccess.getXMLAccessForPrincipal - An error occurred " 
256
						+ "closing prepared statement: " + sqle.getMessage());
257
			} 
258
		}		
259
	}
260
	
261
	/**
262
	 * Add permissions for a given principal on a given document. If the
263
	 * principal already exists, bitwise OR the permission to the existing
264
	 * permission and update.
265
	 * 
266
	 * @param docId
267
	 *            document id
268
	 * @param principalName
269
	 *            principal credentials
270
	 * @param permission
271
	 *            permission bitmap
272
	 * @param permType
273
	 *            permission type
274
	 * @param permOrder
275
	 *            permission order
276
	 */
277
	public void addXMLAccess(String docId, String principalName, Long permission, String permType, 
278
			String permOrder) throws AccessException {
279
		Vector<XMLAccessDAO> xmlAccessList = 
280
			getXMLAccessForPrincipal(docId, principalName, permType, permOrder);
281
		
282
		// if more than one record exists for this principal on this document with the same
283
		// access type / access order combination, call cleanup to combine common access and then
284
		// re-retrieve the access list.
285
		if (xmlAccessList.size() == 0) {
286
			insertXMLAccess(docId, principalName, permission, permType, permOrder);
287
			return;
288
		}
289
		
290
		if (xmlAccessList.size() > 1) {
291
			cleanupXMLAccessForPrincipal(xmlAccessList);
292
			xmlAccessList = getXMLAccessForPrincipal(docId, principalName, permType, permOrder);
293
		}
294
		
295
		if (xmlAccessList.size() == 0) {
296
			throw new AccessException("XMLAccessAccess.addXMLAccess - xml access list is empty when " + 
297
				"it shouldn't be for docid: " + docId + ", prinicpal name: " + principalName + ", perm type " + 
298
				permType + ", perm order: " + permOrder);	
299
		}
300
		
301
		XMLAccessDAO xmlAccessDAO = xmlAccessList.get(0);
302
		
303
		
304
		// if the permission on the xml access dao does not already contain the permission we are 
305
		//trying to add, update the access record with the existing permission bitwis OR-ed with our
306
		// new permission
307
		if ((xmlAccessDAO.getPermission() & permission) != permission) {		
308
			updateXMLAccessPermission(docId, principalName, xmlAccessDAO.getPermission() | permission);
309
		}
310
	}
311
	
312
	/**
313
	 * Set permissions for a given document. This means first removing all access control for the
314
	 * document and then adding the given rules.
315
	 * 
316
	 * @param docId
317
	 *            document id
318
	 * @param xmlAccessList
319
	 *            list of xml access dao objects that hold new access for the document
320
	 */
321
	public void setXMLAccess(String docId, Vector<XMLAccessDAO> xmlAccessList) throws AccessException {
322
		deleteXMLAccessForDoc(docId);
323
		
324
		// if more than one record exists for this principal on this document with the same
325
		// access type / access order combination, call cleanup to combine common access and then
326
		// re-retrieve the access list.
327
		for(XMLAccessDAO xmlAccessDAO : xmlAccessList) {
328
			insertXMLAccess(docId, xmlAccessDAO.getPrincipalName(), xmlAccessDAO.getPermission(), 
329
					xmlAccessDAO.getPermType(), xmlAccessDAO.getPermOrder());
330
		}
331
	}
332
	
333
	/**
334
	 * Insert an xml access record.  It is assumed that the checks have already been made to 
335
	 * make sure the principal does not already have an access record for this document.  If 
336
	 * one does already exist, that record should be updated and this insert not called.
337
	 * 
338
	 * @param docId
339
	 *            document id
340
	 * @param principal
341
	 *            principal credentials
342
	 * @param permission
343
	 *            permission bitmap
344
	 * @param permType
345
	 *            permission type
346
	 * @param permOrder
347
	 *            permission order
348
	 */
349
	private void insertXMLAccess(String docId, String principalName, Long permission, String permType,
350
			String permOrder) throws AccessException {
351
		if (docId == null) {
352
			throw new AccessException("XMLAccessAccess.insertXMLAccess - docid is required when " + 
353
					"inserting XML access record");
354
		}
355
		if (principalName == null) {
356
			throw new AccessException("XMLAccessAccess.insertXMLAccess - principal is required when " + 
357
					"inserting XML access record");
358
		}
359
		if (permission == null) {
360
			throw new AccessException("XMLAccessAccess.insertXMLAccess - permission is required when " + 
361
					"inserting XML access record");
362
		}
363
		if (permType == null) {
364
			throw new AccessException("XMLAccessAccess.insertXMLAccess - permType is required when " + 
365
					"inserting XML access record");
366
		}
367
		if (permOrder == null) {
368
			permOrder = AccessControlInterface.ALLOWFIRST;
369
		}
370
		
371
	    PreparedStatement pstmt = null;
372
		DBConnection conn = null;
373
		int serialNumber = -1;
374
		try {
375
			// check out DBConnection
376
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.insertXMLAccess");
377
			serialNumber = conn.getCheckOutSerialNumber();
378
			String sql = "INSERT INTO xml_access " +
379
				"(docid, principal_name, permission, perm_type, perm_order ) " + 
380
				"VALUES (?,?,?,?,?)";
381
			pstmt = conn.prepareStatement(sql);
382

    
383
			// Bind the values to the query
384
			pstmt.setString(1, docId);
385
			pstmt.setString(2, principalName);
386
			pstmt.setLong(3, permission);
387
			pstmt.setString(4, permType);
388
			pstmt.setString(5, permOrder);
389
			
390
			String sqlReport = "XMLAccessAccess.insertXMLAccess - SQL: " + sql;
391
			sqlReport += " [" + docId + "," + principalName + "," +  permission + "," +  permType + "," + permOrder + "]";
392
			
393
			logMetacat.info(sqlReport);
394

    
395
			pstmt.execute();
396
		} catch (SQLException sqle) {
397
			throw new AccessException("XMLAccessAccess.insertXMLAccess - SQL error when inserting"
398
					+ "xml access permissions for doc id: " + docId + ", principal: " + 
399
					principalName + ":" + sqle.getMessage());
400
		} finally {
401
			try {
402
				if (pstmt != null) {
403
					pstmt.close();
404
				}
405
			} catch (SQLException sqle) {
406
				logMetacat.error("XMLAccessAccess.insertXMLAccess - SQL error when closing prepared " + 
407
						"statement after inserting xml access permissions for doc id: " + docId + 
408
						", principal: " +  principalName + ":" + sqle.getMessage());
409
			} finally {
410
				DBConnectionPool.returnDBConnection(conn, serialNumber);
411
			}
412
		}   
413
	}
414
	
415
	/**
416
	 * Update existing xml access permissions in the db.  The permission value should be the combined
417
	 * value of pre-existing permissions plus new permissions.
418
	 * 
419
	 * @param docId
420
	 *            document id
421
	 * @param principalName
422
	 *            principal credentials
423
	 * @param permission
424
	 *            permission bitmap
425
	 */
426
	private void updateXMLAccessPermission(String docId, String principalName, Long permission)
427
			throws AccessException {
428
		if (docId == null) {
429
			throw new AccessException("XMLAccessAccess.updateXMLAccessPermission - docid is required when " + 
430
					"updating XML access record");
431
		}
432
		if (principalName == null) {
433
			throw new AccessException("XMLAccessAccess.updateXMLAccessPermission - principal is required when " + 
434
					"updating XML access record");
435
		}
436
		if (permission == null) {
437
			throw new AccessException("XMLAccessAccess.updateXMLAccessPermission - permission is required when " + 
438
					"updating XML access record");
439
		}
440
		
441
	    PreparedStatement pstmt = null;
442
		DBConnection conn = null;
443
		int serialNumber = -1;
444
		try {
445
			// check out DBConnection
446
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.updateXMLAccessPermission");
447
			serialNumber = conn.getCheckOutSerialNumber();
448
			String sql = "UPDATE xml_access SET permission = ?" +
449
				"WHERE docid = ? AND principal_name = ?";
450
			pstmt = conn.prepareStatement(sql);
451

    
452
			// Bind the values to the query
453
			pstmt.setLong(1, permission);
454
			pstmt.setString(2, docId);
455
			pstmt.setString(3, principalName);
456
			
457
			String sqlReport = "XMLAccessAccess.updateXMLAccessPermission - SQL: " + sql;
458
			sqlReport += " [" + permission + "," + docId + "," + principalName + "]";
459
			
460
			logMetacat.info(sqlReport);
461

    
462
			pstmt.execute();
463
		} catch (SQLException sqle) {
464
			throw new AccessException("XMLAccessAccess.updateXMLAccessPermission - SQL error when updating"
465
					+ "xml access permissions for doc id: " + docId + ", principal: " + 
466
					principalName + ":" + sqle.getMessage());
467
		} finally {
468
			try {
469
				if (pstmt != null) {
470
					pstmt.close();
471
				}
472
			} catch (SQLException sqle) {
473
				logMetacat.error("XMLAccessAccess.updateXMLAccessPermission - SQL error when closing prepared " + 
474
						"statement after updating xml access permissions for doc id: " + docId + 
475
						", principal: " +  principalName + ":" + sqle.getMessage());
476
			} finally {
477
				DBConnectionPool.returnDBConnection(conn, serialNumber);
478
			}
479
		}
480
		
481
	}
482
	
483
	/**
484
	 * Remove xml access.  This modifies the access in the database for a principal 
485
	 * for a given document.  If the provided permission is exactly the same as what 
486
	 * the principal has, the record is deleted from the database.
487
	 * 
488
	 * @param docId
489
	 *            document id
490
	 * @param principalName
491
	 *            principal credentials
492
	 */
493
	public void removeXMLAccessForPrincipal(String docId, String principalName, Long permission) throws AccessException {
494
		if (docId == null) {
495
			throw new AccessException("XMLAccessAccess.removeXMLAccessForPrincipal - docid is required when " + 
496
					"removing XML access");
497
		}
498
		if (principalName == null) {
499
			throw new AccessException("XMLAccessAccess.removeXMLAccessForPrincipal - principal is required when " + 
500
					"deleting XML access");
501
		}
502
		if (permission == null) {
503
			throw new AccessException("XMLAccessAccess.removeXMLAccessForPrincipal - permission is required when " + 
504
					"updating XML access");
505
		}
506
		
507
		Vector<XMLAccessDAO> xmlAccessList = getXMLAccessForPrincipal(docId, principalName);
508
		if (xmlAccessList.size() == 0) {
509
			logMetacat.warn("XMLAccessAccess.removeXMLAccessForPrincipal - attempting to remove access when no " +
510
				"access record exists for docid: " + docId + ", principal: " + principalName);
511
		} else {
512
			long permissionMask = 0;
513
			for (XMLAccessDAO xmlAccessDAO : xmlAccessList) {
514
				permissionMask |= xmlAccessDAO.getPermission();
515
			}
516
			permissionMask |= permission;
517
			
518
			// in this case, the only existing permissions are the ones we want to remove, so 
519
			// delete the record(s) for this principal on this document
520
			if ((permissionMask & permission) == permission) {
521
				deleteXMLAccessForPrincipal(docId, principalName);
522
			}
523
			
524
			if (xmlAccessList.size() > 1) {
525
				
526
			} else {
527
				updateXMLAccessPermission(docId, principalName, permission);
528
			}
529
		}
530
	   
531
	}
532
	
533
	/**
534
	 * Delete xml access.  This removes all access records from the database for a given document
535
	 * 
536
	 * @param docId
537
	 *            document id
538
	 */
539
	public void deleteXMLAccessForDoc(String docId) throws AccessException {
540
		if (docId == null) {
541
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - docid is required when " + 
542
					"deleting XML access record");
543
		}
544
		
545
	    PreparedStatement pstmt = null;
546
		DBConnection conn = null;
547
		int serialNumber = -1;
548
		try {
549
			// check out DBConnection
550
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.deleteXMLAccessForDoc");
551
			String sql = "DELETE FROM xml_access WHERE docid = ?";
552
			pstmt = conn.prepareStatement(sql);
553

    
554
			// Bind the values to the query
555
			pstmt.setString(1, docId);
556

    
557
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForDoc - SQL: " + sql;
558
			sqlReport += " [" + docId + "]";
559
			
560
			logMetacat.info(sqlReport);
561

    
562
			pstmt.execute();
563
		} catch (SQLException sqle) {
564
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForDoc - SQL error when deleting"
565
					+ "xml access permissions for doc id: " + docId + ":" + sqle.getMessage());
566
		} finally {
567
			try {
568
				if (pstmt != null) {
569
					pstmt.close();
570
				}
571
			} catch (SQLException sqle) {
572
				logMetacat.error("XMLAccessAccess.deleteXMLAccessForDoc - SQL error when closing prepared " + 
573
						"statement after deleting xml access permissions for doc id: " + ":" + sqle.getMessage());
574
			} finally {
575
				DBConnectionPool.returnDBConnection(conn, serialNumber);
576
			}
577
		}	   
578
	}
579
	
580
	/**
581
	 * Delete xml access.  This removes all access records from the database for a principal 
582
	 * for a given document
583
	 * 
584
	 * @param docId
585
	 *            document id
586
	 * @param principal
587
	 *            principal credentials
588
	 */
589
	private void deleteXMLAccessForPrincipal(String docId, String principalName) throws AccessException {
590
		if (docId == null) {
591
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - docid is required when " + 
592
					"deleting XML access record");
593
		}
594
		if (principalName == null) {
595
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - principal is required when " + 
596
					"deleting XML access record");
597
		}
598
		
599
	    PreparedStatement pstmt = null;
600
		DBConnection conn = null;
601
		int serialNumber = -1;
602
		try {
603
			// check out DBConnection
604
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.deleteXMLAccessForPrincipal");
605
			String sql = "DELETE FROM xml_access WHERE docid = ? AND principal_name = ?";
606
			pstmt = conn.prepareStatement(sql);
607

    
608
			// Bind the values to the query
609
			pstmt.setString(1, docId);
610
			pstmt.setString(2, principalName);
611

    
612
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForPrincipal - SQL: " + sql;
613
			sqlReport += " [" + docId + "," + principalName + "]";
614
			
615
			logMetacat.info(sqlReport);
616

    
617
			pstmt.execute();
618
		} catch (SQLException sqle) {
619
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - SQL error when deleting"
620
					+ "xml access permissions for doc id: " + docId + ", principal: " + 
621
					principalName + ":" + sqle.getMessage());
622
		} finally {
623
			try {
624
				if (pstmt != null) {
625
					pstmt.close();
626
				}
627
			} catch (SQLException sqle) {
628
				logMetacat.error("XMLAccessAccess.deleteXMLAccessForPrincipal - SQL error when closing prepared " + 
629
						"statement after deleting xml access permissions for doc id: " + docId + 
630
						", principal: " +  principalName + ":" + sqle.getMessage());
631
			} finally {
632
				DBConnectionPool.returnDBConnection(conn, serialNumber);
633
			}
634
		}	   
635
	}
636
	
637
	/**
638
	 * Delete xml access.  This removes all access records from the database for a principal 
639
	 * for a given document, perm type and perm order
640
	 * @param docId
641
	 *            document id
642
	 * @param principal
643
	 *            principal credentials
644
	 */
645
	private void deleteXMLAccessForPrincipal(String docId, String principalName, String permType, String permOrder) throws AccessException {
646
		if (docId == null) {
647
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - docid is required when " + 
648
					"deleting XML access record");
649
		}
650
		if (principalName == null) {
651
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - principal is required when " + 
652
					"deleting XML access record");
653
		}
654
		if (permType == null) {
655
			throw new AccessException(
656
					"XMLAccessAccess.deleteXMLAccessForPrincipal - perm type is required when "
657
							+ "deleting XML access record");
658
		}
659
		if (permOrder == null) {
660
			throw new AccessException(
661
					"XMLAccessAccess.deleteXMLAccessForPrincipal - perm order is required when "
662
							+ "deleting XML access record");
663
		}
664
		
665
	    PreparedStatement pstmt = null;
666
		DBConnection conn = null;
667
		int serialNumber = -1;
668
		try {
669
			// check out DBConnection
670
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.deleteXMLAccessForPrincipal");
671
			String sql = "DELETE FROM xml_access WHERE docid = ? AND principal_name = ?" +
672
				"AND perm_type = ? AND perm_ord";
673
			pstmt = conn.prepareStatement(sql);
674

    
675
			// Bind the values to the query
676
			pstmt.setString(1, docId);
677
			pstmt.setString(2, principalName);
678
			pstmt.setString(3, permType);
679
			pstmt.setString(4, permOrder);
680
			
681
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForPrincipal - SQL: " + sql;
682
			sqlReport += " [" + docId + "," + principalName + "," + permType + "," + permOrder + "]";
683
			
684
			logMetacat.info(sqlReport);
685

    
686
			pstmt.execute();
687
		} catch (SQLException sqle) {
688
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - SQL error when deleting"
689
					+ "xml access permissions for doc id: " + docId + ", principal: " + 
690
					principalName + ":" + sqle.getMessage());
691
		} finally {
692
			try {
693
				if (pstmt != null) {
694
					pstmt.close();
695
				}
696
			} catch (SQLException sqle) {
697
				logMetacat.error("XMLAccessAccess.deleteXMLAccessForPrincipal - SQL error when closing prepared " + 
698
						"statement after deleting xml access permissions for doc id: " + docId + 
699
						", principal: " +  principalName + ":" + sqle.getMessage());
700
			} finally {
701
				DBConnectionPool.returnDBConnection(conn, serialNumber);
702
			}
703
		}
704
	   
705
	}
706

    
707
	/**
708
	 * Make sure that only one record exists per principal/permType/document. If
709
	 * more than one record exists, delete the existing records, consolidate the
710
	 * permissions insert the new record.
711
	 * 
712
	 * @param xmlAccessList
713
	 * @throws AccessException
714
	 */
715
	private void cleanupXMLAccessForPrincipal(Vector<XMLAccessDAO> xmlAccessList) throws AccessException{
716
		
717
		int numAllowRecords = 0;
718
		int numDenyRecords = 0;
719
		long allowPermissionMask = 0;
720
		long denyPermissionMask = 0;
721
		String docId = null;
722
		String principalName = null;
723
		String permType = null;
724
		String permOrder = null;
725
	
726
		
727
		// iterate through the list of access dao objects and bttwise or the permissions.  Most
728
		// of this is just doing some error checking to make sure each record is valid.
729
		for (XMLAccessDAO xmlAccessDAO : xmlAccessList) {
730
			if (docId == null) {
731
				docId = xmlAccessDAO.getDocId();
732
			} else {
733
				if (!docId.equals(xmlAccessDAO.getDocId())) {
734
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
735
							" Conflicting doc ids " + xmlAccessDAO.getDocId() +
736
							" and " + docId);
737
				}
738
			}
739
			if (principalName == null) {
740
				principalName = xmlAccessDAO.getPrincipalName();
741
			} else {
742
				if (!principalName.equals(xmlAccessDAO.getPrincipalName())) {
743
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
744
							" Conflicting prinicpal names " + xmlAccessDAO.getPrincipalName() +
745
							" and principalName " + principalName);
746
				}
747
			}
748
			if (permType == null) {
749
				permType = xmlAccessDAO.getPermType();
750
			} else {
751
				if (!permType.equals(xmlAccessDAO.getPermType())) {
752
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
753
							" Conflicting permission orders for document " + xmlAccessDAO.getDocId() +
754
							"principalName " + principalName + ". Database intervention required ");
755
				}
756
			}
757
			if (permOrder == null) {
758
				permOrder = xmlAccessDAO.getPermOrder();
759
			} else {
760
				if (!permOrder.equals(xmlAccessDAO.getPermOrder())) {
761
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
762
							" Conflicting permission types for document " + xmlAccessDAO.getDocId() +
763
							"principalName " + principalName + ". Database intervention required ");
764
				}
765
			}
766
			if (permType == null) {
767
				permType = xmlAccessDAO.getPermType();
768
			} else {
769
				if (!permType.equals(xmlAccessDAO.getPermType())) {
770
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
771
							" Conflicting permission orders for document " + xmlAccessDAO.getDocId() +
772
							"principalName " + principalName + ". Database intervention required ");
773
				}
774
			}
775
			if (permType.equals(AccessControlInterface.ALLOW)) {
776
				numAllowRecords++;
777
				allowPermissionMask |= xmlAccessDAO.getPermission();
778
			} else if (permType.equals(AccessControlInterface.DENY)) {
779
				numDenyRecords++;
780
				denyPermissionMask |= xmlAccessDAO.getPermission();
781
			}
782
		}
783
		
784
		// if there was more than one allow record, remove all allow records for this user on this doc 
785
		// with this perm type and perm order then insert a single record 
786
		if (numAllowRecords > 1) {
787
			deleteXMLAccessForPrincipal(docId, principalName, AccessControlInterface.ALLOW, permOrder);
788
			insertXMLAccess(docId, principalName, allowPermissionMask, AccessControlInterface.ALLOW, permOrder);
789
		}
790
		// if there was more than one deny record, remove all deny records for this user on this doc 
791
		// with this perm type and perm order then insert a single record 
792
		if (numDenyRecords > 1) {
793
			deleteXMLAccessForPrincipal(docId, principalName, AccessControlInterface.DENY, permOrder);
794
			insertXMLAccess(docId, principalName, denyPermissionMask, AccessControlInterface.DENY, permOrder);
795
		}
796
	}
797
	
798
	/**
799
	 * 
800
	 * @param xmlAccessList
801
	 * @throws PermOrderException
802
	 */
803
	private void validateDocXMLAccessList(Vector<XMLAccessDAO> xmlAccessList) throws PermOrderException {
804
		String permOrder = null;
805
		for(XMLAccessDAO xmlAccessDAO : xmlAccessList) {
806
			if (permOrder == null) {
807
				permOrder = xmlAccessDAO.getPermOrder();
808
			} else {
809
				if(!permOrder.equals(xmlAccessDAO.getPermOrder())) {
810
					throw new PermOrderException("XMLAccessAccess.validateXMLAccessList - " + 
811
						" Conflicting permission orders for document " + xmlAccessDAO.getDocId() +
812
						". Database intervention required ");
813
				}
814
			}
815
		}		
816
	}
817
	
818
	private void validatePrincipalXMLAccessList(Vector<XMLAccessDAO> xmlAccessList) 
819
			throws PermOrderException {
820
		
821
		boolean allowFirst = false;
822
		boolean denyFirst = false;
823
		String docId = null;
824
		
825
		// These vectors will hold all combinations of access DAOs with different permission
826
		// orders and permission types.  
827
		Vector<XMLAccessDAO> allowFirstAllows = new Vector<XMLAccessDAO>();
828
		Vector<XMLAccessDAO> allowFirstDenys = new Vector<XMLAccessDAO>();
829
		Vector<XMLAccessDAO> denyFirstAllows = new Vector<XMLAccessDAO>();
830
		Vector<XMLAccessDAO> denyFirstDenys = new Vector<XMLAccessDAO>();
831
		
832
		// sort the access dao records into the appropriate vector
833
		for(XMLAccessDAO xmlAccessDAO : xmlAccessList) {
834
			if (docId == null) {
835
				docId = xmlAccessDAO.getDocId();
836
			}
837
			if (xmlAccessDAO.getPermOrder().equals(AccessControlInterface.ALLOWFIRST)) {
838
				allowFirst = true;
839
				if (xmlAccessDAO.getPermType().equals(AccessControlInterface.ALLOW)) {
840
					allowFirstAllows.add(xmlAccessDAO);
841
				} else if (xmlAccessDAO.getPermType().equals(AccessControlInterface.DENY)) {
842
					allowFirstDenys.add(xmlAccessDAO);
843
				} else {
844
					throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " + 
845
							" Invalid permission type: " + xmlAccessDAO.getPermType() + " for document " + 
846
							xmlAccessDAO.getDocId() + ". Database intervention required "); 
847
				}
848
			} else if (xmlAccessDAO.getPermOrder().equals(AccessControlInterface.DENYFIRST)) {
849
				denyFirst = true;
850
				if (xmlAccessDAO.getPermType().equals(AccessControlInterface.ALLOW)) {
851
					denyFirstAllows.add(xmlAccessDAO);
852
				} else if (xmlAccessDAO.getPermType().equals(AccessControlInterface.DENY)) {
853
					denyFirstDenys.add(xmlAccessDAO);
854
				} else {
855
					throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " + 
856
							" Invalid permission type: " + xmlAccessDAO.getPermType() + " for document " + 
857
							xmlAccessDAO.getDocId() + ". Database intervention required "); 
858
				}
859
			} else {
860
				throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " + 
861
						" Invalid permission order: " + xmlAccessDAO.getPermOrder() + " for document " + 
862
						xmlAccessDAO.getDocId() + ". Database intervention required "); 
863
			}
864
		}
865
		
866
		// for a given user, there cannot be allowfirst and denyfirst records on the same 
867
		// document
868
		if(allowFirst && denyFirst) {
869
			throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " + 
870
					" Conflicting permission orders for document " + docId +
871
					". Database intervention required ");
872
		}	
873
	}
874
	
875
	/**
876
	 * Populate a job data object with the current row in a resultset
877
	 * 
878
	 * @param resultSet
879
	 *            the result set which is already pointing to the desired row.
880
	 * @return a scheduled job data object
881
	 */
882
	protected XMLAccessDAO populateDAO(ResultSet resultSet) throws SQLException {
883

    
884
		XMLAccessDAO xmlAccessDAO = new XMLAccessDAO();
885
		xmlAccessDAO.setDocId(resultSet.getString("docid"));
886
		xmlAccessDAO.setAccessFileId(resultSet.getString("accessfileid"));
887
		xmlAccessDAO.setPrincipalName(resultSet.getString("principal_name"));
888
		xmlAccessDAO.setPermission(resultSet.getLong("permission"));
889
		xmlAccessDAO.setPermType(resultSet.getString("perm_type"));
890
		xmlAccessDAO.setPermOrder(resultSet.getString("perm_order"));
891
		xmlAccessDAO.setBeginTime(resultSet.getDate("begin_time"));
892
		xmlAccessDAO.setEndTime(resultSet.getDate("end_time"));
893
		xmlAccessDAO.setTicketCount(resultSet.getLong("ticket_count"));
894
		xmlAccessDAO.setSubTreeId(resultSet.getString("subtreeid"));
895
		xmlAccessDAO.setStartNodeId(resultSet.getString("startnodeid"));
896
		xmlAccessDAO.setEndNodeId(resultSet.getString("endnodeid"));
897

    
898
		return xmlAccessDAO;
899
	}
900
	
901
}
(8-8/9)