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
import edu.ucsb.nceas.utilities.access.AccessControlInterface;
43
import edu.ucsb.nceas.utilities.access.XMLAccessDAO;
44

    
45
public class XMLAccessAccess extends BaseAccess {
46
	
47
	private Logger logMetacat = Logger.getLogger(XMLAccessAccess.class);
48
			
49
	// Constructor
50
	public XMLAccessAccess() throws AccessException {}
51
	
52

    
53
	/**
54
	 * Get all xml access for a document
55
	 * 
56
	 * @param id
57
	 *            the id of the document
58
	 * @return an xml access DAO list
59
	 */ 
60
	public Vector<XMLAccessDAO> getXMLAccessForDoc(String guid) throws AccessException {
61

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

    
77
			String sql = "SELECT * FROM xml_access WHERE guid = ?";
78
			pstmt = conn.prepareStatement(sql);
79

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

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

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

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

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

    
412
			
413
			// Bind the values to the query
414
			pstmt.setString(1, guid);
415
			pstmt.setString(2, principalName);
416
			pstmt.setLong(3, permission);
417
			pstmt.setString(4, permType);
418
			pstmt.setString(5, permOrder);
419
			pstmt.setString(6, accessFileId);
420
			pstmt.setString(7, subTreeId);
421
			
422
			String sqlReport = "XMLAccessAccess.insertXMLAccess - SQL: " + sql;
423
			sqlReport += " [" + guid + "," + principalName + "," +  permission + "," +  permType + "," + permOrder + "]";
424
			
425
			logMetacat.info(sqlReport);
426

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

    
475
			// Bind the values to the query
476
			pstmt.setLong(1, permission);
477
			pstmt.setString(2, guid);
478
			pstmt.setString(3, principalName);
479
			
480
			String sqlReport = "XMLAccessAccess.updateXMLAccessPermission - SQL: " + sql;
481
			sqlReport += " [" + permission + "," + guid + "," + principalName + "]";
482
			
483
			logMetacat.info(sqlReport);
484

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

    
570
			// Bind the values to the query
571
			pstmt.setString(1, guid);
572

    
573
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForDoc - SQL: " + sql;
574
			sqlReport += " [" + guid + "]";
575
			
576
			logMetacat.info(sqlReport);
577

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

    
617
			// Bind the values to the query
618
			pstmt.setString(1, guid);
619
			pstmt.setString(2, principalName);
620

    
621
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForPrincipal - SQL: " + sql;
622
			sqlReport += " [" + guid + "," + principalName + "]";
623
			
624
			logMetacat.info(sqlReport);
625

    
626
			pstmt.execute();
627
		} catch (SQLException sqle) {
628
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - SQL error when deleting"
629
					+ "xml access permissions for id: " + guid + ", principal: " + 
630
					principalName + ":" + sqle.getMessage());
631
		} finally {
632
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
633
		}	   
634
	}
635
	
636
	/**
637
	 * Delete xml access.  This removes all access records from the database for a principal 
638
	 * for a given document
639
	 * 
640
	 * @param guid
641
	 *            document id
642
	 * @param principal
643
	 *            principal credentials
644
	 */
645
	public void deleteXMLAccessForDoc(String guid, String permType) throws AccessException {
646
		if (guid == null) {
647
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForDoc - id is required when " + 
648
					"deleting XML access record");
649
		}
650
		if (permType == null) {
651
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForDoc - permType is required when " + 
652
					"deleting XML access record");
653
		}
654
		
655
	    PreparedStatement pstmt = null;
656
		DBConnection conn = null;
657
		int serialNumber = -1;
658
		try {
659
			// check out DBConnection
660
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.deleteXMLAccessForDoc");
661
    		serialNumber = conn.getCheckOutSerialNumber();
662
    		
663
			String sql = "DELETE FROM xml_access WHERE guid = ? AND perm_type = ?";
664
			pstmt = conn.prepareStatement(sql);
665

    
666
			// Bind the values to the query
667
			pstmt.setString(1, guid);
668
			pstmt.setString(2, permType);
669

    
670
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForDoc - SQL: " + sql;
671
			sqlReport += " [" + guid + "," + permType + "]";
672
			
673
			logMetacat.info(sqlReport);
674

    
675
			pstmt.execute();
676
		} catch (SQLException sqle) {
677
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForDoc - SQL error when deleting"
678
					+ "xml access permissions for id: " + guid + ", permType: " + 
679
					permType + ":" + sqle.getMessage());
680
		} finally {
681
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
682
		}	   
683
	}
684
	
685
	/**
686
	 * Checks to see if there is a permission order conflict for a given document.  Each 
687
	 * document is only allowed to have a single permission order
688
	 * 
689
	 * @param guid
690
	 *            document id
691
	 * @param principal
692
	 *            principal credentials
693
	 */
