Project

General

Profile

1 5091 daigle
/**
2
 *  '$RCSfile$'
3 5098 daigle
 *    Purpose: A Class that manages database access of xml access
4 5091 daigle
 *             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 6108 leinfelder
import java.util.List;
34 5091 daigle
import java.util.Vector;
35
36
import org.apache.log4j.Logger;
37
38
import edu.ucsb.nceas.metacat.database.DBConnection;
39
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
40
import edu.ucsb.nceas.metacat.shared.AccessException;
41
import edu.ucsb.nceas.metacat.shared.BaseAccess;
42
43
public class XMLAccessAccess extends BaseAccess {
44
45
	private Logger logMetacat = Logger.getLogger(XMLAccessAccess.class);
46 6744 leinfelder
47 5091 daigle
	// Constructor
48 5108 daigle
	public XMLAccessAccess() throws AccessException {}
49 5091 daigle
50 6122 leinfelder
51 5091 daigle
	/**
52
	 * Get all xml access for a document
53
	 *
54 6122 leinfelder
	 * @param id
55 5091 daigle
	 *            the id of the document
56
	 * @return an xml access DAO list
57
	 */
58 6744 leinfelder
	public Vector<XMLAccessDAO> getXMLAccessForDoc(String guid) throws AccessException {
59 5091 daigle
60
		Vector<XMLAccessDAO> xmlAccessList = new Vector<XMLAccessDAO>();
61
62 6744 leinfelder
		if (guid == null) {
63 5091 daigle
			throw new AccessException("XMLAccessAccess.getXMLAccessForDoc - doc id " +
64
					"must be specified when selecting xml_access record");
65
		}
66
67 5115 daigle
		// first get the xml access from the db and put it into a DAO list
68 5091 daigle
		PreparedStatement pstmt = null;
69 5108 daigle
		DBConnection conn = null;
70
		int serialNumber = -1;
71
		try {
72
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.getXMLAccessForDoc");
73
    		serialNumber = conn.getCheckOutSerialNumber();
74
75 6744 leinfelder
			String sql = "SELECT * FROM xml_access WHERE guid = ?";
76 5091 daigle
			pstmt = conn.prepareStatement(sql);
77
78 6744 leinfelder
			pstmt.setString(1, guid);
79 5091 daigle
80
			String sqlReport = "XMLAccessAccess.getXMLAccessForDoc - SQL: " + sql;
81 6744 leinfelder
			sqlReport += " [" + guid + "]";
82 5091 daigle
83
			logMetacat.info(sqlReport);
84
85
			pstmt.execute();
86
87
			ResultSet resultSet = pstmt.getResultSet();
88
			while (resultSet.next()) {
89
				XMLAccessDAO xmlAccessDAO = populateDAO(resultSet);
90
				xmlAccessList.add(xmlAccessDAO);
91
			}
92 5115 daigle
93
			// make sure permission orders do not conflict in the database
94 5091 daigle
			validateDocXMLAccessList(xmlAccessList);
95
96
			return xmlAccessList;
97
98
		} catch (SQLException sqle) {
99
			throw new AccessException("XMLAccessAccess.getXMLAccessForDoc - SQL error when getting access " +
100 6744 leinfelder
					" for id: " + guid  + " : "  + sqle.getMessage());
101 5091 daigle
		} catch (PermOrderException poe) {
102
			String errorStr = "XMLAccessAccess.getXMLAccessForDoc - Permission order error when getting " +
103 6744 leinfelder
				"access record for doc id: " + guid + " : "  + poe.getMessage();
104 5091 daigle
			logMetacat.error(errorStr);
105
			throw new AccessException(errorStr);
106
		} finally {
107 5108 daigle
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
108 5091 daigle
		}
109
	}
110
111
	/**
112
	 * Get all xml access for a principal for a certain document
113
	 *
114 6122 leinfelder
	 * @param id
115 5091 daigle
	 *            the id of the document
116
	 * @param principalName
117
	 *            the credentials of the principal in the database
118
	 * @return an xml access DAO list
119
	 */
120 6744 leinfelder
	public Vector<XMLAccessDAO> getXMLAccessForPrincipal(String guid, String principalName)
121 5091 daigle
			throws AccessException {
122
123
		Vector<XMLAccessDAO> xmlAccessList = new Vector<XMLAccessDAO>();
124
125 6744 leinfelder
		if (guid == null) {
126 5091 daigle
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - doc id " +
127
					"must be specified when selecting xml_access record");
128
		}
129
		if (principalName == null) {
130
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - doc id " +
131
					"must be specified when selecting xml_access record");
132
		}
133
134 5115 daigle
		// first get the xml access for this principal from the db and put it into a DAO list
135 5091 daigle
		PreparedStatement pstmt = null;
136 5108 daigle
		DBConnection conn = null;
137
		int serialNumber = -1;
138 5091 daigle
		try {
139 5108 daigle
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.getXMLAccessForPrincipal");
140
    		serialNumber = conn.getCheckOutSerialNumber();
141
142 6744 leinfelder
			String sql = "SELECT * FROM xml_access WHERE guid = ? AND principal_name = ?";
143 5091 daigle
			pstmt = conn.prepareStatement(sql);
144
145 6744 leinfelder
			pstmt.setString(1, guid);
146 5091 daigle
			pstmt.setString(2, principalName);
147
148
			String sqlReport = "XMLAccessAccess.getXMLAccessForPrincipal - SQL: " + sql;
149 6744 leinfelder
			sqlReport += " [" + guid + "," + principalName + "]";
150 5091 daigle
151
			logMetacat.info(sqlReport);
152
153
			pstmt.execute();
154
155
			ResultSet resultSet = pstmt.getResultSet();
156
			while (resultSet.next()) {
157
				XMLAccessDAO xmlAccessDAO = populateDAO(resultSet);
158
				xmlAccessList.add(xmlAccessDAO);
159
			}
160
161 5115 daigle
			// make sure permission orders do not conflict in the database
162 5091 daigle
			validatePrincipalXMLAccessList(xmlAccessList);
163
164
			return xmlAccessList;
165
166
		} catch (SQLException sqle) {
167
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - SQL error when getting access " +
168 6744 leinfelder
					" for id: " + guid + ", principal: " + principalName  + " : "  + sqle.getMessage());
