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
	private static String DOCID = "docid";
48
	
49
	private static String GUID = "guid";
50

    
51
	private String idAttribute = DOCID;
52
	
53
	// Constructor
54
	public XMLAccessAccess() throws AccessException {}
55
	
56
	public XMLAccessAccess(boolean useGuid) {
57
		if (useGuid) {
58
			idAttribute = GUID;
59
		}
60
	}
61

    
62
	/**
63
	 * Get all xml access for a document
64
	 * 
65
	 * @param id
66
	 *            the id of the document
67
	 * @return an xml access DAO list
68
	 */ 
69
	public Vector<XMLAccessDAO> getXMLAccessForDoc(String id) throws AccessException {
70

    
71
		Vector<XMLAccessDAO> xmlAccessList = new Vector<XMLAccessDAO>();
72
		
73
		if (id == null) {
74
			throw new AccessException("XMLAccessAccess.getXMLAccessForDoc - doc id " + 
75
					"must be specified when selecting xml_access record");
76
		}
77
			
78
		// first get the xml access from the db and put it into a DAO list
79
		PreparedStatement pstmt = null;
80
		DBConnection conn = null;
81
		int serialNumber = -1;
82
		try {			
83
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.getXMLAccessForDoc");
84
    		serialNumber = conn.getCheckOutSerialNumber();
85

    
86
			String sql = "SELECT * FROM xml_access WHERE " + idAttribute + " = ?";
87
			pstmt = conn.prepareStatement(sql);
88

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

    
134
		Vector<XMLAccessDAO> xmlAccessList = new Vector<XMLAccessDAO>();
135
		
136
		if (id == null) { 
137
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - doc id " + 
138
					"must be specified when selecting xml_access record");
139
		}
140
		if (principalName == null) { 
141
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - doc id " + 
142
					"must be specified when selecting xml_access record");
143
		}
144
			
145
		// first get the xml access for this principal from the db and put it into a DAO list
146
		PreparedStatement pstmt = null;
147
		DBConnection conn = null;
148
		int serialNumber = -1;
149
		try {
150
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.getXMLAccessForPrincipal");
151
    		serialNumber = conn.getCheckOutSerialNumber();
152
			
153
			String sql = "SELECT * FROM xml_access WHERE " + idAttribute + " = ? AND principal_name = ?";
154
			pstmt = conn.prepareStatement(sql);
155

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

    
202
		Vector<XMLAccessDAO> xmlAccessList = new Vector<XMLAccessDAO>();
203
		
204
		if (id == null) { 
205
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - doc id " + 
206
					"must be specified when selecting xml_access record");
207
		}
208
		if (principalName == null) { 
209
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - doc id " + 
210
					"must be specified when selecting xml_access record");
211
		}
212
		if (permType == null) { 
213
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - permission type " + 
214
					"must be specified when selecting xml_access record");
215
		}
216
		if (permOrder == null) { 
217
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - permission order " + 
218
					"must be specified when selecting xml_access record");
219
		}
220
					
221
		// first get the xml access for this principal from the db and put it into a DAO list
222
		PreparedStatement pstmt = null;
223
		DBConnection conn = null;
224
		int serialNumber = -1;
225
		try {
226
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.getXMLAccessForPrincipal");
227
    		serialNumber = conn.getCheckOutSerialNumber();
228
    		
229
			String sql = "SELECT * FROM xml_access WHERE " + idAttribute + " = ? AND principal_name = ? " + 
230
				"AND perm_type = ? AND perm_order = ?";
231
			pstmt = conn.prepareStatement(sql);
232

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

    
407
			// Bind the values to the query
408
			pstmt.setString(1, id);
409
			pstmt.setString(2, principalName);
410
			pstmt.setLong(3, permission);
411
			pstmt.setString(4, permType);
412
			pstmt.setString(5, permOrder);
413
			pstmt.setString(6, accessFileId);
414
			pstmt.setString(7, subTreeId);
415
			
416
			String sqlReport = "XMLAccessAccess.insertXMLAccess - SQL: " + sql;
417
			sqlReport += " [" + id + "," + principalName + "," +  permission + "," +  permType + "," + permOrder + "]";
418
			
419
			logMetacat.info(sqlReport);
420

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

    
469
			// Bind the values to the query
470
			pstmt.setLong(1, permission);
471
			pstmt.setString(2, id);
472
			pstmt.setString(3, principalName);
473
			
474
			String sqlReport = "XMLAccessAccess.updateXMLAccessPermission - SQL: " + sql;
475
			sqlReport += " [" + permission + "," + id + "," + principalName + "]";
476
			
477
			logMetacat.info(sqlReport);
478

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

    
563
			// Bind the values to the query
564
			pstmt.setString(1, id);
565

    
566
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForDoc - SQL: " + sql;
567
			sqlReport += " [" + id + "]";
568
			
569
			logMetacat.info(sqlReport);
570

    
571
			pstmt.execute();
572
		} catch (SQLException sqle) {
573
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForDoc - SQL error when deleting"
574
					+ "xml access permissions for id: " + id + ":" + sqle.getMessage());
