Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that loads eml-access.xml file containing ACL 
4
 *             for a metadata document into relational DB
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Jivka Bojilova
8
 *
9
 *   '$Author: daigle $'
10
 *     '$Date: 2009-11-03 10:31:34 -0800 (Tue, 03 Nov 2009) $'
11
 * '$Revision: 5099 $'
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.io.IOException;
31
import java.io.StringReader;
32
import java.sql.PreparedStatement;
33
import java.sql.ResultSet;
34
import java.sql.SQLException;
35
import java.util.Vector;
36

    
37
import org.apache.log4j.Logger;
38
import org.xml.sax.ContentHandler;
39
import org.xml.sax.ErrorHandler;
40
import org.xml.sax.InputSource;
41
import org.xml.sax.SAXException;
42
import org.xml.sax.XMLReader;
43
import org.xml.sax.helpers.XMLReaderFactory;
44

    
45
import edu.ucsb.nceas.metacat.DocInfoHandler;
46
import edu.ucsb.nceas.metacat.McdbException;
47
import edu.ucsb.nceas.metacat.PermissionController;
48
import edu.ucsb.nceas.metacat.database.DBConnection;
49
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
50
import edu.ucsb.nceas.metacat.properties.PropertyService;
51
import edu.ucsb.nceas.metacat.shared.AccessException;
52
import edu.ucsb.nceas.metacat.util.DocumentUtil;
53
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
54

    
55

    
56
/** 
57
 * A Class that loads eml-access.xml file containing ACL for a metadata
58
 * document into relational DB. It extends DefaultHandler class to handle
59
 * SAX parsing events when processing the XML stream.
60
 */