169 5091 daigle
		} catch (PermOrderException poe) {
170
			String errorStr = "XMLAccessAccess.getXMLAccessForPrincipal - Permission order error when getting " +
171 6744 leinfelder
				"access record for id: " + guid + ", principal: " + principalName + " : "  + poe.getMessage();
172 5091 daigle
			logMetacat.error(errorStr);
173
			throw new AccessException(errorStr);
174
		} finally {
175 5108 daigle
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
176 5091 daigle
		}
177
	}
178
179
	/**
180 5115 daigle
	 * Get all xml access for a principal/permType/permOrder for a certain document
181 5091 daigle
	 *
182 6744 leinfelder
	 * @param guid
183 5091 daigle
	 *            the id of the document
184
	 * @param principalName
185
	 *            the credentials of the principal in the database
186
	 * @return an xml access DAO list
187
	 */
188 6744 leinfelder
	public Vector<XMLAccessDAO> getXMLAccessForPrincipal(String guid, String principalName, String permType, String permOrder)
189 5091 daigle
			throws AccessException {
190
191
		Vector<XMLAccessDAO> xmlAccessList = new Vector<XMLAccessDAO>();
192
193 6744 leinfelder
		if (guid == null) {
194 5091 daigle
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - doc id " +
195
					"must be specified when selecting xml_access record");
196
		}
197
		if (principalName == null) {
198
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - doc id " +
199
					"must be specified when selecting xml_access record");
200
		}
201
		if (permType == null) {
202
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - permission type " +
203
					"must be specified when selecting xml_access record");
204
		}
205
		if (permOrder == null) {
206
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - permission order " +
207
					"must be specified when selecting xml_access record");
208
		}
209
210 5115 daigle
		// first get the xml access for this principal from the db and put it into a DAO list
211 5091 daigle
		PreparedStatement pstmt = null;
212 5108 daigle
		DBConnection conn = null;
213
		int serialNumber = -1;
214 5091 daigle
		try {
215 5108 daigle
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.getXMLAccessForPrincipal");
216
    		serialNumber = conn.getCheckOutSerialNumber();
217
218 6744 leinfelder
			String sql = "SELECT * FROM xml_access WHERE guid = ? AND principal_name = ? " +
219 5091 daigle
				"AND perm_type = ? AND perm_order = ?";
220
			pstmt = conn.prepareStatement(sql);
221
222 6744 leinfelder
			pstmt.setString(1, guid);
223 5091 daigle
			pstmt.setString(2, principalName);
224
			pstmt.setString(3, permType);
225
			pstmt.setString(4, permOrder);
226
227
			String sqlReport = "XMLAccessAccess.getXMLAccessForPrincipal - SQL: " + sql;
228 6744 leinfelder
			sqlReport += " [" + guid + "," + principalName + "," +  permType + "," + permOrder + "]";
229 5091 daigle
230
			logMetacat.info(sqlReport);
231
232
			pstmt.execute();
233
234
			ResultSet resultSet = pstmt.getResultSet();
235
			while (resultSet.next()) {
236
				XMLAccessDAO xmlAccessDAO = populateDAO(resultSet);
237
				xmlAccessList.add(xmlAccessDAO);
238
			}
239
240
			validatePrincipalXMLAccessList(xmlAccessList);
241
242
			return xmlAccessList;
243
244
		} catch (SQLException sqle) {
245
			throw new AccessException("XMLAccessAccess.getXMLAccessForPrincipal - SQL error when getting access " +
246 6744 leinfelder
					" for id: " + guid + ", principal: " + principalName  + " : "  + sqle.getMessage());
247 5091 daigle
		} catch (PermOrderException poe) {
248
			String errorStr = "XMLAccessAccess.getXMLAccessForPrincipal - Permission order error when getting " +
249 6744 leinfelder
				"access record for id: " + guid + ", principal: " + principalName + " : "  + poe.getMessage();
250 5091 daigle
			logMetacat.error(errorStr);
251
			throw new AccessException(errorStr);
252
		} finally {
253 5108 daigle
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
254 5091 daigle
		}
255
	}
256
257
	/**
258 5098 daigle
	 * Add permissions for a given principal on a given document. If the
259
	 * principal already exists, bitwise OR the permission to the existing
260 5091 daigle
	 * permission and update.
261
	 *
262 6744 leinfelder
	 * @param guid
263 5091 daigle
	 *            document id
264
	 * @param principalName
265
	 *            principal credentials
266
	 * @param permission
267
	 *            permission bitmap
268
	 * @param permType
269
	 *            permission type
270
	 * @param permOrder
271
	 *            permission order
272
	 */
