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.List;
34
import java.util.Vector;
35

    
36
import org.apache.log4j.Logger;
37

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

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

    
59
		Vector<XMLAccessDAO> xmlAccessList = new Vector<XMLAccessDAO>();
60
		
61
		if (docId == null) {
62
			throw new AccessException("XMLAccessAccess.getXMLAccessForDoc - doc id " + 
63
					"must be specified when selecting xml_access record");
64
		}
65
			
66
		// first get the xml access from the db and put it into a DAO list
67
		PreparedStatement pstmt = null;
68
		DBConnection conn = null;
69
		int serialNumber = -1;
70
		try {			
71
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.getXMLAccessForDoc");
72
    		serialNumber = conn.getCheckOutSerialNumber();
73

    
74
			String sql = "SELECT * FROM xml_access WHERE docid = ?";
75
			pstmt = conn.prepareStatement(sql);
76

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

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

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

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

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

    
395
			// Bind the values to the query
396
			pstmt.setString(1, docId);
397
			pstmt.setString(2, principalName);
398
			pstmt.setLong(3, permission);
399
			pstmt.setString(4, permType);
400
			pstmt.setString(5, permOrder);
401
			pstmt.setString(6, accessFileId);
402
			pstmt.setString(7, subTreeId);
403
			
404
			String sqlReport = "XMLAccessAccess.insertXMLAccess - SQL: " + sql;
405
			sqlReport += " [" + docId + "," + principalName + "," +  permission + "," +  permType + "," + permOrder + "]";
406
			
407
			logMetacat.info(sqlReport);
408

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

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

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

    
551
			// Bind the values to the query
552
			pstmt.setString(1, docId);
553

    
554
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForDoc - SQL: " + sql;
555
			sqlReport += " [" + docId + "]";
556
			
557
			logMetacat.info(sqlReport);
558

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

    
598
			// Bind the values to the query
599
			pstmt.setString(1, docId);
600
			pstmt.setString(2, principalName);
601

    
602
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForPrincipal - SQL: " + sql;
603
			sqlReport += " [" + docId + "," + principalName + "]";
604
			
605
			logMetacat.info(sqlReport);
606

    
607
			pstmt.execute();
608
		} catch (SQLException sqle) {
609
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - SQL error when deleting"
610
					+ "xml access permissions for doc id: " + docId + ", principal: " + 
611
					principalName + ":" + sqle.getMessage());
612
		} finally {
613
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
614
		}	   
615
	}
616
	
617
	/**
618
	 * Checks to see if there is a permission order conflict for a given document.  Each 
619
	 * document is only allowed to have a single permission order
620
	 * 
621
	 * @param docId
622
	 *            document id
623
	 * @param principal
624
	 *            principal credentials
625
	 */
626
	private void permOrderConflict(String docId, String permOrder) throws AccessException, PermOrderException {
627
		if (docId == null) {
628
			throw new AccessException("XMLAccessAccess.permOrderConflict - docid is required when " + 
629
					"determining perm order conflict");
630
		}
631
		if (permOrder == null) {
632
			throw new AccessException("XMLAccessAccess.permOrderConflict - perm order is required when " + 
633
					"determining perm order conflict");
634
		}
635
		
636
	    PreparedStatement pstmt = null;
637
		DBConnection conn = null;
638
		int serialNumber = -1;
639
		try {
640
			// check out DBConnection
641
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.permOrderConflict");
642
    		serialNumber = conn.getCheckOutSerialNumber();
643
    		
644
			String sql = "SELECT * FROM xml_access WHERE docid = ? AND perm_order != ?";
645
			pstmt = conn.prepareStatement(sql);
646

    
647
			// Bind the values to the query
648
			pstmt.setString(1, docId);
649
			pstmt.setString(2, permOrder);
650
			
651
			String sqlReport = "XMLAccessAccess.permOrderConflict - SQL: " + sql;
652
			sqlReport += " [" + docId + "," + permOrder + "]";
653
			
654
			logMetacat.info(sqlReport);
655

    
656
			pstmt.execute();
657
			
658
			ResultSet resultSet = pstmt.getResultSet();
659
			if (resultSet.next()) {			
660
				throw new PermOrderException("XMLAccessAccess.addXMLAccess - cannot add permission " + 
661
					"record for doc id: " + docId + "with permOrder: " + permOrder + " due to permOrder conflict");
662
			}
663
		} catch (SQLException sqle) {
664
			throw new AccessException("XMLAccessAccess.permOrderConflict - SQL error when checking"
665
					+ "for perm order conflict on: " + docId + ":" + sqle.getMessage());
666
		} finally {
667
			closeDBObjects(pstmt, conn, serialNumber, logMetacat); 
668
		}
669
	   
670
	}