61
public class AccessControlForSingleFile implements AccessControlInterface 
62
{
63

    
64
  private String _docId;
65
  private Logger logMetacat = Logger.getLogger(AccessControlForSingleFile.class);
66

    
67
 
68
  /**
69
   * Construct an instance of the AccessControlForSingleFile class.
70
   * @param myAccessNumber  the docid or docid with dev will be controlled
71
   */
72
  public AccessControlForSingleFile(String accessionNumber) throws AccessControlException
73
  {
74
      //Get rid of dev if myaccessNumber has one;
75
	  _docId = DocumentUtil.getDocIdFromString(accessionNumber);
76
      if (_docId == null || _docId.equals(""))
77
      {
78
        throw new AccessControlException("AccessControlForSingleFile() - Accession number " + 
79
        		"can't be null in constructor");
80
      }
81
      
82
      logMetacat.debug("AccessControlForSingleFile() - docid: " + _docId);
83

    
84
  }
85
  
86
  	/**
87
	 * Insert a single access record into the database based on access DAO
88
	 * object
89
	 * 
90
	 * @param xmlAccessDAO
91
	 *            dao object holding info to insert
92
	 */
93
	public void insertPermissions(XMLAccessDAO xmlAccessDAO) throws AccessControlException{
94
		insertPermissions(xmlAccessDAO.getPrincipalName(), xmlAccessDAO.getPermission(), 
95
				xmlAccessDAO.getPermType(), xmlAccessDAO.getPermOrder());
96
	}
97

    
98
	/**
99
	 * Insert a single access record into the database.
100
	 * 
101
	 * @param principalName
102
	 * @param permission
103
	 * @param permType
104
	 * @param permOrder
105
	 * @throws AccessControlException
106
	 */
107
	public void insertPermissions(String principalName, Long permission, String permType, String permOrder) throws AccessControlException {
108
		try {
109
			// The addXMLAccess method will create the permission record if it does not exist.  
110
			// It will bitwise OR to permissions if the principal already has a record for this
111
			// doc id.
112
			XMLAccessAccess xmlAccessAccess = new XMLAccessAccess();
113
			xmlAccessAccess.addXMLAccess(_docId, principalName, new Long(permission), permType, permOrder);
114
		} catch (AccessException ae) {
115
			throw new AccessControlException("AccessControlForSingleFile.insertPermissions - "
116
					+ "DB access error when inserting permissions: " + ae.getMessage());
117
		} 
118
	}
119
  
120
	/**
121
	 * Replace existing permissions with a given block of permissions for this
122
	 * document.
123
	 * 
124
	 * @param accessBlock
125
	 *            the xml access block. This is the same structure as that
126
	 *            returned by the getdocumentinfo action in metacat.
127
	 */
128
	public void insertPermissions(String accessBlock) throws AccessControlException {
129
		try {			
130
			XMLReader parser = null;
131
			DocInfoHandler docInfoHandler = new DocInfoHandler(_docId);
132
			ContentHandler chandler = docInfoHandler;
133

    
134
			// Get an instance of the parser
135
			String parserName = PropertyService.getProperty("xml.saxparser");
136
			parser = XMLReaderFactory.createXMLReader(parserName);
137

    
138
			// Turn off validation
139
			parser.setFeature("http://xml.org/sax/features/validation", false);
140
			parser.setContentHandler((ContentHandler)chandler);
141
			parser.setErrorHandler((ErrorHandler)chandler);
142

    
143
			parser.parse(new InputSource(new StringReader(accessBlock)));
144
			
145
			XMLAccessAccess xmlAccessAccess = new XMLAccessAccess();
146
			xmlAccessAccess.deleteXMLAccessForDoc(_docId);			
147
			
148
	        Vector<XMLAccessDAO> accessControlList = docInfoHandler.getAccessControlList();
149
	        if (accessControlList != null) {
150
	        	for (XMLAccessDAO xmlAccessDAO : accessControlList) {
151
        			insertPermissions(xmlAccessDAO);
152
					logMetacat.debug("AccessControlForSingleFile.insertPermissions - document " + _docId
153
							+ " permissions added to DB");
154
	            }
155
	        }
156
		} catch (PropertyNotFoundException pnfe) {
157
			throw new AccessControlException("AccessControlForSingleFile.insertPermissions - "
158
					+ "property error when replacing permissions: " + pnfe.getMessage());
159
		} catch (AccessException ae) {
160
			throw new AccessControlException("AccessControlForSingleFile.insertPermissions - "
161
					+ "DB access error when replacing permissions: " + ae.getMessage());
162
		} catch (SAXException se) {
163
			throw new AccessControlException("AccessControlForSingleFile.insertPermissions - "
164
					+ "SAX error when replacing permissions: " + se.getMessage());
165
		} catch(IOException ioe) {
166
			throw new AccessControlException("AccessControlForSingleFile.insertPermissions - "
167
					+ "I/O error when replacing permissions: " + ioe.getMessage());
168
		}
169
	}
170
  
171
	/**
172
	 * 
173
	 * @return true if the Access Control for this file already exists in the DB
174
	 * @throws SQLException
175
	 */
176
	public boolean accessControlExists(XMLAccessDAO xmlAccessDAO) throws AccessControlException {
177
		boolean exists = false;
178
		PreparedStatement pstmt = null;
179
		DBConnection conn = null;
180
		int serialNumber = -1;
181
		try {
182
			//check out DBConnection
183
			conn=DBConnectionPool.getDBConnection
184
                               ("AccessControlForSingleFiel.accessControlExists");
185
			serialNumber=conn.getCheckOutSerialNumber();
186
			pstmt = conn.prepareStatement(
187
				"SELECT * FROM xml_access " + 
188
				"WHERE docid = ? " +
189
				"AND principal_name = ? " +
190
				"AND permission = ? " +
191
				"AND perm_type = ? " +
192
				"AND perm_order =? ");
193
     
194
			// Bind the values to the query
195
			pstmt.setString(1, _docId);
196
			pstmt.setString(2, xmlAccessDAO.getPrincipalName());
197
			pstmt.setLong(3, xmlAccessDAO.getPermission());
198
			pstmt.setString(4, xmlAccessDAO.getPermType());
199
			pstmt.setString(5, xmlAccessDAO.getPermOrder());
200
      
201
			pstmt.execute();
202
			ResultSet rs = pstmt.getResultSet();
203
			exists = rs.next();
204
      
205
		} catch (SQLException sqle){
206
			throw new AccessControlException("AccessControlForSingleFile.accessControlExists - SQL error when " +  
207
					"checking if access control exists: " + sqle.getMessage());
208
		} finally {
209
			try {
210
				if(pstmt != null) {
211
					pstmt.close();
212
				}
213
			} catch (SQLException sqle) {
214
				logMetacat.error("AccessControlForSingleFile.accessControlExists - Could not close " + 
215
						"prepared statement: " +sqle.getMessage());
216
			} finally {
217
				DBConnectionPool.returnDBConnection(conn, serialNumber);
218
			}
219
		}
220
    
221
		return exists;  
222
	}
223
  
224
	/**
225
	 * Get Access Control List information for document from db connetion. User
226
	 * or Group should have permissions for reading access control information
227
	 * for a document specified by
228
	 * 
229
	 * @docid.
230
	 * @param docid
231
	 *            document identifier which acl info to get
232
	 * @param user
233
	 *            name of user connected to Metacat system
234
	 * @param groups
235
	 *            names of user's groups to which user belongs
236
	 */
237
	public String getACL(String user, String[] groups)
238
			throws AccessControlException {
239
		StringBuffer output = new StringBuffer();
240
		boolean hasPermission = false;
241

    
242
		try {   
243
			hasPermission = isOwned(_docId, user);
244
			if (!hasPermission) {
245
				PermissionController controller = new PermissionController(_docId);
246
				hasPermission = 
247
					controller.hasPermission(user, groups, READSTRING);
248
			}
249

    
250
			if (hasPermission) {
251
				// Get a list of all access dao objects for this docid
252
				XMLAccessAccess xmlAccessAccess = new XMLAccessAccess();
253
				Vector<XMLAccessDAO> xmlAccessDAOList = xmlAccessAccess.getXMLAccessForDoc(_docId);
254
				output.append(getAccessString(xmlAccessDAOList));
255
			} else {
256
				output.append(getAccessString(new Vector<XMLAccessDAO>()));
257
			}
258

    
259
			return output.toString();
260

    
261
		} catch (SQLException sqle) {
262
			throw new AccessControlException("AccessControlForSingleFile.getACL() - SQL error when " + 
263
					"getting ACL: " + sqle.getMessage());
264
		} catch (AccessException ae) {
265
			throw new AccessControlException("AccessControlForSingleFile.getACL() - DB access error when " + 
266
					"getting ACL: " + ae.getMessage());
267
		} catch (McdbException mcdb) {
268
			throw new AccessControlException("AccessControlForSingleFile.getACL() - MCDB error when " + 
269
					"getting ACL: " + mcdb.getMessage());
270
		}
271
	}
272
	
273
	public String getAccessString() throws AccessControlException {
274
		Vector<XMLAccessDAO> xmlAccessDAOList = null;
275
		
276
		try {
277
			// Get a list of all access dao objects for this docid
278
			XMLAccessAccess xmlAccessAccess = new XMLAccessAccess();
279
			xmlAccessDAOList = xmlAccessAccess.getXMLAccessForDoc(_docId);
280
		} catch (AccessException ae) {
281
				throw new AccessControlException("AccessControlForSingleFile.getAccessString() - DB access error when " + 
282
						"getting access string: " + ae.getMessage());
283
		} 
284
		
285
		return getAccessString(xmlAccessDAOList);
286
	}
287
	
288
	public String getAccessString(Vector<XMLAccessDAO> xmlAccessDAOList) throws AccessControlException {
289
			
290
		StringBuffer output = new StringBuffer();
291
		StringBuffer tmpOutput = new StringBuffer();
292
		StringBuffer allowOutput = new StringBuffer();
293
		StringBuffer denyOutput = new StringBuffer();
294
		
295
		String principal = null;
296
		int permission = -1;
297
		String permOrder = ALLOWFIRST;
298
		String permType = null;
299
		
300
		// We assume that all the records will have the same permission order, so we can just
301
		// grab the perm order from the first one.
302
		if (xmlAccessDAOList.size() > 0) {
303
			permOrder = xmlAccessDAOList.get(0).getPermOrder();
304
		}
305

    
306
		output.append("<access authSystem=\"knb\" order=\"" + permOrder + "\" id=\"" + _docId + "\" scope=\"document\"");
307
		
308
		output.append(">\n");
309
		
310
		if (xmlAccessDAOList.size() > 0) {
311
			// Since there should only be one permission order allowed per document,
312
			// we can just grab the order off of the first xml access dao object
313
			permOrder = xmlAccessDAOList.get(0).getPermOrder();
314
		}
315
		
316
		for (XMLAccessDAO xmlAccessDAO : xmlAccessDAOList) {
317
			principal = xmlAccessDAO.getPrincipalName();
318
			permission = xmlAccessDAO.getPermission().intValue();
319
			permType = xmlAccessDAO.getPermType();
320
			
321
			tmpOutput.append("    <" + permType + ">\n");
322
			tmpOutput.append("      <principal>" + principal + "</principal>\n");
323
	
324
			if ((permission & READ) == READ) {
325
				tmpOutput.append("      <permission>read</permission>\n");
326
			}
327
			if ((permission & WRITE) == WRITE) {
328
				tmpOutput.append("      <permission>write</permission>\n");
329
			}
330
			if ((permission & ALL) == ALL) {
331
				tmpOutput.append("      <permission>all</permission>\n");
332
			}
333
			if ((permission & CHMOD) == CHMOD) {
334
				tmpOutput.append("      <permission>chmod</permission>\n");
335
			}
336

    
337
			tmpOutput.append("    </" + permType + ">\n");
338
			
339
			if (permType.equals(ALLOW)) {
340
				allowOutput.append(tmpOutput);
341
			} else if (permType.equals(DENY)) {
342
				denyOutput.append(tmpOutput);
343
			}
344
			tmpOutput = new StringBuffer();
345
		}
346
		
347
		// This just orders the allow/deny sections based on the permOrder.  Not 
348
		// required, but convenient later when parsing the output.
349
		if (permOrder.equals(ALLOWFIRST)) {
350
			output.append(allowOutput);
351
			output.append(denyOutput);
352
		} else if (permOrder.equals(DENYFIRST)) {
353
			output.append(denyOutput);
354
			output.append(allowOutput);
355
		}
356
		
357
		output.append("</access>");
358
					
359
		return output.toString();
360
	}
361
	
362
	/* Check if @user is owner of @docid from db conn. */
363
	private boolean isOwned(String docid, String user) throws SQLException {
364
		PreparedStatement pstmt = null;
365
		DBConnection conn = null;
366
		int serialNumber = -1;
367
		try {
368
			// check out DBConnection
369
			conn = DBConnectionPool.getDBConnection("AccessControlList.isOwned");
370
			serialNumber = conn.getCheckOutSerialNumber();
371
			pstmt = conn.prepareStatement("SELECT 'x' FROM xml_documents "
372
					+ "WHERE docid = ? " + "AND user_owner = ?");
373
			pstmt.setString(1, docid);
374
			pstmt.setString(2, user);
375
			pstmt.execute();
376
			ResultSet rs = pstmt.getResultSet();
377
			boolean hasRow = rs.next();
378
			return hasRow;
379
		} finally {
380
			try {
381
				if (pstmt != null) {
382
					pstmt.close();
383
				}
384
			} finally {
385
				DBConnectionPool.returnDBConnection(conn, serialNumber);
386
			}
387
		}
388
	}
389

    
390

    
391
	
392
// public String getAccessString() throws AccessControlException {
393
// Vector<XMLAccessDAO> xmlAccessDAOList = null;
394
// try {
395
// XMLAccessAccess xmlAccessAccess = new XMLAccessAccess();
396
//		  xmlAccessDAOList = xmlAccessAccess.getXMLAccessForDoc(docId);
397
//	  } catch (AccessException ae) {
398
//		  throw new AccessControlException("AccessControlForSingleFile.getAccessString - error when getting " + 
399
//				  "access DAO list: " + ae.getMessage());
400
//	  }
401
//	  
402
//	  StringBuffer sb = new StringBuffer();
403
//  
404
//	  for (XMLAccessDAO xmlAccessDAO : xmlAccessDAOList) {
405
//		  sb.append("<access>");
406
//		  
407
//		  sb.append("<permOrder>");
408
//		  sb.append(xmlAccessDAO.getPermOrder());
409
//		  sb.append("</permOrder>");
410
//		  
411
//		  sb.append("<permType>");
412
//		  sb.append(xmlAccessDAO.getPermType());
413
//		  sb.append("</permType>");
414
//		  
415
//		  sb.append("<permission>");
416
//		  sb.append(xmlAccessDAO.getPermission());
417
//		  sb.append("</permission>");
418
//		  
419
//		  sb.append("<principal>");
420
//		  sb.append(xmlAccessDAO.getPrincipalName());
421
//		  sb.append("</principal>");
422
//		  
423
//		  sb.append("</access>");
424
//	  }
425
//  
426
//	  return sb.toString();
427
//	  
428
//  }
429

    
430

    
431
}
(2-2/9)