273 6744 leinfelder
	public void addXMLAccess(String guid, String principalName, Long permission, String permType,
274 6017 leinfelder
			String permOrder, String accessFileId, String subTreeId) throws AccessException, PermOrderException {
275 5108 daigle
276 6744 leinfelder
		permOrderConflict(guid, permOrder);
277 5108 daigle
278 5091 daigle
		Vector<XMLAccessDAO> xmlAccessList =
279 6744 leinfelder
			getXMLAccessForPrincipal(guid, principalName, permType, permOrder);
280 5091 daigle
281
		// if more than one record exists for this principal on this document with the same
282
		// access type / access order combination, call cleanup to combine common access and then
283
		// re-retrieve the access list.
284
		if (xmlAccessList.size() == 0) {
285 6744 leinfelder
			insertXMLAccess(guid, principalName, permission, permType, permOrder, accessFileId, subTreeId);
286 5091 daigle
			return;
287
		}
288
289
		if (xmlAccessList.size() > 1) {
290
			cleanupXMLAccessForPrincipal(xmlAccessList);
291 6744 leinfelder
			xmlAccessList = getXMLAccessForPrincipal(guid, principalName, permType, permOrder);
292 5091 daigle
		}
293
294
		if (xmlAccessList.size() == 0) {
295
			throw new AccessException("XMLAccessAccess.addXMLAccess - xml access list is empty when " +
296 6744 leinfelder
				"it shouldn't be for id: " + guid + ", prinicpal name: " + principalName + ", perm type " +
297 5091 daigle
				permType + ", perm order: " + permOrder);
298
		}
299
300
		XMLAccessDAO xmlAccessDAO = xmlAccessList.get(0);
301 5108 daigle
302 5091 daigle
		// if the permission on the xml access dao does not already contain the permission we are
303
		//trying to add, update the access record with the existing permission bitwis OR-ed with our
304
		// new permission
305
		if ((xmlAccessDAO.getPermission() & permission) != permission) {
306 6744 leinfelder
			updateXMLAccessPermission(guid, principalName, xmlAccessDAO.getPermission() | permission);
307 5091 daigle
		}
308
	}
309
310
	/**
311 5098 daigle
	 * Set permissions for a given document. This means first removing all access control for the
312
	 * document and then adding the given rules.
313
	 *
314 6122 leinfelder
	 * @param id
315 5091 daigle
	 *            document id
316 5098 daigle
	 * @param xmlAccessList
317
	 *            list of xml access dao objects that hold new access for the document
318
	 */
319 6744 leinfelder
	public void replaceAccess(String guid, List<XMLAccessDAO> xmlAccessList) throws AccessException {
320
		deleteXMLAccessForDoc(guid);
321 5098 daigle
322 6744 leinfelder
		insertAccess(guid, xmlAccessList);
323
	}
324
325
	/**
326
	 * Set permissions for a given document. This means first removing all access control for the
327
	 * document and then adding the given rules.
328
	 *
329
	 * @param id
330
	 *            document id
331
	 * @param xmlAccessList
332
	 *            list of xml access dao objects that hold new access for the document
333
	 */
334
	public void insertAccess(String guid, List<XMLAccessDAO> xmlAccessList) throws AccessException {
335
336 5098 daigle
		// if more than one record exists for this principal on this document with the same
337
		// access type / access order combination, call cleanup to combine common access and then
338
		// re-retrieve the access list.
339
		for(XMLAccessDAO xmlAccessDAO : xmlAccessList) {
340 6744 leinfelder
			insertXMLAccess(guid, xmlAccessDAO.getPrincipalName(), xmlAccessDAO.getPermission(),
341 6017 leinfelder
					xmlAccessDAO.getPermType(), xmlAccessDAO.getPermOrder(), xmlAccessDAO.getAccessFileId(), xmlAccessDAO.getSubTreeId());
342 5098 daigle
		}
343
	}
344
345
	/**
346
	 * Insert an xml access record.  It is assumed that the checks have already been made to
347
	 * make sure the principal does not already have an access record for this document.  If
348
	 * one does already exist, that record should be updated and this insert not called.
349
	 *
350 6122 leinfelder
	 * @param id
351 5098 daigle
	 *            document id
352 5091 daigle
	 * @param principal
353
	 *            principal credentials
354
	 * @param permission
355
	 *            permission bitmap
356
	 * @param permType
357
	 *            permission type
358
	 * @param permOrder
359
	 *            permission order
360
	 */