671
	
672
	/**
673
	 * Delete xml access.  This removes all access records from the database for a principal 
674
	 * for a given document, perm type and perm order
675
	 * 
676
	 * @param docId
677
	 *            document id
678
	 * @param principal
679
	 *            principal credentials
680
	 */
681
	private void deleteXMLAccessForPrincipal(String docId, String principalName, String permType, String permOrder) throws AccessException {
682
		if (docId == null) {
683
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - docid is required when " + 
684
					"deleting XML access record");
685
		}
686
		if (principalName == null) {
687
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - principal is required when " + 
688
					"deleting XML access record");
689
		}
690
		if (permType == null) {
691
			throw new AccessException(
692
					"XMLAccessAccess.deleteXMLAccessForPrincipal - perm type is required when "
693
							+ "deleting XML access record");
694
		}
695
		if (permOrder == null) {
696
			throw new AccessException(
697
					"XMLAccessAccess.deleteXMLAccessForPrincipal - perm order is required when "
698
							+ "deleting XML access record");
699
		}
700
		
701
	    PreparedStatement pstmt = null;
702
		DBConnection conn = null;
703
		int serialNumber = -1;
704
		try {
705
			// check out DBConnection
706
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.deleteXMLAccessForPrincipal");
707
    		serialNumber = conn.getCheckOutSerialNumber();
708
    		
709
			String sql = "DELETE FROM xml_access WHERE docid = ? AND principal_name = ? " +
710
				"AND perm_type = ? AND perm_order = ?";
711
			pstmt = conn.prepareStatement(sql);
712

    
713
			// Bind the values to the query
714
			pstmt.setString(1, docId);
715
			pstmt.setString(2, principalName);
716
			pstmt.setString(3, permType);
717
			pstmt.setString(4, permOrder);
718
			
719
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForPrincipal - SQL: " + sql;
720
			sqlReport += " [" + docId + "," + principalName + "," + permType + "," + permOrder + "]";
721
			
722
			logMetacat.info(sqlReport);
723

    
724
			pstmt.execute();
725
		} catch (SQLException sqle) {
726
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - SQL error when deleting"
727
					+ "xml access permissions for doc id: " + docId + ", principal: " + 
728
					principalName + ":" + sqle.getMessage());
729
		} finally {
730
			closeDBObjects(pstmt, conn, serialNumber, logMetacat); 
731
		}
732
	   
733
	}
734

    
735
	/**
736
	 * Make sure that only one record exists per principal/permType/document. If
737
	 * more than one record exists, delete the existing records, consolidate the
738
	 * permissions insert the new record.
739
	 * 
740
	 * @param xmlAccessList the access dao list
741
	 */
742
	private void cleanupXMLAccessForPrincipal(Vector<XMLAccessDAO> xmlAccessList) throws AccessException{
743
		
744
		int numAllowRecords = 0;
745
		int numDenyRecords = 0;
746
		long allowPermissionMask = 0;
747
		long denyPermissionMask = 0;
748
		String docId = null;
749
		String principalName = null;
750
		String permType = null;
751
		String permOrder = null;
752
		// TODO: handle these fields
753
		String accessFileId = null;
754
		String subTreeId = null;
755
	
756
		
757
		// iterate through the list of access dao objects and bttwise or the permissions.  Most
758
		// of this is just doing some error checking to make sure each record is valid.
759
		for (XMLAccessDAO xmlAccessDAO : xmlAccessList) {
760
			if (docId == null) {
761
				docId = xmlAccessDAO.getDocId();
762
			} else {
763
				if (!docId.equals(xmlAccessDAO.getDocId())) {
764
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
765
							" Conflicting doc ids " + xmlAccessDAO.getDocId() +
766
							" and " + docId);
767
				}
768
			}
769
			if (principalName == null) {
770
				principalName = xmlAccessDAO.getPrincipalName();
771
			} else {
772
				if (!principalName.equals(xmlAccessDAO.getPrincipalName())) {
773
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
774
							" Conflicting prinicpal names " + xmlAccessDAO.getPrincipalName() +
775
							" and principalName " + principalName);
776
				}
777
			}
