001package org.apache.fulcrum.security.torque; 002/* 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 */ 020import java.sql.Connection; 021import java.util.List; 022 023import org.apache.avalon.framework.configuration.Configuration; 024import org.apache.avalon.framework.configuration.ConfigurationException; 025import org.apache.fulcrum.security.entity.Role; 026import org.apache.fulcrum.security.spi.AbstractRoleManager; 027import org.apache.fulcrum.security.torque.security.TorqueAbstractSecurityEntity; 028import org.apache.fulcrum.security.util.DataBackendException; 029import org.apache.fulcrum.security.util.EntityExistsException; 030import org.apache.fulcrum.security.util.RoleSet; 031import org.apache.fulcrum.security.util.UnknownEntityException; 032import org.apache.torque.NoRowsException; 033import org.apache.torque.TooManyRowsException; 034import org.apache.torque.TorqueException; 035import org.apache.torque.util.Transaction; 036/** 037 * This implementation persists to a database via Torque. 038 * 039 * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a> 040 * @version $Id:$ 041 */ 042public abstract class TorqueAbstractRoleManager extends AbstractRoleManager implements LazyLoadable 043{ 044 045 /** Serial version */ 046 private static final long serialVersionUID = 4258137881250800204L; 047 048 private static final String LAZY_LOADING = "lazy"; 049 protected Boolean lazyLoading = false; 050 051 /** 052 * Avalon Service lifecycle method 053 */ 054 @Override 055 public void configure(Configuration conf) throws ConfigurationException 056 { 057 super.configure( conf ); 058 lazyLoading = conf.getAttributeAsBoolean( LAZY_LOADING, false); 059 getLogger().debug("setting lazyLoading: " + lazyLoading); 060 } 061 062 063 /** 064 * Get all specialized Roles 065 * 066 * @param con a database connection 067 * 068 * @return a List of Role instances 069 * 070 * @throws TorqueException if any database error occurs 071 */ 072 protected abstract <T extends Role> List<T> doSelectAllRoles(Connection con) 073 throws TorqueException; 074 075 /** 076 * Get a specialized Role by name 077 * 078 * @param name the name of the group 079 * @param con a database connection 080 * 081 * @return a Role instance 082 * 083 * @throws NoRowsException if no such group exists 084 * @throws TooManyRowsException if multiple groups with the given name exist 085 * @throws TorqueException if any database error occurs if any other database error occurs 086 */ 087 protected abstract <T extends Role> T doSelectByName(String name, Connection con) 088 throws NoRowsException, TooManyRowsException, TorqueException; 089 090 /** 091 * Get a specialized Role by id 092 * 093 * @param id the id of the group 094 * @param con a database connection 095 * 096 * @return a Role instance 097 * 098 * @throws NoRowsException if no such group exists 099 * @throws TooManyRowsException if multiple groups with the given id exist 100 * @throws TorqueException if any database error occurs if any other database error occurs 101 */ 102 protected abstract <T extends Role> T doSelectById(Integer id, Connection con) 103 throws NoRowsException, TooManyRowsException, TorqueException; 104 105 106 /** 107 * Renames an existing Role. 108 * 109 * @param role The object describing the role to be renamed. 110 * @param name the new name for the role. 111 * @throws DataBackendException if there was an error accessing the data 112 * backend. 113 * @throws UnknownEntityException if the role does not exist. 114 */ 115 @Override 116 public synchronized void renameRole(Role role, String name) throws DataBackendException, UnknownEntityException 117 { 118 if (checkExists(role)) 119 { 120 role.setName(name); 121 122 try 123 { 124 TorqueAbstractSecurityEntity r = (TorqueAbstractSecurityEntity)role; 125 r.setNew(false); 126 r.save(); 127 } 128 catch (Exception e) 129 { 130 throw new DataBackendException("Renaming Role '" + role.getName() + "' failed", e); 131 } 132 } 133 else 134 { 135 throw new UnknownEntityException("Unknown Role '" + role.getName() + "'"); 136 } 137 } 138 139 /** 140 * Creates a new role with specified attributes. 141 * 142 * @param role the object describing the role to be created. 143 * @return a new Role object that has id set up properly. 144 * @throws DataBackendException if there was an error accessing the data 145 * backend. 146 */ 147 @Override 148 protected synchronized <T extends Role> T persistNewRole(T role) throws DataBackendException 149 { 150 try 151 { 152 ((TorqueAbstractSecurityEntity)role).save(); 153 } 154 catch (Exception e) 155 { 156 throw new DataBackendException("Adding Role '" + role.getName() + "' failed", e); 157 } 158 159 return role; 160 } 161 162 /** 163 * Removes a Role from the system. 164 * 165 * @param role The object describing the role to be removed. 166 * @throws DataBackendException if there was an error accessing the data 167 * backend. 168 * @throws UnknownEntityException if the role does not exist. 169 */ 170 @Override 171 public synchronized void removeRole(Role role) throws DataBackendException, UnknownEntityException 172 { 173 if (checkExists(role)) 174 { 175 try 176 { 177 ((TorqueAbstractSecurityEntity)role).delete(); 178 } 179 catch (TorqueException e) 180 { 181 throw new DataBackendException("Removing Role '" + role.getName() + "' failed", e); 182 } 183 } 184 else 185 { 186 throw new UnknownEntityException("Unknown role '" + role.getName() + "'"); 187 } 188 } 189 190 /** 191 * Determines if the <code>Role</code> exists in the security system. 192 * 193 * @param roleName a <code>Role</code> value 194 * @return true if the role name exists in the system, false otherwise 195 * @throws DataBackendException when more than one Role with 196 * the same name exists. 197 */ 198 @Override 199 public boolean checkExists(String roleName) throws DataBackendException 200 { 201 boolean exists = false; 202 203 Connection con = null; 204 205 try 206 { 207 con = Transaction.begin(); 208 209 doSelectByName(roleName, con); 210 211 Transaction.commit(con); 212 con = null; 213 214 exists = true; 215 } 216 catch (NoRowsException e) 217 { 218 exists = false; 219 } 220 catch (TooManyRowsException e) 221 { 222 throw new DataBackendException("Multiple roles with same name '" + roleName + "'"); 223 } 224 catch (TorqueException e) 225 { 226 throw new DataBackendException("Error retrieving role information", e); 227 } 228 finally 229 { 230 if (con != null) 231 { 232 Transaction.safeRollback(con); 233 } 234 } 235 236 return exists; 237 } 238 239 /** 240 * Retrieves all roles defined in the system. 241 * 242 * @return the names of all roles defined in the system. 243 * @throws DataBackendException if there was an error accessing the 244 * data backend. 245 */ 246 @Override 247 public RoleSet getAllRoles() throws DataBackendException 248 { 249 RoleSet roleSet = new RoleSet(); 250 Connection con = null; 251 252 try 253 { 254 con = Transaction.begin(); 255 256 List<Role> roles = doSelectAllRoles(con); 257 258 for (Role role : roles) 259 { 260 // Add attached objects if they exist 261 ((TorqueAbstractSecurityEntity)role).retrieveAttachedObjects(con, getLazyLoading()); 262 263 roleSet.add(role); 264 } 265 266 Transaction.commit(con); 267 con = null; 268 } 269 catch (TorqueException e) 270 { 271 throw new DataBackendException("Error retrieving role information", e); 272 } 273 finally 274 { 275 if (con != null) 276 { 277 Transaction.safeRollback(con); 278 } 279 } 280 281 return roleSet; 282 } 283 284 /** 285 * Retrieve a Role object with specified id. 286 * 287 * @param id 288 * the id of the Role. 289 * @return an object representing the Role with specified id. 290 * @throws DataBackendException 291 * if there was an error accessing the data backend. 292 * @throws UnknownEntityException 293 * if the role does not exist. 294 */ 295 @Override 296 public <T extends Role> T getRoleById(Object id) throws DataBackendException, UnknownEntityException 297 { 298 T role; 299 300 if (id != null && id instanceof Integer) 301 { 302 Connection con = null; 303 304 try 305 { 306 con = Transaction.begin(); 307 308 role = doSelectById((Integer)id, con); 309 310 // Add attached objects if they exist 311 ((TorqueAbstractSecurityEntity)role).retrieveAttachedObjects(con, getLazyLoading()); 312 313 Transaction.commit(con); 314 con = null; 315 } 316 catch (NoRowsException e) 317 { 318 throw new UnknownEntityException("Role with id '" + id + "' does not exist.", e); 319 } 320 catch (TorqueException e) 321 { 322 throw new DataBackendException("Error retrieving role information", e); 323 } 324 finally 325 { 326 if (con != null) 327 { 328 Transaction.safeRollback(con); 329 } 330 } 331 } 332 else 333 { 334 throw new UnknownEntityException("Invalid role id '" + id + "'"); 335 } 336 337 return role; 338 } 339 340 /** 341 * Retrieve a Role object with specified name. 342 * 343 * @param name the name of the Role. 344 * @return an object representing the Role with specified name. 345 * @throws DataBackendException if there was an error accessing the 346 * data backend. 347 * @throws UnknownEntityException if the role does not exist. 348 */ 349 @Override 350 public <T extends Role> T getRoleByName(String name) throws DataBackendException, UnknownEntityException 351 { 352 T role = null; 353 Connection con = null; 354 355 try 356 { 357 con = Transaction.begin(); 358 359 role = doSelectByName(name, con); 360 361 // Add attached objects if they exist 362 ((TorqueAbstractSecurityEntity)role).retrieveAttachedObjects(con, getLazyLoading()); 363 364 Transaction.commit(con); 365 con = null; 366 } 367 catch (NoRowsException e) 368 { 369 throw new UnknownEntityException("Could not find role" + name); 370 } 371 catch (TooManyRowsException e) 372 { 373 throw new DataBackendException("Multiple Roles with same name '" + name + "'"); 374 } 375 catch (TorqueException e) 376 { 377 throw new DataBackendException("Error retrieving role information", e); 378 } 379 finally 380 { 381 if (con != null) 382 { 383 Transaction.safeRollback(con); 384 } 385 } 386 387 return role; 388 } 389 390 391 /* (non-Javadoc) 392 * @see org.apache.fulcrum.security.torque.LazyLoadable#getLazyLoading() 393 */ 394 @Override 395 public Boolean getLazyLoading() 396 { 397 return lazyLoading; 398 } 399 400 401 /* (non-Javadoc) 402 * @see org.apache.fulcrum.security.torque.LazyLoadable#setLazyLoading(java.lang.Boolean) 403 */ 404 @Override 405 public void setLazyLoading( Boolean lazyLoading ) 406 { 407 this.lazyLoading = lazyLoading; 408 } 409}