361 6744 leinfelder
	private void insertXMLAccess(String guid, String principalName, Long permission, String permType,
362 6017 leinfelder
			String permOrder, String accessFileId, String subTreeId) throws AccessException {
363 5734 berkley
	    //System.out.println("permission in insertXMLAccess: " + permission);
364
	    try
365
	    {
366
	        if(permission == -1)
367
	        {
368
	            throw new Exception("Permission is -1 in XMLAccessAccess.insertXMLAccess().");
369
	        }
370
	    }
371
	    catch(Exception e)
372
	    {
373
	        e.printStackTrace();
374
	        logMetacat.warn(e.getMessage());
375
	    }
376
377 6744 leinfelder
		if (guid == null) {
378 6122 leinfelder
			throw new AccessException("XMLAccessAccess.insertXMLAccess - id is required when " +
379 5091 daigle
					"inserting XML access record");
380
		}
381
		if (principalName == null) {
382
			throw new AccessException("XMLAccessAccess.insertXMLAccess - principal is required when " +
383
					"inserting XML access record");
384
		}
385
		if (permission == null) {
386
			throw new AccessException("XMLAccessAccess.insertXMLAccess - permission is required when " +
387
					"inserting XML access record");
388
		}
389
		if (permType == null) {
390
			throw new AccessException("XMLAccessAccess.insertXMLAccess - permType is required when " +
391
					"inserting XML access record");
392
		}
393
		if (permOrder == null) {
394
			permOrder = AccessControlInterface.ALLOWFIRST;
395
		}
396
397
	    PreparedStatement pstmt = null;
398
		DBConnection conn = null;
399
		int serialNumber = -1;
400
		try {
401
			// check out DBConnection
402
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.insertXMLAccess");
403
			serialNumber = conn.getCheckOutSerialNumber();
404 5120 daigle
405 5091 daigle
			String sql = "INSERT INTO xml_access " +
406 6744 leinfelder
				"(guid, principal_name, permission, perm_type, perm_order, accessfileid, subtreeid ) " +
407
				"VALUES (?,?,?,?,?,?,?)";
408 5091 daigle
			pstmt = conn.prepareStatement(sql);
409
410 6422 leinfelder
411 5091 daigle
			// Bind the values to the query
412 6744 leinfelder
			pstmt.setString(1, guid);
413
			pstmt.setString(2, principalName);
414
			pstmt.setLong(3, permission);
415
			pstmt.setString(4, permType);
416
			pstmt.setString(5, permOrder);
417
			pstmt.setString(6, accessFileId);
418
			pstmt.setString(7, subTreeId);
419 5091 daigle
420
			String sqlReport = "XMLAccessAccess.insertXMLAccess - SQL: " + sql;
421 6744 leinfelder
			sqlReport += " [" + guid + "," + principalName + "," +  permission + "," +  permType + "," + permOrder + "]";
422 5091 daigle
423
			logMetacat.info(sqlReport);
424
425
			pstmt.execute();
426
		} catch (SQLException sqle) {
427
			throw new AccessException("XMLAccessAccess.insertXMLAccess - SQL error when inserting"
428 6744 leinfelder
					+ "xml access permissions for id: " + guid + ", principal: " +
429 5091 daigle
					principalName + ":" + sqle.getMessage());
430
		} finally {
431 5108 daigle
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
432 5091 daigle
		}
433
	}
434
435
	/**
436 5098 daigle
	 * Update existing xml access permissions in the db.  The permission value should be the combined
437
	 * value of pre-existing permissions plus new permissions.
438
	 *
439 6744 leinfelder
	 * @param guid
440 5091 daigle
	 *            document id
441
	 * @param principalName
442
	 *            principal credentials
443
	 * @param permission
444
	 *            permission bitmap
445
	 */
446 6744 leinfelder
	private void updateXMLAccessPermission(String guid, String principalName, Long permission)
447 5091 daigle
			throws AccessException {
448 6744 leinfelder
		if (guid == null) {
449 6122 leinfelder
			throw new AccessException("XMLAccessAccess.updateXMLAccessPermission - id is required when " +
450 5091 daigle
					"updating XML access record");
451
		}
452
		if (principalName == null) {
453
			throw new AccessException("XMLAccessAccess.updateXMLAccessPermission - principal is required when " +
454
					"updating XML access record");
455
		}
456
		if (permission == null) {
457
			throw new AccessException("XMLAccessAccess.updateXMLAccessPermission - permission is required when " +
458
					"updating XML access record");
459
		}
460
461
	    PreparedStatement pstmt = null;
462
		DBConnection conn = null;
463
		int serialNumber = -1;
464
		try {
465
			// check out DBConnection
466
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.updateXMLAccessPermission");
467
			serialNumber = conn.getCheckOutSerialNumber();
468 5120 daigle
469 5091 daigle
			String sql = "UPDATE xml_access SET permission = ?" +
470 6744 leinfelder
				"WHERE guid = ? AND principal_name = ?";
471 5091 daigle
			pstmt = conn.prepareStatement(sql);
472
473
			// Bind the values to the query
474
			pstmt.setLong(1, permission);
475 6744 leinfelder
			pstmt.setString(2, guid);
476 5091 daigle
			pstmt.setString(3, principalName);
477
478
			String sqlReport = "XMLAccessAccess.updateXMLAccessPermission - SQL: " + sql;
479 6744 leinfelder
			sqlReport += " [" + permission + "," + guid + "," + principalName + "]";
480 5091 daigle
481
			logMetacat.info(sqlReport);
482
483
			pstmt.execute();
484
		} catch (SQLException sqle) {
485
			throw new AccessException("XMLAccessAccess.updateXMLAccessPermission - SQL error when updating"
486 6744 leinfelder
					+ "xml access permissions for id: " + guid + ", principal: " +
487 5091 daigle
					principalName + ":" + sqle.getMessage());
488
		} finally {
489 5108 daigle
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
490 5091 daigle
		}
491
492
	}
493
494
	/**
495 5098 daigle
	 * Remove xml access.  This modifies the access in the database for a principal
496 5091 daigle
	 * for a given document.  If the provided permission is exactly the same as what
497 5098 daigle
	 * the principal has, the record is deleted from the database.
498
	 *
499 6744 leinfelder
	 * @param guid
500 5091 daigle
	 *            document id
501
	 * @param principalName
502
	 *            principal credentials
503
	 */
