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 xml access from the db and put it into a DAO list
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
			// make sure permission orders do not conflict in the database
92
			validateDocXMLAccessList(xmlAccessList);
93
			
94
			return xmlAccessList;
95
			
96
		} catch (SQLException sqle) {
97
			throw new AccessException("XMLAccessAccess.getXMLAccessForDoc - SQL error when getting access " + 
98
					" for doc id: " + docId  + " : "  + sqle.getMessage());
99
		} catch (PermOrderException poe) {
100
			String errorStr = "XMLAccessAccess.getXMLAccessForDoc - Permission order error when getting " + 
101
				"access record for doc id: " + docId + " : "  + poe.getMessage();
102
			logMetacat.error(errorStr);
103
			throw new AccessException(errorStr);
104
		} finally {
105
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
106
		}		
107
	}
108
	
109
	/**
110
	 * Get all xml access for a principal for a certain document
111
	 * 
112
	 * @param docId
113
	 *            the id of the document
114
	 * @param principalName
115
	 *            the credentials of the principal in the database
116
	 * @return an xml access DAO list
117
	 */ 
118
	public Vector<XMLAccessDAO> getXMLAccessForPrincipal(String docId, String principalName) 
119
			throws AccessException {
120

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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