778
			if (permType == null) {
779
				permType = xmlAccessDAO.getPermType();
780
			} else {
781
				if (!permType.equals(xmlAccessDAO.getPermType())) {
782
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
783
							" Conflicting permission orders for document " + xmlAccessDAO.getDocId() +
784
							"principalName " + principalName + ". Database intervention required ");
785
				}
786
			}
787
			if (permOrder == null) {
788
				permOrder = xmlAccessDAO.getPermOrder();
789
			} else {
790
				if (!permOrder.equals(xmlAccessDAO.getPermOrder())) {
791
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
792
							" Conflicting permission types for document " + xmlAccessDAO.getDocId() +
793
							"principalName " + principalName + ". Database intervention required ");
794
				}
795
			}
796
			if (permType == null) {
797
				permType = xmlAccessDAO.getPermType();
798
			} else {
799
				if (!permType.equals(xmlAccessDAO.getPermType())) {
800
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
801
							" Conflicting permission orders for document " + xmlAccessDAO.getDocId() +
802
							"principalName " + principalName + ". Database intervention required ");
803
				}
804
			}
805
			if (permType.equals(AccessControlInterface.ALLOW)) {
806
				numAllowRecords++;
807
				allowPermissionMask |= xmlAccessDAO.getPermission();
808
			} else if (permType.equals(AccessControlInterface.DENY)) {
809
				numDenyRecords++;
810
				denyPermissionMask |= xmlAccessDAO.getPermission();
811
			}
812
			if (accessFileId == null) {
813
				accessFileId = xmlAccessDAO.getAccessFileId();
814
			}
815
			if (subTreeId == null) {
816
				subTreeId = xmlAccessDAO.getSubTreeId();
817
			}
818
		}
819
		
820
		// if there was more than one allow record, remove all allow records for this user on this doc 
821
		// with this perm type and perm order then insert a single record 
822
		if (numAllowRecords > 1) {
823
			deleteXMLAccessForPrincipal(docId, principalName, AccessControlInterface.ALLOW, permOrder);
824
			insertXMLAccess(docId, principalName, allowPermissionMask, AccessControlInterface.ALLOW, permOrder, accessFileId, subTreeId);
825
		}
826
		// if there was more than one deny record, remove all deny records for this user on this doc 
827
		// with this perm type and perm order then insert a single record 
828
		if (numDenyRecords > 1) {
829
			deleteXMLAccessForPrincipal(docId, principalName, AccessControlInterface.DENY, permOrder);
830
			insertXMLAccess(docId, principalName, denyPermissionMask, AccessControlInterface.DENY, permOrder, accessFileId, subTreeId);
831
		}
832
	}
833
	
834
	/**
835
	 * Make sure for a given list of access DAOs that only one perm order
836
	 * exists. It is assumed that all the DAOs are for the same doc
837
	 * 
838
	 * @param xmlAccessList
839
	 *            the access dao list
840
	 */
841
	private void validateDocXMLAccessList(Vector<XMLAccessDAO> xmlAccessList) throws PermOrderException {
842
		String permOrder = null;
843
		for(XMLAccessDAO xmlAccessDAO : xmlAccessList) {
844
			if (permOrder == null) {
845
				permOrder = xmlAccessDAO.getPermOrder();
846
			} else {
847
				if(!permOrder.equals(xmlAccessDAO.getPermOrder())) {
848
					throw new PermOrderException("XMLAccessAccess.validateXMLAccessList - " + 
849
						" Conflicting permission orders for document " + xmlAccessDAO.getDocId() +
850
						". Database intervention required ");
851
				}
852
			}
853
		}		
854
	}
855
	
856
	/**
857
	 * Check that only one permOrder exists for each principal. 
858
	 * TODO add check that one of each permType exists as well
859
	 * 
860
	 * @param xmlAccessList
861
	 *            the access dao list
862
	 */
863
	private void validatePrincipalXMLAccessList(Vector<XMLAccessDAO> xmlAccessList) 
