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
	
49
	/**
50
	 * Get all xml access for a document
51
	 * 
52
	 * @param docId
53
	 *            the id of the document
54
	 * @return an xml access DAO list
55
	 */ 
56
	public Vector<XMLAccessDAO> getXMLAccessForDoc(String docId) throws AccessException {
57

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

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

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

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

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

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

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

    
377
			// Bind the values to the query
378
			pstmt.setString(1, docId);
379
			pstmt.setString(2, principalName);
380
			pstmt.setLong(3, permission);
381
			pstmt.setString(4, permType);
382
			pstmt.setString(5, permOrder);
383
			
384
			String sqlReport = "XMLAccessAccess.insertXMLAccess - SQL: " + sql;
385
			sqlReport += " [" + docId + "," + principalName + "," +  permission + "," +  permType + "," + permOrder + "]";
386
			
387
			logMetacat.info(sqlReport);
388

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

    
436
			// Bind the values to the query
437
			pstmt.setLong(1, permission);
438
			pstmt.setString(2, docId);
439
			pstmt.setString(3, principalName);
440
			
441
			String sqlReport = "XMLAccessAccess.updateXMLAccessPermission - SQL: " + sql;
442
			sqlReport += " [" + permission + "," + docId + "," + principalName + "]";
443
			
444
			logMetacat.info(sqlReport);
445

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

    
528
			// Bind the values to the query
529
			pstmt.setString(1, docId);
530

    
531
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForDoc - SQL: " + sql;
532
			sqlReport += " [" + docId + "]";
533
			
534
			logMetacat.info(sqlReport);
535

    
536
			pstmt.execute();
537
		} catch (SQLException sqle) {
538
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForDoc - SQL error when deleting"
539
					+ "xml access permissions for doc id: " + docId + ":" + sqle.getMessage());
540
		} finally {
541
			closeDBObjects(pstmt, conn, serialNumber, logMetacat); 
542
		}	   
543
	}
544
	
545
	/**
546
	 * Delete xml access.  This removes all access records from the database for a principal 
547
	 * for a given document
548
	 * 
549
	 * @param docId
550
	 *            document id
551
	 * @param principal
552
	 *            principal credentials
553
	 */
554
	private void deleteXMLAccessForPrincipal(String docId, String principalName) throws AccessException {
555
		if (docId == null) {
556
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - docid is required when " + 
557
					"deleting XML access record");
558
		}
559
		if (principalName == null) {
560
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - principal is required when " + 
561
					"deleting XML access record");
562
		}
563
		
564
	    PreparedStatement pstmt = null;
565
		DBConnection conn = null;
566
		int serialNumber = -1;
567
		try {
568
			// check out DBConnection
569
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.deleteXMLAccessForPrincipal");
570
			String sql = "DELETE FROM xml_access WHERE docid = ? AND principal_name = ?";
571
			pstmt = conn.prepareStatement(sql);
572

    
573
			// Bind the values to the query
574
			pstmt.setString(1, docId);
575
			pstmt.setString(2, principalName);
576

    
577
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForPrincipal - SQL: " + sql;
578
			sqlReport += " [" + docId + "," + principalName + "]";
579
			
580
			logMetacat.info(sqlReport);
581

    
582
			pstmt.execute();
583
		} catch (SQLException sqle) {
584
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - SQL error when deleting"
585
					+ "xml access permissions for doc id: " + docId + ", principal: " + 
586
					principalName + ":" + sqle.getMessage());
587
		} finally {
588
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
589
		}	   
590
	}
591
	
592
	/**
593
	 * Delete xml access.  This removes all access records from the database for a principal 
594
	 * for a given document, perm type and perm order
595
	 * @param docId
596
	 *            document id
597
	 * @param principal
598
	 *            principal credentials
599
	 */