504 6744 leinfelder
	public void removeXMLAccessForPrincipal(String guid, String principalName, Long permission) throws AccessException {
505
		if (guid == null) {
506 6122 leinfelder
			throw new AccessException("XMLAccessAccess.removeXMLAccessForPrincipal - id is required when " +
507 5091 daigle
					"removing XML access");
508
		}
509
		if (principalName == null) {
510
			throw new AccessException("XMLAccessAccess.removeXMLAccessForPrincipal - principal is required when " +
511
					"deleting XML access");
512
		}
513
		if (permission == null) {
514
			throw new AccessException("XMLAccessAccess.removeXMLAccessForPrincipal - permission is required when " +
515
					"updating XML access");
516
		}
517
518 6744 leinfelder
		Vector<XMLAccessDAO> xmlAccessList = getXMLAccessForPrincipal(guid, principalName);
519 5091 daigle
		if (xmlAccessList.size() == 0) {
520
			logMetacat.warn("XMLAccessAccess.removeXMLAccessForPrincipal - attempting to remove access when no " +
521 6744 leinfelder
				"access record exists for id: " + guid + ", principal: " + principalName);
522 5091 daigle
		} else {
523
			long permissionMask = 0;
524
			for (XMLAccessDAO xmlAccessDAO : xmlAccessList) {
525
				permissionMask |= xmlAccessDAO.getPermission();
526
			}
527
			permissionMask |= permission;
528
529
			// in this case, the only existing permissions are the ones we want to remove, so
530
			// delete the record(s) for this principal on this document
531
			if ((permissionMask & permission) == permission) {
532 6744 leinfelder
				deleteXMLAccessForPrincipal(guid, principalName);
533 5091 daigle
			}
534
535
			if (xmlAccessList.size() > 1) {
536
537
			} else {
538 6744 leinfelder
				updateXMLAccessPermission(guid, principalName, permission);
539 5091 daigle
			}
540
		}
541
542
	}
543
544
	/**
545 5098 daigle
	 * Delete xml access.  This removes all access records from the database for a given document
546
	 *
547 6122 leinfelder
	 * @param id
548 5098 daigle
	 *            document id
549
	 */
550 6744 leinfelder
	public void deleteXMLAccessForDoc(String guid) throws AccessException {
551
		if (guid == null) {
552 6122 leinfelder
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - id is required when " +
553 5098 daigle
					"deleting XML access record");
554
		}
555
556
	    PreparedStatement pstmt = null;
557
		DBConnection conn = null;
558
		int serialNumber = -1;
559
		try {
560 6536 leinfelder
561 5098 daigle
			// check out DBConnection
562
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.deleteXMLAccessForDoc");
563 5120 daigle
    		serialNumber = conn.getCheckOutSerialNumber();
564
565 6744 leinfelder
			String sql = "DELETE FROM xml_access WHERE guid = ?";
566 5098 daigle
			pstmt = conn.prepareStatement(sql);
567
568
			// Bind the values to the query
569 6744 leinfelder
			pstmt.setString(1, guid);
570 5098 daigle
571
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForDoc - SQL: " + sql;
572 6744 leinfelder
			sqlReport += " [" + guid + "]";
573 5098 daigle
574
			logMetacat.info(sqlReport);
575
576
			pstmt.execute();
577
		} catch (SQLException sqle) {
578
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForDoc - SQL error when deleting"
579 6744 leinfelder
					+ "xml access permissions for id: " + guid + ":" + sqle.getMessage());
580 5098 daigle
		} finally {
581 5108 daigle
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
582 5098 daigle
		}
583
	}
584
585
	/**
586 5091 daigle
	 * Delete xml access.  This removes all access records from the database for a principal
587
	 * for a given document
588 5098 daigle
	 *
589 6744 leinfelder
	 * @param guid
590 5091 daigle
	 *            document id
591
	 * @param principal
592
	 *            principal credentials
593
	 */
594 6744 leinfelder
	private void deleteXMLAccessForPrincipal(String guid, String principalName) throws AccessException {
595
		if (guid == null) {
596 6122 leinfelder
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - id is required when " +
597 5091 daigle
					"deleting XML access record");
598
		}
599
		if (principalName == null) {
600
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - principal is required when " +
601
					"deleting XML access record");
602
		}
603
604
	    PreparedStatement pstmt = null;
605
		DBConnection conn = null;
606
		int serialNumber = -1;
607
		try {
608
			// check out DBConnection
609
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.deleteXMLAccessForPrincipal");
610 5120 daigle
    		serialNumber = conn.getCheckOutSerialNumber();
611
612 6744 leinfelder
			String sql = "DELETE FROM xml_access WHERE guid = ? AND principal_name = ?";
613 5091 daigle
			pstmt = conn.prepareStatement(sql);
614
615
			// Bind the values to the query
616 6744 leinfelder
			pstmt.setString(1, guid);
617 5091 daigle
			pstmt.setString(2, principalName);
618
619
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForPrincipal - SQL: " + sql;
620 6744 leinfelder
			sqlReport += " [" + guid + "," + principalName + "]";
621 5091 daigle
622
			logMetacat.info(sqlReport);
623
624
			pstmt.execute();
625
		} catch (SQLException sqle) {
626
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - SQL error when deleting"
627 6744 leinfelder
					+ "xml access permissions for id: " + guid + ", principal: " +
628 5091 daigle
					principalName + ":" + sqle.getMessage());
629
		} finally {
630 5108 daigle
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
631 5091 daigle
		}
632
	}
633
634
	/**
635 6744 leinfelder
	 * Delete xml access.  This removes all access records from the database for a principal
636
	 * for a given document
637
	 *
638
	 * @param guid
639
	 *            document id
640
	 * @param principal
641
	 *            principal credentials
642
	 */
643
	public void deleteXMLAccessForDoc(String guid, String permType) throws AccessException {
644
		if (guid == null) {
645
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForDoc - id is required when " +
646
					"deleting XML access record");
647
		}
648
		if (permType == null) {
649
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForDoc - permType is required when " +
650
					"deleting XML access record");
651
		}
652
653
	    PreparedStatement pstmt = null;
654
		DBConnection conn = null;
655
		int serialNumber = -1;