694
	private void permOrderConflict(String guid, String permOrder) throws AccessException, PermOrderException {
695
		if (guid == null) {
696
			throw new AccessException("XMLAccessAccess.permOrderConflict - id is required when " + 
697
					"determining perm order conflict");
698
		}
699
		if (permOrder == null) {
700
			throw new AccessException("XMLAccessAccess.permOrderConflict - perm order is required when " + 
701
					"determining perm order conflict");
702
		}
703
		
704
	    PreparedStatement pstmt = null;
705
		DBConnection conn = null;
706
		int serialNumber = -1;
707
		try {
708
			// check out DBConnection
709
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.permOrderConflict");
710
    		serialNumber = conn.getCheckOutSerialNumber();
711
    		
712
			String sql = "SELECT * FROM xml_access WHERE guid = ? AND perm_order != ?";
713
			pstmt = conn.prepareStatement(sql);
714

    
715
			// Bind the values to the query
716
			pstmt.setString(1, guid);
717
			pstmt.setString(2, permOrder);
718
			
719
			String sqlReport = "XMLAccessAccess.permOrderConflict - SQL: " + sql;
720
			sqlReport += " [" + guid + "," + permOrder + "]";
721
			
722
			logMetacat.info(sqlReport);
723

    
724
			pstmt.execute();
725
			
726
			ResultSet resultSet = pstmt.getResultSet();
727
			if (resultSet.next()) {			
728
				throw new PermOrderException("XMLAccessAccess.addXMLAccess - cannot add permission " + 
729
					"record for id: " + guid + "with permOrder: " + permOrder + " due to permOrder conflict");
730
			}
731
		} catch (SQLException sqle) {
732
			throw new AccessException("XMLAccessAccess.permOrderConflict - SQL error when checking"
733
					+ "for perm order conflict on: " + guid + ":" + sqle.getMessage());
734
		} finally {
735
			closeDBObjects(pstmt, conn, serialNumber, logMetacat); 
736
		}
737
	   
738
	}
739
	
740
	/**
741
	 * Delete xml access.  This removes all access records from the database for a principal 
742
	 * for a given document, perm type and perm order
743
	 * 
744
	 * @param guid
745
	 *            document id
746
	 * @param principal
747
	 *            principal credentials
748
	 */
749
	private void deleteXMLAccessForPrincipal(String guid, String principalName, String permType, String permOrder) throws AccessException {
750
		if (guid == null) {
751
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - id is required when " + 
752
					"deleting XML access record");
753
		}
754
		if (principalName == null) {
755
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - principal is required when " + 
756
					"deleting XML access record");
757
		}
758
		if (permType == null) {
759
			throw new AccessException(
760
					"XMLAccessAccess.deleteXMLAccessForPrincipal - perm type is required when "
761
							+ "deleting XML access record");
762
		}
763
		if (permOrder == null) {
764
			throw new AccessException(
765
					"XMLAccessAccess.deleteXMLAccessForPrincipal - perm order is required when "
766
							+ "deleting XML access record");
767
		}
768
		
769
	    PreparedStatement pstmt = null;
770
		DBConnection conn = null;
771
		int serialNumber = -1;
772
		try {
773
			// check out DBConnection
774
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.deleteXMLAccessForPrincipal");
775
    		serialNumber = conn.getCheckOutSerialNumber();
776
    		
777
			String sql = "DELETE FROM xml_access WHERE guid = ? AND principal_name = ? " +
778
				"AND perm_type = ? AND perm_order = ?";
779
			pstmt = conn.prepareStatement(sql);
780

    
781
			// Bind the values to the query
782
			pstmt.setString(1, guid);
783
			pstmt.setString(2, principalName);
784
			pstmt.setString(3, permType);
785
			pstmt.setString(4, permOrder);
786
			
787
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForPrincipal - SQL: " + sql;
788
			sqlReport += " [" + guid + "," + principalName + "," + permType + "," + permOrder + "]";
789
			
790
			logMetacat.info(sqlReport);
791

    
792
			pstmt.execute();
793
		} catch (SQLException sqle) {
794
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - SQL error when deleting"
795
					+ "xml access permissions for id: " + guid + ", principal: " + 
796
					principalName + ":" + sqle.getMessage());
797
		} finally {
798
			closeDBObjects(pstmt, conn, serialNumber, logMetacat); 
799
		}
800
	   
801
	}
802

    
803
	/**
804
	 * Make sure that only one record exists per principal/permType/document. If
805
	 * more than one record exists, delete the existing records, consolidate the
806
	 * permissions insert the new record.
807
	 * 
808
	 * @param xmlAccessList the access dao list
809
	 */
