View Javadoc
1   package org.apache.fulcrum.security.torque;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  import java.sql.Connection;
22  import java.util.List;
23  
24  import org.apache.avalon.framework.configuration.Configuration;
25  import org.apache.avalon.framework.configuration.ConfigurationException;
26  import org.apache.fulcrum.security.entity.Permission;
27  import org.apache.fulcrum.security.spi.AbstractPermissionManager;
28  import org.apache.fulcrum.security.torque.security.TorqueAbstractSecurityEntity;
29  import org.apache.fulcrum.security.util.DataBackendException;
30  import org.apache.fulcrum.security.util.EntityExistsException;
31  import org.apache.fulcrum.security.util.PermissionSet;
32  import org.apache.fulcrum.security.util.UnknownEntityException;
33  import org.apache.torque.NoRowsException;
34  import org.apache.torque.TooManyRowsException;
35  import org.apache.torque.TorqueException;
36  import org.apache.torque.util.Transaction;
37  
38  /**
39   * This implementation persists to a database via Torque.
40   *
41   * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
42   * @version $Id:$
43   */
44  public abstract class TorqueAbstractPermissionManager extends AbstractPermissionManager {
45  
46  	/** Serial version */
47  	private static final long serialVersionUID = 194503017446833485L;
48  
49  	// no lazyLoading
50  
51  	/**
52  	 * Avalon Service lifecycle method
53  	 */
54  	@Override
55  	public void configure(Configuration conf) throws ConfigurationException {
56  		super.configure(conf);
57  
58  	}
59  
60  	/**
61  	 * Get all specialized Permissions
62  	 *
63  	 * @param con a database connection
64  	 * @return a List of Permission instances
65  	 * @throws TorqueException if any database error occurs
66  	 */
67  	protected abstract <T extends Permission> List<T> doSelectAllPermissions(Connection con) throws TorqueException;
68  
69  	/**
70  	 * Get a specialized Permission by name
71  	 *
72  	 * @param name the name of the group
73  	 * @param con  a database connection
74  	 *
75  	 * @return a Permission instance
76  	 *
77  	 * @throws NoRowsException      if no such group exists
78  	 * @throws TooManyRowsException if multiple groups with the given name exist
79  	 * @throws TorqueException      if any database error occurs if any other
80  	 *                              database error occurs
81  	 */
82  	protected abstract <T extends Permission> T doSelectByName(String name, Connection con)
83  			throws NoRowsException, TooManyRowsException, TorqueException;
84  
85  	/**
86  	 * Get a specialized Permission by id
87  	 *
88  	 * @param id  the id of the group
89  	 * @param con a database connection
90  	 *
91  	 * @return a Permission instance
92  	 *
93  	 * @throws NoRowsException      if no such group exists
94  	 * @throws TooManyRowsException if multiple groups with the given id exist
95  	 * @throws TorqueException      if any database error occurs if any other
96  	 *                              database error occurs
97  	 */
98  	protected abstract <T extends Permission> T doSelectById(Integer id, Connection con)
99  			throws NoRowsException, TooManyRowsException, TorqueException;
100 
101 	/**
102 	 * Renames an existing Permission.
103 	 *
104 	 * @param permission The object describing the permission to be renamed.
105 	 * @param name       the new name for the permission.
106 	 * @throws DataBackendException   if there was an error accessing the data
107 	 *                                backend.
108 	 * @throws UnknownEntityException if the permission does not exist.
109 	 */
110 	@Override
111 	public synchronized void renamePermission(Permission permission, String name)
112 			throws DataBackendException, UnknownEntityException {
113 		if (checkExists(permission)) {
114 			permission.setName(name);
115 
116 			try {
117 				TorqueAbstractSecurityEntity p = (TorqueAbstractSecurityEntity) permission;
118 				p.setNew(false);
119 				p.save();
120 			} catch (Exception e) {
121 				throw new DataBackendException("Renaming Permission '" + permission.getName() + "' failed", e);
122 			}
123 		} else {
124 			throw new UnknownEntityException("Unknown permission '" + permission.getName() + "'");
125 		}
126 	}
127 
128 	/**
129 	 * Removes a Permission from the system.
130 	 *
131 	 * @param permission The object describing the permission to be removed.
132 	 * @throws DataBackendException   if there was an error accessing the data
133 	 *                                backend.
134 	 * @throws UnknownEntityException if the permission does not exist.
135 	 */
136 	@Override
137 	public synchronized void removePermission(Permission permission)
138 			throws DataBackendException, UnknownEntityException {
139 		if (checkExists(permission)) {
140 			try {
141 
142 				((TorqueAbstractSecurityEntity) permission).delete();
143 			} catch (TorqueException e) {
144 				throw new DataBackendException("Removing Permission '" + permission.getName() + "' failed", e);
145 			}
146 		} else {
147 			throw new UnknownEntityException("Unknown permission '" + permission.getName() + "'");
148 		}
149 	}
150 
151 	/**
152 	 * Creates a new permission with specified attributes.
153 	 *
154 	 * @param permission the object describing the permission to be created.
155 	 * @return a new Permission object that has id set up properly.
156 	 * @throws DataBackendException  if there was an error accessing the data
157 	 *                               backend.
158 	 */
159 	@Override
160 	protected synchronized <T extends Permission> T persistNewPermission(T permission) throws DataBackendException {
161 		try {
162 			((TorqueAbstractSecurityEntity) permission).save();
163 		} catch (Exception e) {
164 			throw new DataBackendException("Adding Permission '" + permission.getName() + "' failed", e);
165 		}
166 
167 		return permission;
168 	}
169 
170 	/**
171 	 * Retrieves all permissions defined in the system.
172 	 *
173 	 * @return the names of all roles defined in the system.
174 	 * @throws DataBackendException if there was an error accessing the data
175 	 *                              backend.
176 	 */
177 	@Override
178 	public PermissionSet getAllPermissions() throws DataBackendException {
179 		PermissionSet permissionSet = new PermissionSet();
180 		Connection con = null;
181 
182 		try {
183 			con = Transaction.begin();
184 
185 			List<Permission> permissions = doSelectAllPermissions(con);
186 
187 			for (Permission p : permissions) {
188 				// Add attached objects if they exist
189 				((TorqueAbstractSecurityEntity) p).retrieveAttachedObjects(con, false);
190 				permissionSet.add(p);
191 			}
192 
193 			Transaction.commit(con);
194 			con = null;
195 		} catch (TorqueException e) {
196 			throw new DataBackendException("Error retrieving permission information", e);
197 		} finally {
198 			if (con != null) {
199 				Transaction.safeRollback(con);
200 			}
201 		}
202 
203 		return permissionSet;
204 	}
205 
206 	/**
207 	 * Determines if the <code>Permission</code> exists in the security system.
208 	 *
209 	 * @param permissionName a <code>Permission</code> value
210 	 * @return true if the permission name exists in the system, false otherwise
211 	 * @throws DataBackendException when more than one Permission with the same name
212 	 *                              exists.
213 	 */
214 	@Override
215 	public boolean checkExists(String permissionName) throws DataBackendException {
216 		boolean exists = false;
217 
218 		Connection con = null;
219 
220 		try {
221 			con = Transaction.begin();
222 
223 			doSelectByName(permissionName, con);
224 
225 			Transaction.commit(con);
226 			con = null;
227 
228 			exists = true;
229 		} catch (NoRowsException e) {
230 			exists = false;
231 		} catch (TooManyRowsException e) {
232 			throw new DataBackendException("Multiple permissions with same name '" + permissionName + "'");
233 		} catch (TorqueException e) {
234 			throw new DataBackendException("Error retrieving permission information", e);
235 		} finally {
236 			if (con != null) {
237 				Transaction.safeRollback(con);
238 			}
239 		}
240 
241 		return exists;
242 	}
243 
244 	/**
245 	 * Retrieve a Permission object with specified id.
246 	 *
247 	 * @param id the id of the Permission.
248 	 * @return an object representing the Permission with specified id.
249 	 * @throws DataBackendException   if there was an error accessing the data
250 	 *                                backend.
251 	 * @throws UnknownEntityException if the permission does not exist.
252 	 */
253 	@Override
254 	public <T extends Permission> T getPermissionById(Object id) throws DataBackendException, UnknownEntityException {
255 		T permission;
256 
257 		if (id != null && id instanceof Integer) {
258 			Connection con = null;
259 
260 			try {
261 				con = Transaction.begin();
262 
263 				permission = doSelectById((Integer) id, con);
264 
265 				// Add attached objects if they exist
266 				((TorqueAbstractSecurityEntity) permission).retrieveAttachedObjects(con, false);
267 
268 				Transaction.commit(con);
269 				con = null;
270 			} catch (NoRowsException e) {
271 				throw new UnknownEntityException("Permission with id '" + id + "' does not exist.", e);
272 			} catch (TorqueException e) {
273 				throw new DataBackendException("Error retrieving permission information", e);
274 			} finally {
275 				if (con != null) {
276 					Transaction.safeRollback(con);
277 				}
278 			}
279 		} else {
280 			throw new UnknownEntityException("Invalid permission id '" + id + "'");
281 		}
282 
283 		return permission;
284 	}
285 
286 	/**
287 	 * Retrieve a Permission object with specified name.
288 	 *
289 	 * @param name the name of the Group.
290 	 * @return an object representing the Group with specified name.
291 	 * @throws DataBackendException   if there was an error accessing the data
292 	 *                                backend.
293 	 * @throws UnknownEntityException if the group does not exist.
294 	 */
295 	@Override
296 	public <T extends Permission> T getPermissionByName(String name)
297 			throws DataBackendException, UnknownEntityException {
298 		T permission = null;
299 		Connection con = null;
300 
301 		try {
302 			con = Transaction.begin();
303 
304 			permission = doSelectByName(name, con);
305 
306 			// Add attached objects if they exist
307 			((TorqueAbstractSecurityEntity) permission).retrieveAttachedObjects(con, false);
308 
309 			Transaction.commit(con);
310 			con = null;
311 		} catch (NoRowsException e) {
312 			throw new UnknownEntityException("Could not find permission " + name);
313 		} catch (TooManyRowsException e) {
314 			throw new DataBackendException("Multiple Permissions with same name '" + name + "'");
315 		} catch (TorqueException e) {
316 			throw new DataBackendException("Error retrieving permission information", e);
317 		} finally {
318 			if (con != null) {
319 				Transaction.safeRollback(con);
320 			}
321 		}
322 
323 		return permission;
324 	}
325 }