656
		try {
657
			// check out DBConnection
658
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.deleteXMLAccessForDoc");
659
    		serialNumber = conn.getCheckOutSerialNumber();
660
661
			String sql = "DELETE FROM xml_access WHERE guid = ? AND perm_type = ?";
662
			pstmt = conn.prepareStatement(sql);
663
664
			// Bind the values to the query
665
			pstmt.setString(1, guid);
666
			pstmt.setString(2, permType);
667
668
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForDoc - SQL: " + sql;
669
			sqlReport += " [" + guid + "," + permType + "]";
670
671
			logMetacat.info(sqlReport);
672
673
			pstmt.execute();
674
		} catch (SQLException sqle) {
675
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForDoc - SQL error when deleting"
676
					+ "xml access permissions for id: " + guid + ", permType: " +
677
					permType + ":" + sqle.getMessage());
678
		} finally {
679
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
680
		}
681
	}
682
683
	/**
684 5115 daigle
	 * Checks to see if there is a permission order conflict for a given document.  Each
685
	 * document is only allowed to have a single permission order
686
	 *
687 6744 leinfelder
	 * @param guid
688 5091 daigle
	 *            document id
689
	 * @param principal
690
	 *            principal credentials
691
	 */
692 6744 leinfelder
	private void permOrderConflict(String guid, String permOrder) throws AccessException, PermOrderException {
693
		if (guid == null) {
694 6122 leinfelder
			throw new AccessException("XMLAccessAccess.permOrderConflict - id is required when " +
695 5108 daigle
					"determining perm order conflict");
696
		}
697
		if (permOrder == null) {
698
			throw new AccessException("XMLAccessAccess.permOrderConflict - perm order is required when " +
699
					"determining perm order conflict");
700
		}
701
702
	    PreparedStatement pstmt = null;
703
		DBConnection conn = null;
704
		int serialNumber = -1;
705
		try {
706
			// check out DBConnection
707
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.permOrderConflict");
708 5120 daigle
    		serialNumber = conn.getCheckOutSerialNumber();
709
710 6744 leinfelder
			String sql = "SELECT * FROM xml_access WHERE guid = ? AND perm_order != ?";
711 5108 daigle
			pstmt = conn.prepareStatement(sql);
712
713
			// Bind the values to the query
714 6744 leinfelder
			pstmt.setString(1, guid);
715 5108 daigle
			pstmt.setString(2, permOrder);
716
717
			String sqlReport = "XMLAccessAccess.permOrderConflict - SQL: " + sql;
718 6744 leinfelder
			sqlReport += " [" + guid + "," + permOrder + "]";
719 5108 daigle
720
			logMetacat.info(sqlReport);
721
722
			pstmt.execute();
723
724
			ResultSet resultSet = pstmt.getResultSet();
725
			if (resultSet.next()) {
726
				throw new PermOrderException("XMLAccessAccess.addXMLAccess - cannot add permission " +
727 6744 leinfelder
					"record for id: " + guid + "with permOrder: " + permOrder + " due to permOrder conflict");
728 5108 daigle
			}
729
		} catch (SQLException sqle) {
730
			throw new AccessException("XMLAccessAccess.permOrderConflict - SQL error when checking"
731 6744 leinfelder
					+ "for perm order conflict on: " + guid + ":" + sqle.getMessage());
732 5108 daigle
		} finally {
733
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
734
		}
735
736
	}
737
738
	/**
739
	 * Delete xml access.  This removes all access records from the database for a principal
740
	 * for a given document, perm type and perm order
741 5115 daigle
	 *
742 6744 leinfelder
	 * @param guid
743 5108 daigle
	 *            document id
744
	 * @param principal
745
	 *            principal credentials
746
	 */
747 6744 leinfelder
	private void deleteXMLAccessForPrincipal(String guid, String principalName, String permType, String permOrder) throws AccessException {
748
		if (guid == null) {
749 6122 leinfelder
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - id is required when " +
750 5091 daigle
					"deleting XML access record");
751
		}
752
		if (principalName == null) {
753
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - principal is required when " +
754
					"deleting XML access record");
755
		}
756
		if (permType == null) {
757
			throw new AccessException(
758
					"XMLAccessAccess.deleteXMLAccessForPrincipal - perm type is required when "
759
							+ "deleting XML access record");
760
		}
761
		if (permOrder == null) {
762
			throw new AccessException(
763
					"XMLAccessAccess.deleteXMLAccessForPrincipal - perm order is required when "
764
							+ "deleting XML access record");
765
		}
766
767
	    PreparedStatement pstmt = null;
768
		DBConnection conn = null;
769
		int serialNumber = -1;
770
		try {
771
			// check out DBConnection
772
			conn = DBConnectionPool.getDBConnection("XMLAccessAccess.deleteXMLAccessForPrincipal");
773 5120 daigle
    		serialNumber = conn.getCheckOutSerialNumber();
774
775 6744 leinfelder
			String sql = "DELETE FROM xml_access WHERE guid = ? AND principal_name = ? " +
776 5108 daigle
				"AND perm_type = ? AND perm_order = ?";
777 5091 daigle
			pstmt = conn.prepareStatement(sql);
778
779
			// Bind the values to the query
780 6744 leinfelder
			pstmt.setString(1, guid);
781 5091 daigle
			pstmt.setString(2, principalName);
782
			pstmt.setString(3, permType);
783
			pstmt.setString(4, permOrder);
784
785
			String sqlReport = "XMLAccessAccess.deleteXMLAccessForPrincipal - SQL: " + sql;
786 6744 leinfelder
			sqlReport += " [" + guid + "," + principalName + "," + permType + "," + permOrder + "]";
787 5091 daigle
788
			logMetacat.info(sqlReport);
789
790
			pstmt.execute();
791
		} catch (SQLException sqle) {
792
			throw new AccessException("XMLAccessAccess.deleteXMLAccessForPrincipal - SQL error when deleting"
793 6744 leinfelder
					+ "xml access permissions for id: " + guid + ", principal: " +
794 5091 daigle
					principalName + ":" + sqle.getMessage());
795
		} finally {
796 5108 daigle
			closeDBObjects(pstmt, conn, serialNumber, logMetacat);
797 5091 daigle
		}