810
	private void cleanupXMLAccessForPrincipal(Vector<XMLAccessDAO> xmlAccessList) throws AccessException{
811
		
812
		int numAllowRecords = 0;
813
		int numDenyRecords = 0;
814
		long allowPermissionMask = 0;
815
		long denyPermissionMask = 0;
816
		String guid = null;
817
		String principalName = null;
818
		String permType = null;
819
		String permOrder = null;
820
		// TODO: handle these fields
821
		String accessFileId = null;
822
		String subTreeId = null;
823
	
824
		
825
		// iterate through the list of access dao objects and bttwise or the permissions.  Most
826
		// of this is just doing some error checking to make sure each record is valid.
827
		for (XMLAccessDAO xmlAccessDAO : xmlAccessList) {
828
			String daoId = xmlAccessDAO.getGuid();
829
			if (guid == null) {
830
				guid = daoId;
831
			} else {
832
				if (!guid.equals(daoId)) {
833
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
834
							" Conflicting ids " + daoId + " and " + guid);
835
				}
836
			}
837
			if (principalName == null) {
838
				principalName = xmlAccessDAO.getPrincipalName();
839
			} else {
840
				if (!principalName.equals(xmlAccessDAO.getPrincipalName())) {
841
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
842
							" Conflicting prinicpal names " + xmlAccessDAO.getPrincipalName() +
843
							" and principalName " + principalName);
844
				}
845
			}
846
			if (permType == null) {
847
				permType = xmlAccessDAO.getPermType();
848
			} else {
849
				if (!permType.equals(xmlAccessDAO.getPermType())) {
850
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
851
							" Conflicting permission orders for document " + daoId +
852
							"principalName " + principalName + ". Database intervention required ");
853
				}
854
			}
855
			if (permOrder == null) {
856
				permOrder = xmlAccessDAO.getPermOrder();
857
			} else {
858
				if (!permOrder.equals(xmlAccessDAO.getPermOrder())) {
859
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
860
							" Conflicting permission types for document " + daoId +
861
							"principalName " + principalName + ". Database intervention required ");
862
				}
863
			}
864
			if (permType == null) {
865
				permType = xmlAccessDAO.getPermType();
866
			} else {
867
				if (!permType.equals(xmlAccessDAO.getPermType())) {
868
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " + 
869
							" Conflicting permission orders for document " + daoId +
870
							"principalName " + principalName + ". Database intervention required ");
871
				}
872
			}
873
			if (permType.equals(AccessControlInterface.ALLOW)) {
874
				numAllowRecords++;
875
				allowPermissionMask |= xmlAccessDAO.getPermission();
876
			} else if (permType.equals(AccessControlInterface.DENY)) {
877
				numDenyRecords++;
878
				denyPermissionMask |= xmlAccessDAO.getPermission();
879
			}
880
			if (accessFileId == null) {
881
				accessFileId = xmlAccessDAO.getAccessFileId();
882
			}
883
			if (subTreeId == null) {
884
				subTreeId = xmlAccessDAO.getSubTreeId();
885
			}
886
		}
887
		
888
		// if there was more than one allow record, remove all allow records for this user on this doc 
889
		// with this perm type and perm order then insert a single record 
890
		if (numAllowRecords > 1) {
891
			deleteXMLAccessForPrincipal(guid, principalName, AccessControlInterface.ALLOW, permOrder);
892
			insertXMLAccess(guid, principalName, allowPermissionMask, AccessControlInterface.ALLOW, permOrder, accessFileId, subTreeId);
893
		}
894
		// if there was more than one deny record, remove all deny records for this user on this doc 
895
		// with this perm type and perm order then insert a single record 
896
		if (numDenyRecords > 1) {
897
			deleteXMLAccessForPrincipal(guid, principalName, AccessControlInterface.DENY, permOrder);
898
			insertXMLAccess(guid, principalName, denyPermissionMask, AccessControlInterface.DENY, permOrder, accessFileId, subTreeId);
899
		}
900
	}
901
	
902
	/**
903
	 * Make sure for a given list of access DAOs that only one perm order
904
	 * exists. It is assumed that all the DAOs are for the same doc
905
	 * 
906
	 * @param xmlAccessList
907
	 *            the access dao list
908
	 */
909
	private void validateDocXMLAccessList(Vector<XMLAccessDAO> xmlAccessList) throws PermOrderException {
910
		String permOrder = null;
911
		for(XMLAccessDAO xmlAccessDAO : xmlAccessList) {
912
			String daoId = xmlAccessDAO.getGuid();
913
			if (permOrder == null) {
914
				permOrder = xmlAccessDAO.getPermOrder();
915
			} else {
916
				if(!permOrder.equals(xmlAccessDAO.getPermOrder())) {
917
					throw new PermOrderException("XMLAccessAccess.validateXMLAccessList - " + 
918
						" Conflicting permission orders for document " + daoId +
919
						". Database intervention required ");
920
				}
921
			}
922
		}		
923
	}