600
	private void permOrderConflict(String docId, String permOrder) throws AccessException, PermOrderException {
601
		if (docId == null) {
602
			throw new AccessException("XMLAccessAccess.permOrderConflict - docid is required when " + 
603
					"determining perm order conflict");
604
		}
605
		if (permOrder == null) {
606
			throw new AccessException("XMLAccessAccess.permOrderConflict - perm order is required when " + 
607
					"determining perm order conflict");
608
		}
609
		
610
	    PreparedStatement pstmt = null;
611
		DBConnection conn = null;
612
		int serialNumber = -1;
613
		try {
614
			// check out DBConnection
615
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.permOrderConflict");
616
			String sql = "SELECT * FROM xml_access WHERE docid = ? AND perm_order != ?";
617
			pstmt = conn.prepareStatement(sql);
618

    
619
			// Bind the values to the query
620
			pstmt.setString(1, docId);
621
			pstmt.setString(2, permOrder);
622
			
623
			String sqlReport = "XMLAccessAccess.permOrderConflict - SQL: " + sql;
624
			sqlReport += " [" + docId + "," + permOrder + "]";
625
			
626
			logMetacat.info(sqlReport);
627

    
628
			pstmt.execute();
629
			
630
			ResultSet resultSet = pstmt.getResultSet();
631
			if (resultSet.next()) {			
632
				throw new PermOrderException("XMLAccessAccess.addXMLAccess - cannot add permission " + 
633
					"record for doc id: " + docId + "with permOrder: " + permOrder + " due to permOrder conflict");
634
			}
635
		} catch (SQLException sqle) {
636
			throw new AccessException("XMLAccessAccess.permOrderConflict - SQL error when checking"
637
					+ "for perm order conflict on: " + docId + ":" + sqle.getMessage());
638
		} finally {
639
			closeDBObjects(pstmt, conn, serialNumber, logMetacat); 
640
		}
641
	   
642
	}
643
	
644
	/**
645
	 * Delete xml access.  This removes all access records from the database for a principal 
646
	 * for a given document, perm type and perm order
647
	 * @param docId
648
	 *            document id
649
	 * @param principal
650
	 *            principal credentials
651
	 */
652
	private void deleteXMLAccessForPrincipal(String docId, String principalName, String permType, String permOrder) throws AccessException {
653
		if (docId == null) {
654
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - docid is required when " + 
655
					"deleting XML access record");
656
		}
657
		if (principalName == null) {
658
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - principal is required when " + 
659
					"deleting XML access record");
660
		}
661
		if (permType == null) {
662
			throw new AccessException(
663
					"XMLAccessAccess.deleteXMLAccessForPrincipal - perm type is required when "
664
							+ "deleting XML access record");
665
		}
666
		if (permOrder == null) {
667
			throw new AccessException(
668
					"XMLAccessAccess.deleteXMLAccessForPrincipal - perm order is required when "
669
							+ "deleting XML access record");
670
		}
671
		
672
	    PreparedStatement pstmt = null;
673
		DBConnection conn = null;
674
		int serialNumber = -1;
675
		try {
676
			// check out DBConnection
677
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.deleteXMLAccessForPrincipal");
678
			String sql = "DELETE FROM xml_access WHERE docid = ? AND principal_name = ? " +
679
				"AND perm_type = ? AND perm_order = ?";
680
			pstmt = conn.prepareStatement(sql);
681

    
682
			// Bind the values to the query
683
			pstmt.setString(1, docId);
684
			pstmt.setString(2, principalName);
685
			pstmt.setString(3, permType);
686
			pstmt.setString(4, permOrder);
687
			
688
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForPrincipal - SQL: " + sql;
689
			sqlReport += " [" + docId + "," + principalName + "," + permType + "," + permOrder + "]";
690
			
691
			logMetacat.info(sqlReport);
692

    
693
			pstmt.execute();
694
		} catch (SQLException sqle) {
695
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - SQL error when deleting"
696
					+ "xml access permissions for doc id: " + docId + ", principal: " + 
697
					principalName + ":" + sqle.getMessage());
698
		} finally {
699
			closeDBObjects(pstmt, conn, serialNumber, logMetacat); 
700
		}
701
	   
702
	}
703

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

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

    
895
		return xmlAccessDAO;
896
	}
897
	
898
}
(8-8/9)