798
799
	}
800 5098 daigle
801
	/**
802
	 * Make sure that only one record exists per principal/permType/document. If
803
	 * more than one record exists, delete the existing records, consolidate the
804
	 * permissions insert the new record.
805
	 *
806 5115 daigle
	 * @param xmlAccessList the access dao list
807 5098 daigle
	 */
808 5091 daigle
	private void cleanupXMLAccessForPrincipal(Vector<XMLAccessDAO> xmlAccessList) throws AccessException{
809
810 5098 daigle
		int numAllowRecords = 0;
811
		int numDenyRecords = 0;
812
		long allowPermissionMask = 0;
813
		long denyPermissionMask = 0;
814 6744 leinfelder
		String guid = null;
815 5091 daigle
		String principalName = null;
816
		String permType = null;
817
		String permOrder = null;
818 6017 leinfelder
		// TODO: handle these fields
819
		String accessFileId = null;
820
		String subTreeId = null;
821 5091 daigle
822
823
		// iterate through the list of access dao objects and bttwise or the permissions.  Most
824
		// of this is just doing some error checking to make sure each record is valid.
825
		for (XMLAccessDAO xmlAccessDAO : xmlAccessList) {
826 6744 leinfelder
			String daoId = xmlAccessDAO.getGuid();
827
			if (guid == null) {
828
				guid = daoId;
829 5091 daigle
			} else {
830 6744 leinfelder
				if (!guid.equals(daoId)) {
831 5091 daigle
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " +
832 6744 leinfelder
							" Conflicting ids " + daoId + " and " + guid);
833 5091 daigle
				}
834
			}
835
			if (principalName == null) {
836
				principalName = xmlAccessDAO.getPrincipalName();
837
			} else {
838
				if (!principalName.equals(xmlAccessDAO.getPrincipalName())) {
839
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " +
840
							" Conflicting prinicpal names " + xmlAccessDAO.getPrincipalName() +
841
							" and principalName " + principalName);
842
				}
843
			}
844
			if (permType == null) {
845
				permType = xmlAccessDAO.getPermType();
846
			} else {
847
				if (!permType.equals(xmlAccessDAO.getPermType())) {
848
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " +
849 6122 leinfelder
							" Conflicting permission orders for document " + daoId +
850 5091 daigle
							"principalName " + principalName + ". Database intervention required ");
851
				}
852
			}
853
			if (permOrder == null) {
854
				permOrder = xmlAccessDAO.getPermOrder();
855
			} else {
856
				if (!permOrder.equals(xmlAccessDAO.getPermOrder())) {
857
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " +
858 6122 leinfelder
							" Conflicting permission types for document " + daoId +
859 5091 daigle
							"principalName " + principalName + ". Database intervention required ");
860
				}
861
			}
862
			if (permType == null) {
863
				permType = xmlAccessDAO.getPermType();
864
			} else {
865
				if (!permType.equals(xmlAccessDAO.getPermType())) {
866
					throw new AccessException("XMLAccessAccess.cleanupXMLAccessForPrincipal - " +
867 6122 leinfelder
							" Conflicting permission orders for document " + daoId +
868 5091 daigle
							"principalName " + principalName + ". Database intervention required ");
869
				}
870
			}
871 5098 daigle
			if (permType.equals(AccessControlInterface.ALLOW)) {
872
				numAllowRecords++;
873
				allowPermissionMask |= xmlAccessDAO.getPermission();
874
			} else if (permType.equals(AccessControlInterface.DENY)) {
875
				numDenyRecords++;
876
				denyPermissionMask |= xmlAccessDAO.getPermission();
877
			}
878 6017 leinfelder
			if (accessFileId == null) {
879
				accessFileId = xmlAccessDAO.getAccessFileId();
880
			}
881
			if (subTreeId == null) {
882
				subTreeId = xmlAccessDAO.getSubTreeId();
883
			}
884 5091 daigle
		}
885
886 5098 daigle
		// if there was more than one allow record, remove all allow records for this user on this doc
887
		// with this perm type and perm order then insert a single record
888
		if (numAllowRecords > 1) {
889 6744 leinfelder
			deleteXMLAccessForPrincipal(guid, principalName, AccessControlInterface.ALLOW, permOrder);
890
			insertXMLAccess(guid, principalName, allowPermissionMask, AccessControlInterface.ALLOW, permOrder, accessFileId, subTreeId);
891 5098 daigle
		}
892
		// if there was more than one deny record, remove all deny records for this user on this doc
893
		// with this perm type and perm order then insert a single record
894
		if (numDenyRecords > 1) {
895 6744 leinfelder
			deleteXMLAccessForPrincipal(guid, principalName, AccessControlInterface.DENY, permOrder);
896
			insertXMLAccess(guid, principalName, denyPermissionMask, AccessControlInterface.DENY, permOrder, accessFileId, subTreeId);
897 5098 daigle
		}
898 5091 daigle
	}
899
900 5098 daigle
	/**
901 5115 daigle
	 * Make sure for a given list of access DAOs that only one perm order
902
	 * exists. It is assumed that all the DAOs are for the same doc
903 5098 daigle
	 *
904
	 * @param xmlAccessList
905 5115 daigle
	 *            the access dao list
906 5098 daigle
	 */