924
	
925
	/**
926
	 * Check that only one permOrder exists for each principal. 
927
	 * TODO add check that one of each permType exists as well
928
	 * 
929
	 * @param xmlAccessList
930
	 *            the access dao list
931
	 */
932
	private void validatePrincipalXMLAccessList(Vector<XMLAccessDAO> xmlAccessList) 
933
			throws PermOrderException {
934
		
935
		boolean allowFirst = false;
936
		boolean denyFirst = false;
937
		String guid = null;
938
		
939
		// These vectors will hold all combinations of access DAOs with different permission
940
		// orders and permission types.  
941
		Vector<XMLAccessDAO> allowFirstAllows = new Vector<XMLAccessDAO>();
942
		Vector<XMLAccessDAO> allowFirstDenys = new Vector<XMLAccessDAO>();
943
		Vector<XMLAccessDAO> denyFirstAllows = new Vector<XMLAccessDAO>();
944
		Vector<XMLAccessDAO> denyFirstDenys = new Vector<XMLAccessDAO>();
945
		
946
		// sort the access dao records into the appropriate vector
947
		for(XMLAccessDAO xmlAccessDAO : xmlAccessList) {
948
			String daoId = xmlAccessDAO.getGuid();
949
			if (guid == null) {
950
				guid = daoId;
951
			}
952
			if (xmlAccessDAO.getPermOrder().equals(AccessControlInterface.ALLOWFIRST)) {
953
				allowFirst = true;
954
				if (xmlAccessDAO.getPermType().equals(AccessControlInterface.ALLOW)) {
955
					allowFirstAllows.add(xmlAccessDAO);
956
				} else if (xmlAccessDAO.getPermType().equals(AccessControlInterface.DENY)) {
957
					allowFirstDenys.add(xmlAccessDAO);
958
				} else {
959
					throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " + 
960
							" Invalid permission type: " + xmlAccessDAO.getPermType() + " for document " + 
961
							daoId + ". Database intervention required "); 
962
				}
963
			} else if (xmlAccessDAO.getPermOrder().equals(AccessControlInterface.DENYFIRST)) {
964
				denyFirst = true;
965
				if (xmlAccessDAO.getPermType().equals(AccessControlInterface.ALLOW)) {
966
					denyFirstAllows.add(xmlAccessDAO);
967
				} else if (xmlAccessDAO.getPermType().equals(AccessControlInterface.DENY)) {
968
					denyFirstDenys.add(xmlAccessDAO);
969
				} else {
970
					throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " + 
971
							" Invalid permission type: " + xmlAccessDAO.getPermType() + " for document " + 
972
							daoId + ". Database intervention required "); 
973
				}
974
			} else {
975
				throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " + 
976
						" Invalid permission order: " + xmlAccessDAO.getPermOrder() + " for document " + 
977
						daoId + ". Database intervention required "); 
978
			}
979
		}
980
		
981
		// for a given user, there cannot be allowfirst and denyfirst records on the same 
982
		// document
983
		if(allowFirst && denyFirst) {
984
			throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " + 
985
					" Conflicting permission orders for document " + guid +
986
					". Database intervention required ");
987
		}	
988
	}
989
	
990
	/**
991
	 * Populate a job data object with the current row in a resultset
992
	 * 
993
	 * @param resultSet
994
	 *            the result set which is already pointing to the desired row.
995
	 * @return a scheduled job data object
996
	 */
997
	protected XMLAccessDAO populateDAO(ResultSet resultSet) throws SQLException {
998

    
999
		XMLAccessDAO xmlAccessDAO = new XMLAccessDAO();
1000
		xmlAccessDAO.setGuid(resultSet.getString("guid"));
1001
		xmlAccessDAO.setAccessFileId(resultSet.getString("accessfileid"));
1002
		xmlAccessDAO.setPrincipalName(resultSet.getString("principal_name"));
1003
		xmlAccessDAO.setPermission(resultSet.getLong("permission"));
1004
		xmlAccessDAO.setPermType(resultSet.getString("perm_type"));
1005
		xmlAccessDAO.setPermOrder(resultSet.getString("perm_order"));
1006
		xmlAccessDAO.setBeginTime(resultSet.getDate("begin_time"));
1007
		xmlAccessDAO.setEndTime(resultSet.getDate("end_time"));
1008
		xmlAccessDAO.setTicketCount(resultSet.getLong("ticket_count"));
1009
		xmlAccessDAO.setSubTreeId(resultSet.getString("subtreeid"));
1010
		xmlAccessDAO.setStartNodeId(resultSet.getString("startnodeid"));
1011
		xmlAccessDAO.setEndNodeId(resultSet.getString("endnodeid"));
1012

    
1013
		return xmlAccessDAO;
1014
	}
1015
	
1016
}
(7-7/7)