575
		} finally {
576
			closeDBObjects(pstmt, conn, serialNumber, logMetacat); 
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 id
585
	 *            document id
586
	 * @param principal
587
	 *            principal credentials
588
	 */
589
	private void deleteXMLAccessForPrincipal(String id, String principalName) throws AccessException {
590
		if (id == null) {
591
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - id 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
    		serialNumber = conn.getCheckOutSerialNumber();
606
    		
607
			String sql = "DELETE FROM xml_access WHERE " + idAttribute + " = ? AND principal_name = ?";
608
			pstmt = conn.prepareStatement(sql);
609

    
610
			// Bind the values to the query
611
			pstmt.setString(1, id);
612
			pstmt.setString(2, principalName);
613

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

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

    
659
			// Bind the values to the query
660
			pstmt.setString(1, id);
661
			pstmt.setString(2, permOrder);
662
			
663
			String sqlReport = "XMLAccessAccess.permOrderConflict - SQL: " + sql;
664
			sqlReport += " [" + id + "," + permOrder + "]";
665
			
666
			logMetacat.info(sqlReport);
667

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

    
725
			// Bind the values to the query
726
			pstmt.setString(1, id);
727
			pstmt.setString(2, principalName);
728
			pstmt.setString(3, permType);
729
			pstmt.setString(4, permOrder);
730
			
731
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForPrincipal - SQL: " + sql;
732
			sqlReport += " [" + id + "," + principalName + "," + permType + "," + permOrder + "]";
733
			
734
			logMetacat.info(sqlReport);
735

    
736
			pstmt.execute();
737
		} catch (SQLException sqle) {
738
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - SQL error when deleting"
739
					+ "xml access permissions for id: " + id + ", principal: " + 
740
					principalName + ":" + sqle.getMessage());
741
		} finally {
742
			closeDBObjects(pstmt, conn, serialNumber, logMetacat); 
743
		}
744
	   
745
	}
746

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

    
952
		XMLAccessDAO xmlAccessDAO = new XMLAccessDAO();
953
		xmlAccessDAO.setDocId(resultSet.getString(idAttribute));
954
		xmlAccessDAO.setAccessFileId(resultSet.getString("accessfileid"));
955
		xmlAccessDAO.setPrincipalName(resultSet.getString("principal_name"));
956
		xmlAccessDAO.setPermission(resultSet.getLong("permission"));
957
		xmlAccessDAO.setPermType(resultSet.getString("perm_type"));
958
		xmlAccessDAO.setPermOrder(resultSet.getString("perm_order"));
959
		xmlAccessDAO.setBeginTime(resultSet.getDate("begin_time"));
960
		xmlAccessDAO.setEndTime(resultSet.getDate("end_time"));
961
		xmlAccessDAO.setTicketCount(resultSet.getLong("ticket_count"));
962
		xmlAccessDAO.setSubTreeId(resultSet.getString("subtreeid"));
963
		xmlAccessDAO.setStartNodeId(resultSet.getString("startnodeid"));
964
		xmlAccessDAO.setEndNodeId(resultSet.getString("endnodeid"));
965

    
966
		return xmlAccessDAO;
967
	}
968
	
969
}
(8-8/9)