907 5091 daigle
	private void validateDocXMLAccessList(Vector<XMLAccessDAO> xmlAccessList) throws PermOrderException {
908
		String permOrder = null;
909
		for(XMLAccessDAO xmlAccessDAO : xmlAccessList) {
910 6744 leinfelder
			String daoId = xmlAccessDAO.getGuid();
911 5091 daigle
			if (permOrder == null) {
912
				permOrder = xmlAccessDAO.getPermOrder();
913
			} else {
914
				if(!permOrder.equals(xmlAccessDAO.getPermOrder())) {
915
					throw new PermOrderException("XMLAccessAccess.validateXMLAccessList - " +
916 6122 leinfelder
						" Conflicting permission orders for document " + daoId +
917 5091 daigle
						". Database intervention required ");
918
				}
919
			}
920
		}
921
	}
922
923 5115 daigle
	/**
924
	 * Check that only one permOrder exists for each principal.
925
	 * TODO add check that one of each permType exists as well
926
	 *
927
	 * @param xmlAccessList
928
	 *            the access dao list
929
	 */
930 5091 daigle
	private void validatePrincipalXMLAccessList(Vector<XMLAccessDAO> xmlAccessList)
931
			throws PermOrderException {
932
933
		boolean allowFirst = false;
934
		boolean denyFirst = false;
935 6744 leinfelder
		String guid = null;
936 5091 daigle
937
		// These vectors will hold all combinations of access DAOs with different permission
938
		// orders and permission types.
939
		Vector<XMLAccessDAO> allowFirstAllows = new Vector<XMLAccessDAO>();
940
		Vector<XMLAccessDAO> allowFirstDenys = new Vector<XMLAccessDAO>();
941
		Vector<XMLAccessDAO> denyFirstAllows = new Vector<XMLAccessDAO>();
942
		Vector<XMLAccessDAO> denyFirstDenys = new Vector<XMLAccessDAO>();
943
944
		// sort the access dao records into the appropriate vector
945
		for(XMLAccessDAO xmlAccessDAO : xmlAccessList) {
946 6744 leinfelder
			String daoId = xmlAccessDAO.getGuid();
947
			if (guid == null) {
948
				guid = daoId;
949 5091 daigle
			}
950
			if (xmlAccessDAO.getPermOrder().equals(AccessControlInterface.ALLOWFIRST)) {
951
				allowFirst = true;
952
				if (xmlAccessDAO.getPermType().equals(AccessControlInterface.ALLOW)) {
953
					allowFirstAllows.add(xmlAccessDAO);
954
				} else if (xmlAccessDAO.getPermType().equals(AccessControlInterface.DENY)) {
955
					allowFirstDenys.add(xmlAccessDAO);
956
				} else {
957
					throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " +
958
							" Invalid permission type: " + xmlAccessDAO.getPermType() + " for document " +
959 6122 leinfelder
							daoId + ". Database intervention required ");
960 5091 daigle
				}
961
			} else if (xmlAccessDAO.getPermOrder().equals(AccessControlInterface.DENYFIRST)) {
962
				denyFirst = true;
963
				if (xmlAccessDAO.getPermType().equals(AccessControlInterface.ALLOW)) {
964
					denyFirstAllows.add(xmlAccessDAO);
965
				} else if (xmlAccessDAO.getPermType().equals(AccessControlInterface.DENY)) {
966
					denyFirstDenys.add(xmlAccessDAO);
967
				} else {
968
					throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " +
969
							" Invalid permission type: " + xmlAccessDAO.getPermType() + " for document " +
970 6122 leinfelder
							daoId + ". Database intervention required ");
971 5091 daigle
				}
972
			} else {
973
				throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " +
974
						" Invalid permission order: " + xmlAccessDAO.getPermOrder() + " for document " +
975 6122 leinfelder
						daoId + ". Database intervention required ");
976 5091 daigle
			}
977
		}
978
979
		// for a given user, there cannot be allowfirst and denyfirst records on the same
980
		// document
981
		if(allowFirst && denyFirst) {
982
			throw new PermOrderException("XMLAccessAccess.validatePrincipalXMLAccessList - " +
983 6744 leinfelder
					" Conflicting permission orders for document " + guid +
984 5091 daigle
					". Database intervention required ");
985
		}
986
	}
987
988
	/**
989
	 * Populate a job data object with the current row in a resultset
990
	 *
991
	 * @param resultSet
992
	 *            the result set which is already pointing to the desired row.
993
	 * @return a scheduled job data object
994
	 */
995
	protected XMLAccessDAO populateDAO(ResultSet resultSet) throws SQLException {
996
997
		XMLAccessDAO xmlAccessDAO = new XMLAccessDAO();
998 6744 leinfelder
		xmlAccessDAO.setGuid(resultSet.getString("guid"));
999 5091 daigle
		xmlAccessDAO.setAccessFileId(resultSet.getString("accessfileid"));
1000
		xmlAccessDAO.setPrincipalName(resultSet.getString("principal_name"));
1001
		xmlAccessDAO.setPermission(resultSet.getLong("permission"));
1002
		xmlAccessDAO.setPermType(resultSet.getString("perm_type"));
1003
		xmlAccessDAO.setPermOrder(resultSet.getString("perm_order"));
1004
		xmlAccessDAO.setBeginTime(resultSet.getDate("begin_time"));
1005
		xmlAccessDAO.setEndTime(resultSet.getDate("end_time"));
1006
		xmlAccessDAO.setTicketCount(resultSet.getLong("ticket_count"));
1007
		xmlAccessDAO.setSubTreeId(resultSet.getString("subtreeid"));
1008
		xmlAccessDAO.setStartNodeId(resultSet.getString("startnodeid"));
1009
		xmlAccessDAO.setEndNodeId(resultSet.getString("endnodeid"));
1010
1011
		return xmlAccessDAO;
1012
	}
1013
1014
}