864
			throws PermOrderException {
865
		
866
		boolean allowFirst = false;
867
		boolean denyFirst = false;
868
		String docId = null;
869
		
870
		// These vectors will hold all combinations of access DAOs with different permission
871
		// orders and permission types.  
872
		Vector<XMLAccessDAO> allowFirstAllows = new Vector<XMLAccessDAO>();
873
		Vector<XMLAccessDAO> allowFirstDenys = new Vector<XMLAccessDAO>();
874
		Vector<XMLAccessDAO> denyFirstAllows = new Vector<XMLAccessDAO>();
875
		Vector<XMLAccessDAO> denyFirstDenys = new Vector<XMLAccessDAO>();
876
		
877
		// sort the access dao records into the appropriate vector
878
		for(XMLAccessDAO xmlAccessDAO : xmlAccessList) {
879
			if (docId == null) {
880
				docId = xmlAccessDAO.getDocId();
881
			}
882
			if (xmlAccessDAO.getPermOrder().equals(AccessControlInterface.ALLOWFIRST)) {
883
				allowFirst = true;
884
				if (xmlAccessDAO.getPermType().equals(AccessControlInterface.ALLOW)) {
885
					allowFirstAllows.add(xmlAccessDAO);
886
				} else if (xmlAccessDAO.getPermType().equals(AccessControlInterface.DENY)) {
887
					allowFirstDenys.add(xmlAccessDAO);
888
				} else {
889
					throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " + 
890
							" Invalid permission type: " + xmlAccessDAO.getPermType() + " for document " + 
891
							xmlAccessDAO.getDocId() + ". Database intervention required "); 
892
				}
893
			} else if (xmlAccessDAO.getPermOrder().equals(AccessControlInterface.DENYFIRST)) {
894
				denyFirst = true;
895
				if (xmlAccessDAO.getPermType().equals(AccessControlInterface.ALLOW)) {
896
					denyFirstAllows.add(xmlAccessDAO);
897
				} else if (xmlAccessDAO.getPermType().equals(AccessControlInterface.DENY)) {
898
					denyFirstDenys.add(xmlAccessDAO);
899
				} else {
900
					throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " + 
901
							" Invalid permission type: " + xmlAccessDAO.getPermType() + " for document " + 
902
							xmlAccessDAO.getDocId() + ". Database intervention required "); 
903
				}
904
			} else {
905
				throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " + 
906
						" Invalid permission order: " + xmlAccessDAO.getPermOrder() + " for document " + 
907
						xmlAccessDAO.getDocId() + ". Database intervention required "); 
908
			}
909
		}
910
		
911
		// for a given user, there cannot be allowfirst and denyfirst records on the same 
912
		// document
913
		if(allowFirst && denyFirst) {
914
			throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " + 
915
					" Conflicting permission orders for document " + docId +
916
					". Database intervention required ");
917
		}	
918
	}
919
	
920
	/**
921
	 * Populate a job data object with the current row in a resultset
922
	 * 
923
	 * @param resultSet
924
	 *            the result set which is already pointing to the desired row.
925
	 * @return a scheduled job data object
926
	 */
927
	protected XMLAccessDAO populateDAO(ResultSet resultSet) throws SQLException {
928

    
929
		XMLAccessDAO xmlAccessDAO = new XMLAccessDAO();
930
		xmlAccessDAO.setDocId(resultSet.getString("docid"));
931
		xmlAccessDAO.setAccessFileId(resultSet.getString("accessfileid"));
932
		xmlAccessDAO.setPrincipalName(resultSet.getString("principal_name"));
933
		xmlAccessDAO.setPermission(resultSet.getLong("permission"));
934
		xmlAccessDAO.setPermType(resultSet.getString("perm_type"));
935
		xmlAccessDAO.setPermOrder(resultSet.getString("perm_order"));
936
		xmlAccessDAO.setBeginTime(resultSet.getDate("begin_time"));
937
		xmlAccessDAO.setEndTime(resultSet.getDate("end_time"));
938
		xmlAccessDAO.setTicketCount(resultSet.getLong("ticket_count"));
939
		xmlAccessDAO.setSubTreeId(resultSet.getString("subtreeid"));
940
		xmlAccessDAO.setStartNodeId(resultSet.getString("startnodeid"));
941
		xmlAccessDAO.setEndNodeId(resultSet.getString("endnodeid"));
942

    
943
		return xmlAccessDAO;
944
	}
945
	
946
}
(8-8/9)