001 package org.apache.turbine.services.security.torque; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022 import java.util.ArrayList; 023 import java.util.Hashtable; 024 import java.util.Iterator; 025 import java.util.List; 026 027 import org.apache.commons.configuration.Configuration; 028 import org.apache.commons.lang.StringUtils; 029 import org.apache.commons.logging.Log; 030 import org.apache.commons.logging.LogFactory; 031 import org.apache.torque.TorqueException; 032 import org.apache.torque.om.NumberKey; 033 import org.apache.torque.om.Persistent; 034 import org.apache.torque.util.Criteria; 035 import org.apache.turbine.om.security.Group; 036 import org.apache.turbine.om.security.Permission; 037 import org.apache.turbine.om.security.Role; 038 import org.apache.turbine.om.security.User; 039 import org.apache.turbine.services.InitializationException; 040 import org.apache.turbine.services.security.BaseSecurityService; 041 import org.apache.turbine.services.security.TurbineSecurity; 042 import org.apache.turbine.services.security.torque.om.TurbineRolePermissionPeer; 043 import org.apache.turbine.services.security.torque.om.TurbineUserGroupRolePeer; 044 import org.apache.turbine.util.security.AccessControlList; 045 import org.apache.turbine.util.security.DataBackendException; 046 import org.apache.turbine.util.security.EntityExistsException; 047 import org.apache.turbine.util.security.GroupSet; 048 import org.apache.turbine.util.security.PermissionSet; 049 import org.apache.turbine.util.security.RoleSet; 050 import org.apache.turbine.util.security.UnknownEntityException; 051 052 /** 053 * An implementation of SecurityService that uses torque objects. 054 * 055 * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a> 056 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> 057 * @author <a href="mailto:marco@intermeta.de">Marco Knüttel</a> 058 * @version $Id: TorqueSecurityService.java 1096130 2011-04-23 10:37:19Z ludwig $ 059 */ 060 public class TorqueSecurityService 061 extends BaseSecurityService 062 { 063 /** Logging */ 064 private static Log log = LogFactory.getLog(TorqueSecurityService.class); 065 066 /** 067 * Initializes the TorqueSecurityService, loading the various class objects 068 * representing the security entity peer classes 069 * 070 * @exception InitializationException A problem occured during initialization 071 */ 072 073 public void init() 074 throws InitializationException 075 { 076 Configuration conf = getConfiguration(); 077 078 GroupPeerManager.init(conf); 079 RolePeerManager.init(conf); 080 PermissionPeerManager.init(conf); 081 082 /* At the end, because it calls setInit(true)! */ 083 super.init(); 084 } 085 086 087 /*----------------------------------------------------------------------- 088 Creation of AccessControlLists 089 -----------------------------------------------------------------------*/ 090 091 /** 092 * Constructs an AccessControlList for a specific user. 093 * 094 * This method creates a snapshot of the state of security information 095 * concerning this user, at the moment of invocation and stores it 096 * into an AccessControlList object. 097 * 098 * @param user the user for whom the AccessControlList are to be retrieved 099 * @return A new AccessControlList object. 100 * @throws DataBackendException if there was an error accessing the data 101 * backend. 102 * @throws UnknownEntityException if user account is not present. 103 */ 104 public AccessControlList getACL(User user) 105 throws DataBackendException, UnknownEntityException 106 { 107 if (!TurbineSecurity.accountExists(user)) 108 { 109 throw new UnknownEntityException("The account '" 110 + user.getName() + "' does not exist"); 111 } 112 try 113 { 114 Hashtable roles = new Hashtable(); 115 Hashtable permissions = new Hashtable(); 116 // notify the state modifiers (writers) that we want to create 117 // the snapshot. 118 lockShared(); 119 120 // construct the snapshot: 121 122 // foreach group in the system 123 for (Iterator groupsIterator = getAllGroups().iterator(); 124 groupsIterator.hasNext();) 125 { 126 Group group = (Group) groupsIterator.next(); 127 // get roles of user in the group 128 RoleSet groupRoles = RolePeerManager.retrieveSet(user, group); 129 // put the Set into roles(group) 130 roles.put(group, groupRoles); 131 // collect all permissions in this group 132 PermissionSet groupPermissions = new PermissionSet(); 133 // foreach role in Set 134 for (Iterator rolesIterator = groupRoles.iterator(); 135 rolesIterator.hasNext();) 136 { 137 Role role = (Role) rolesIterator.next(); 138 // get permissions of the role 139 PermissionSet rolePermissions = 140 PermissionPeerManager.retrieveSet(role); 141 groupPermissions.add(rolePermissions); 142 } 143 // put the Set into permissions(group) 144 permissions.put(group, groupPermissions); 145 } 146 return getAclInstance(roles, permissions); 147 } 148 catch (Exception e) 149 { 150 throw new DataBackendException("Failed to build ACL for user '" + 151 user.getName() + "'" , e); 152 } 153 finally 154 { 155 // notify the state modifiers that we are done creating the snapshot. 156 unlockShared(); 157 } 158 } 159 160 /*----------------------------------------------------------------------- 161 Security management 162 -----------------------------------------------------------------------*/ 163 164 /** 165 * Grant an User a Role in a Group. 166 * 167 * @param user the user. 168 * @param group the group. 169 * @param role the role. 170 * @throws DataBackendException if there was an error accessing the data 171 * backend. 172 * @throws UnknownEntityException if user account, group or role is not 173 * present. 174 */ 175 public synchronized void grant(User user, Group group, Role role) 176 throws DataBackendException, UnknownEntityException 177 { 178 boolean userExists = false; 179 boolean groupExists = false; 180 boolean roleExists = false; 181 try 182 { 183 lockExclusive(); 184 userExists = TurbineSecurity.accountExists(user); 185 groupExists = checkExists(group); 186 roleExists = checkExists(role); 187 if (userExists && groupExists && roleExists) 188 { 189 Criteria criteria = new Criteria(); 190 criteria.add(TurbineUserGroupRolePeer.USER_ID, 191 ((Persistent) user).getPrimaryKey()); 192 criteria.add(TurbineUserGroupRolePeer.GROUP_ID, 193 ((Persistent) group).getPrimaryKey()); 194 criteria.add(TurbineUserGroupRolePeer.ROLE_ID, 195 ((Persistent) role).getPrimaryKey()); 196 TurbineUserGroupRolePeer.doInsert(criteria); 197 return; 198 } 199 } 200 catch (Exception e) 201 { 202 throw new DataBackendException("grant(User,Group,Role) failed", e); 203 } 204 finally 205 { 206 unlockExclusive(); 207 } 208 if (!userExists) 209 { 210 throw new UnknownEntityException("Unknown user '" 211 + user.getName() + "'"); 212 } 213 if (!groupExists) 214 { 215 throw new UnknownEntityException("Unknown group '" 216 + group.getName() + "'"); 217 } 218 if (!roleExists) 219 { 220 throw new UnknownEntityException("Unknown role '" 221 + role.getName() + "'"); 222 } 223 } 224 225 /** 226 * Revoke a Role in a Group from an User. 227 * 228 * @param user the user. 229 * @param group the group. 230 * @param role the role. 231 * @throws DataBackendException if there was an error accessing the data 232 * backend. 233 * @throws UnknownEntityException if user account, group or role is not 234 * present. 235 */ 236 public synchronized void revoke(User user, Group group, Role role) 237 throws DataBackendException, UnknownEntityException 238 { 239 boolean userExists = false; 240 boolean groupExists = false; 241 boolean roleExists = false; 242 try 243 { 244 lockExclusive(); 245 userExists = TurbineSecurity.accountExists(user); 246 groupExists = checkExists(group); 247 roleExists = checkExists(role); 248 if (userExists && groupExists && roleExists) 249 { 250 Criteria criteria = new Criteria(); 251 criteria.add(TurbineUserGroupRolePeer.USER_ID, 252 ((Persistent) user).getPrimaryKey()); 253 criteria.add(TurbineUserGroupRolePeer.GROUP_ID, 254 ((Persistent) group).getPrimaryKey()); 255 criteria.add(TurbineUserGroupRolePeer.ROLE_ID, 256 ((Persistent) role).getPrimaryKey()); 257 TurbineUserGroupRolePeer.doDelete(criteria); 258 return; 259 } 260 } 261 catch (Exception e) 262 { 263 throw new DataBackendException("revoke(User,Role,Group) failed", e); 264 } 265 finally 266 { 267 unlockExclusive(); 268 } 269 if (!userExists) 270 { 271 throw new UnknownEntityException("Unknown user '" 272 + user.getName() + "'"); 273 } 274 if (!groupExists) 275 { 276 throw new UnknownEntityException("Unknown group '" 277 + group.getName() + "'"); 278 } 279 if (!roleExists) 280 { 281 throw new UnknownEntityException("Unknown role '" 282 + role.getName() + "'"); 283 } 284 } 285 286 /** 287 * Revokes all roles from an User. 288 * 289 * This method is used when deleting an account. 290 * 291 * @param user the User. 292 * @throws DataBackendException if there was an error accessing the data 293 * backend. 294 * @throws UnknownEntityException if the account is not present. 295 */ 296 public synchronized void revokeAll(User user) 297 throws DataBackendException, UnknownEntityException 298 { 299 boolean userExists = false; 300 try 301 { 302 lockExclusive(); 303 userExists = TurbineSecurity.accountExists(user); 304 if (userExists) 305 { 306 // The following would not work, due to an annoying misfeature 307 // of Village. Village allows only a single row to be deleted at 308 // a time. I wish that it was possible to disable this 309 // behaviour! 310 311 // Criteria criteria = new Criteria(); 312 // criteria.add(UserGroupRolePeer.USER_ID, 313 // ((Persistent) user).getPrimaryKey()); 314 // UserGroupRolePeer.doDelete(criteria); 315 int id = ((NumberKey) ((Persistent) user) 316 .getPrimaryKey()).intValue(); 317 TurbineUserGroupRolePeer.deleteAll( 318 TurbineUserGroupRolePeer.TABLE_NAME, 319 TurbineUserGroupRolePeer.USER_ID, id); 320 return; 321 } 322 } 323 catch (Exception e) 324 { 325 throw new DataBackendException("revokeAll(User) failed", e); 326 } 327 finally 328 { 329 unlockExclusive(); 330 } 331 throw new UnknownEntityException("Unknown user '" 332 + user.getName() + "'"); 333 } 334 335 /** 336 * Grants a Role a Permission 337 * 338 * @param role the Role. 339 * @param permission the Permission. 340 * @throws DataBackendException if there was an error accessing the data 341 * backend. 342 * @throws UnknownEntityException if role or permission is not present. 343 */ 344 public synchronized void grant(Role role, Permission permission) 345 throws DataBackendException, UnknownEntityException 346 { 347 boolean roleExists = false; 348 boolean permissionExists = false; 349 try 350 { 351 lockExclusive(); 352 roleExists = checkExists(role); 353 permissionExists = checkExists(permission); 354 if (roleExists && permissionExists) 355 { 356 Criteria criteria = new Criteria(); 357 criteria.add(TurbineRolePermissionPeer.ROLE_ID, 358 ((Persistent) role).getPrimaryKey()); 359 criteria.add(TurbineRolePermissionPeer.PERMISSION_ID, 360 ((Persistent) permission).getPrimaryKey()); 361 TurbineRolePermissionPeer.doInsert(criteria); 362 return; 363 } 364 } 365 catch (Exception e) 366 { 367 throw new DataBackendException("grant(Role,Permission) failed", e); 368 } 369 finally 370 { 371 unlockExclusive(); 372 } 373 if (!roleExists) 374 { 375 throw new UnknownEntityException("Unknown role '" 376 + role.getName() + "'"); 377 } 378 if (!permissionExists) 379 { 380 throw new UnknownEntityException("Unknown permission '" 381 + permission.getName() + "'"); 382 } 383 } 384 385 /** 386 * Revokes a Permission from a Role. 387 * 388 * @param role the Role. 389 * @param permission the Permission. 390 * @throws DataBackendException if there was an error accessing the data 391 * backend. 392 * @throws UnknownEntityException if role or permission is not present. 393 */ 394 public synchronized void revoke(Role role, Permission permission) 395 throws DataBackendException, UnknownEntityException 396 { 397 boolean roleExists = false; 398 boolean permissionExists = false; 399 try 400 { 401 lockExclusive(); 402 roleExists = checkExists(role); 403 permissionExists = checkExists(permission); 404 if (roleExists && permissionExists) 405 { 406 Criteria criteria = new Criteria(); 407 criteria.add(TurbineRolePermissionPeer.ROLE_ID, 408 ((Persistent) role).getPrimaryKey()); 409 criteria.add(TurbineRolePermissionPeer.PERMISSION_ID, 410 ((Persistent) permission).getPrimaryKey()); 411 TurbineRolePermissionPeer.doDelete(criteria); 412 return; 413 } 414 } 415 catch (Exception e) 416 { 417 throw new DataBackendException("revoke(Role,Permission) failed", e); 418 } 419 finally 420 { 421 unlockExclusive(); 422 } 423 if (!roleExists) 424 { 425 throw new UnknownEntityException("Unknown role '" 426 + role.getName() + "'"); 427 } 428 if (!permissionExists) 429 { 430 throw new UnknownEntityException("Unknown permission '" 431 + permission.getName() + "'"); 432 } 433 } 434 435 /** 436 * Revokes all permissions from a Role. 437 * 438 * This method is user when deleting a Role. 439 * 440 * @param role the Role 441 * @throws DataBackendException if there was an error accessing the data 442 * backend. 443 * @throws UnknownEntityException if the Role is not present. 444 */ 445 public synchronized void revokeAll(Role role) 446 throws DataBackendException, UnknownEntityException 447 { 448 boolean roleExists = false; 449 try 450 { 451 lockExclusive(); 452 roleExists = checkExists(role); 453 if (roleExists) 454 { 455 // The following would not work, due to an annoying misfeature 456 // of Village. see revokeAll( user ) 457 458 // Criteria criteria = new Criteria(); 459 // criteria.add(RolePermissionPeer.ROLE_ID, 460 // role.getPrimaryKey()); 461 // RolePermissionPeer.doDelete(criteria); 462 463 int id = ((NumberKey) ((Persistent) role) 464 .getPrimaryKey()).intValue(); 465 TurbineRolePermissionPeer.deleteAll( 466 TurbineRolePermissionPeer.TABLE_NAME, 467 TurbineRolePermissionPeer.ROLE_ID, id); 468 return; 469 } 470 } 471 catch (Exception e) 472 { 473 throw new DataBackendException("revokeAll(Role) failed", e); 474 } 475 finally 476 { 477 unlockExclusive(); 478 } 479 throw new UnknownEntityException("Unknown role '" 480 + role.getName() + "'"); 481 } 482 483 /*----------------------------------------------------------------------- 484 Group/Role/Permission management 485 -----------------------------------------------------------------------*/ 486 487 /** 488 * Retrieve a set of Groups that meet the specified Criteria. 489 * 490 * @param criteria A Criteria of Group selection. 491 * @return a set of Groups that meet the specified Criteria. 492 * @throws DataBackendException if there was an error accessing the data 493 * backend. 494 */ 495 public GroupSet getGroups(Object criteria) 496 throws DataBackendException 497 { 498 if (criteria instanceof Criteria) 499 { 500 Criteria torqueCriteria = new Criteria(); 501 Criteria c = (Criteria)criteria; 502 Iterator keys = c.keySet().iterator(); 503 while (keys.hasNext()) 504 { 505 String key = (String) keys.next(); 506 torqueCriteria.put(GroupPeerManager.getColumnName(key), 507 c.get(key)); 508 } 509 List groups = new ArrayList(0); 510 try 511 { 512 groups = GroupPeerManager.doSelect(torqueCriteria); 513 } 514 catch (TorqueException e) 515 { 516 throw new DataBackendException("getGroups(Object) failed", e); 517 } 518 519 return new GroupSet(groups); 520 } 521 else 522 { 523 throw new DataBackendException( 524 "getGroups(Object) failed with invalid criteria"); 525 } 526 } 527 528 /** 529 * Retrieve a set of Roles that meet the specified Criteria. 530 * 531 * @param criteria A Criteria of Roles selection. 532 * @return a set of Roles that meet the specified Criteria. 533 * @throws DataBackendException if there was an error accessing the data 534 * backend. 535 */ 536 public RoleSet getRoles(Object criteria) 537 throws DataBackendException 538 { 539 if (criteria instanceof Criteria) 540 { 541 Criteria torqueCriteria = new Criteria(); 542 Criteria c = (Criteria)criteria; 543 Iterator keys = c.keySet().iterator(); 544 while (keys.hasNext()) 545 { 546 String key = (String) keys.next(); 547 torqueCriteria.put(RolePeerManager.getColumnName(key), 548 c.get(key)); 549 } 550 List roles = new ArrayList(0); 551 try 552 { 553 roles = RolePeerManager.doSelect(torqueCriteria); 554 } 555 catch (TorqueException e) 556 { 557 throw new DataBackendException("getRoles(Criteria) failed", e); 558 } 559 return new RoleSet(roles); 560 } 561 else 562 { 563 throw new DataBackendException( 564 "getRoles(Object) failed with invalid criteria"); 565 } 566 } 567 568 /** 569 * Retrieve a set of Permissions that meet the specified Criteria. 570 * 571 * @param criteria A Criteria of Permissions selection. 572 * @return a set of Permissions that meet the specified Criteria. 573 * @throws DataBackendException if there was an error accessing the data 574 * backend. 575 */ 576 public PermissionSet getPermissions(Object criteria) 577 throws DataBackendException 578 { 579 if (criteria instanceof Criteria) 580 { 581 Criteria torqueCriteria = new Criteria(); 582 Criteria c = (Criteria)criteria; 583 Iterator keys = c.keySet().iterator(); 584 while (keys.hasNext()) 585 { 586 String key = (String) keys.next(); 587 torqueCriteria.put(PermissionPeerManager.getColumnName(key), 588 c.get(key)); 589 } 590 List permissions = new ArrayList(0); 591 try 592 { 593 permissions = PermissionPeerManager.doSelect(torqueCriteria); 594 } 595 catch (TorqueException e) 596 { 597 throw new DataBackendException( 598 "getPermissions(Object) failed", e); 599 } 600 601 return new PermissionSet(permissions); 602 } 603 else 604 { 605 throw new DataBackendException( 606 "getPermissions(Object) failed with invalid criteria"); 607 } 608 } 609 610 /** 611 * Retrieves all permissions associated with a role. 612 * 613 * @param role the role name, for which the permissions are to be retrieved. 614 * @return A Permission set for the Role. 615 * @throws DataBackendException if there was an error accessing the data 616 * backend. 617 * @throws UnknownEntityException if the role is not present. 618 */ 619 public PermissionSet getPermissions(Role role) 620 throws DataBackendException, UnknownEntityException 621 { 622 boolean roleExists = false; 623 try 624 { 625 lockShared(); 626 roleExists = checkExists(role); 627 if (roleExists) 628 { 629 return PermissionPeerManager.retrieveSet(role); 630 } 631 } 632 catch (Exception e) 633 { 634 throw new DataBackendException("getPermissions(Role) failed", e); 635 } 636 finally 637 { 638 unlockShared(); 639 } 640 throw new UnknownEntityException("Unknown role '" 641 + role.getName() + "'"); 642 } 643 644 /** 645 * Stores Group's attributes. The Groups is required to exist in the system. 646 * 647 * @param group The Group to be stored. 648 * @throws DataBackendException if there was an error accessing the data 649 * backend. 650 * @throws UnknownEntityException if the group does not exist. 651 */ 652 public void saveGroup(Group group) 653 throws DataBackendException, UnknownEntityException 654 { 655 boolean groupExists = false; 656 try 657 { 658 groupExists = checkExists(group); 659 if (groupExists) 660 { 661 Criteria criteria = GroupPeerManager.buildCriteria(group); 662 GroupPeerManager.doUpdate(criteria); 663 return; 664 } 665 } 666 catch (Exception e) 667 { 668 throw new DataBackendException("saveGroup(Group) failed", e); 669 } 670 throw new UnknownEntityException("Unknown group '" + group + "'"); 671 } 672 673 /** 674 * Stores Role's attributes. The Roles is required to exist in the system. 675 * 676 * @param role The Role to be stored. 677 * @throws DataBackendException if there was an error accessing the data 678 * backend. 679 * @throws UnknownEntityException if the role does not exist. 680 */ 681 public void saveRole(Role role) 682 throws DataBackendException, UnknownEntityException 683 { 684 boolean roleExists = false; 685 try 686 { 687 roleExists = checkExists(role); 688 if (roleExists) 689 { 690 Criteria criteria = RolePeerManager.buildCriteria(role); 691 RolePeerManager.doUpdate(criteria); 692 return; 693 } 694 } 695 catch (Exception e) 696 { 697 throw new DataBackendException("saveRole(Role) failed", e); 698 } 699 throw new UnknownEntityException("Unknown role '" + role + "'"); 700 } 701 702 /** 703 * Stores Permission's attributes. The Permissions is required to exist in 704 * the system. 705 * 706 * @param permission The Permission to be stored. 707 * @throws DataBackendException if there was an error accessing the data 708 * backend. 709 * @throws UnknownEntityException if the permission does not exist. 710 */ 711 public void savePermission(Permission permission) 712 throws DataBackendException, UnknownEntityException 713 { 714 boolean permissionExists = false; 715 try 716 { 717 permissionExists = checkExists(permission); 718 if (permissionExists) 719 { 720 Criteria criteria = PermissionPeerManager.buildCriteria(permission); 721 PermissionPeerManager.doUpdate(criteria); 722 return; 723 } 724 } 725 catch (Exception e) 726 { 727 throw new DataBackendException( 728 "savePermission(Permission) failed", e); 729 } 730 throw new UnknownEntityException("Unknown permission '" 731 + permission + "'"); 732 } 733 734 /** 735 * Creates a new group with specified attributes. 736 * 737 * @param group the object describing the group to be created. 738 * @return a new Group object that has id set up properly. 739 * @throws DataBackendException if there was an error accessing the data 740 * backend. 741 * @throws EntityExistsException if the group already exists. 742 */ 743 public synchronized Group addGroup(Group group) 744 throws DataBackendException, 745 EntityExistsException 746 { 747 boolean groupExists = false; 748 749 if (StringUtils.isEmpty(group.getName())) 750 { 751 throw new DataBackendException("Could not create " 752 + "a group with empty name!"); 753 } 754 755 try 756 { 757 lockExclusive(); 758 groupExists = checkExists(group); 759 if (!groupExists) 760 { 761 // add a row to the table 762 Criteria criteria = GroupPeerManager.buildCriteria(group); 763 GroupPeerManager.doInsert(criteria); 764 // try to get the object back using the name as key. 765 criteria = new Criteria(); 766 criteria.add(GroupPeerManager.getNameColumn(), 767 group.getName()); 768 List results = GroupPeerManager.doSelect(criteria); 769 if (results.size() != 1) 770 { 771 throw new DataBackendException( 772 "Internal error - query returned " 773 + results.size() + " rows"); 774 } 775 Group newGroup = (Group) results.get(0); 776 // add the group to system-wide cache 777 getAllGroups().add(newGroup); 778 // return the object with correct id 779 return newGroup; 780 } 781 } 782 catch (Exception e) 783 { 784 throw new DataBackendException("addGroup(Group) failed", e); 785 } 786 finally 787 { 788 unlockExclusive(); 789 } 790 // the only way we could get here without return/throw tirggered 791 // is that the groupExists was true. 792 throw new EntityExistsException("Group '" + group + "' already exists"); 793 } 794 795 /** 796 * Creates a new role with specified attributes. 797 * 798 * @param role the object describing the role to be created. 799 * @return a new Role object that has id set up properly. 800 * @throws DataBackendException if there was an error accessing the data 801 * backend. 802 * @throws EntityExistsException if the role already exists. 803 */ 804 public synchronized Role addRole(Role role) 805 throws DataBackendException, EntityExistsException 806 { 807 boolean roleExists = false; 808 809 if (StringUtils.isEmpty(role.getName())) 810 { 811 throw new DataBackendException("Could not create " 812 + "a role with empty name!"); 813 } 814 815 try 816 { 817 lockExclusive(); 818 roleExists = checkExists(role); 819 if (!roleExists) 820 { 821 // add a row to the table 822 Criteria criteria = RolePeerManager.buildCriteria(role); 823 RolePeerManager.doInsert(criteria); 824 // try to get the object back using the name as key. 825 criteria = new Criteria(); 826 criteria.add(RolePeerManager.getNameColumn(), role.getName()); 827 List results = RolePeerManager.doSelect(criteria); 828 if (results.size() != 1) 829 { 830 throw new DataBackendException( 831 "Internal error - query returned " 832 + results.size() + " rows"); 833 } 834 Role newRole = (Role) results.get(0); 835 // add the role to system-wide cache 836 getAllRoles().add(newRole); 837 // return the object with correct id 838 return newRole; 839 } 840 } 841 catch (Exception e) 842 { 843 throw new DataBackendException("addRole(Role) failed", e); 844 } 845 finally 846 { 847 unlockExclusive(); 848 } 849 // the only way we could get here without return/throw tirggered 850 // is that the roleExists was true. 851 throw new EntityExistsException("Role '" + role + "' already exists"); 852 } 853 854 /** 855 * Creates a new permission with specified attributes. 856 * 857 * @param permission the object describing the permission to be created. 858 * @return a new Permission object that has id set up properly. 859 * @throws DataBackendException if there was an error accessing the data 860 * backend. 861 * @throws EntityExistsException if the permission already exists. 862 */ 863 public synchronized Permission addPermission(Permission permission) 864 throws DataBackendException, EntityExistsException 865 { 866 boolean permissionExists = false; 867 868 if (StringUtils.isEmpty(permission.getName())) 869 { 870 throw new DataBackendException("Could not create " 871 + "a permission with empty name!"); 872 } 873 874 try 875 { 876 lockExclusive(); 877 permissionExists = checkExists(permission); 878 if (!permissionExists) 879 { 880 // add a row to the table 881 Criteria criteria = PermissionPeerManager.buildCriteria(permission); 882 PermissionPeerManager.doInsert(criteria); 883 // try to get the object back using the name as key. 884 criteria = new Criteria(); 885 criteria.add(PermissionPeerManager.getNameColumn(), 886 permission.getName()); 887 List results = PermissionPeerManager.doSelect(criteria); 888 if (results.size() != 1) 889 { 890 throw new DataBackendException( 891 "Internal error - query returned " 892 + results.size() + " rows"); 893 } 894 Permission newPermission = (Permission) results.get(0); 895 // add the permission to system-wide cache 896 getAllPermissions().add(newPermission); 897 // return the object with correct id 898 return newPermission; 899 } 900 } 901 catch (Exception e) 902 { 903 throw new DataBackendException( 904 "addPermission(Permission) failed", e); 905 } 906 finally 907 { 908 unlockExclusive(); 909 } 910 // the only way we could get here without return/throw tirggered 911 // is that the permissionExists was true. 912 throw new EntityExistsException("Permission '" + permission 913 + "' already exists"); 914 } 915 916 /** 917 * Removes a Group from the system. 918 * 919 * @param group The object describing the group to be removed. 920 * @throws DataBackendException if there was an error accessing the data 921 * backend. 922 * @throws UnknownEntityException if the group does not exist. 923 */ 924 public synchronized void removeGroup(Group group) 925 throws DataBackendException, UnknownEntityException 926 { 927 boolean groupExists = false; 928 try 929 { 930 lockExclusive(); 931 groupExists = checkExists(group); 932 if (groupExists) 933 { 934 Criteria criteria = GroupPeerManager.buildCriteria(group); 935 GroupPeerManager.doDelete(criteria); 936 getAllGroups().remove(group); 937 return; 938 } 939 } 940 catch (Exception e) 941 { 942 log.error("Failed to delete a Group"); 943 log.error(e); 944 throw new DataBackendException("removeGroup(Group) failed", e); 945 } 946 finally 947 { 948 unlockExclusive(); 949 } 950 throw new UnknownEntityException("Unknown group '" + group + "'"); 951 } 952 953 /** 954 * Removes a Role from the system. 955 * 956 * @param role The object describing the role to be removed. 957 * @throws DataBackendException if there was an error accessing the data 958 * backend. 959 * @throws UnknownEntityException if the role does not exist. 960 */ 961 public synchronized void removeRole(Role role) 962 throws DataBackendException, UnknownEntityException 963 { 964 boolean roleExists = false; 965 try 966 { 967 lockExclusive(); 968 roleExists = checkExists(role); 969 if (roleExists) 970 { 971 // revoke all permissions from the role to be deleted 972 revokeAll(role); 973 Criteria criteria = RolePeerManager.buildCriteria(role); 974 RolePeerManager.doDelete(criteria); 975 getAllRoles().remove(role); 976 return; 977 } 978 } 979 catch (Exception e) 980 { 981 throw new DataBackendException("removeRole(Role)", e); 982 } 983 finally 984 { 985 unlockExclusive(); 986 } 987 throw new UnknownEntityException("Unknown role '" + role + "'"); 988 } 989 990 /** 991 * Removes a Permission from the system. 992 * 993 * @param permission The object describing the permission to be removed. 994 * @throws DataBackendException if there was an error accessing the data 995 * backend. 996 * @throws UnknownEntityException if the permission does not exist. 997 */ 998 public synchronized void removePermission(Permission permission) 999 throws DataBackendException, UnknownEntityException 1000 { 1001 boolean permissionExists = false; 1002 try 1003 { 1004 lockExclusive(); 1005 permissionExists = checkExists(permission); 1006 if (permissionExists) 1007 { 1008 Criteria criteria = PermissionPeerManager.buildCriteria(permission); 1009 PermissionPeerManager.doDelete(criteria); 1010 getAllPermissions().remove(permission); 1011 return; 1012 } 1013 } 1014 catch (Exception e) 1015 { 1016 throw new DataBackendException("removePermission(Permission)", e); 1017 } 1018 finally 1019 { 1020 unlockExclusive(); 1021 } 1022 throw new UnknownEntityException("Unknown permission '" 1023 + permission + "'"); 1024 } 1025 1026 /** 1027 * Renames an existing Group. 1028 * 1029 * @param group The object describing the group to be renamed. 1030 * @param name the new name for the group. 1031 * @throws DataBackendException if there was an error accessing the data 1032 * backend. 1033 * @throws UnknownEntityException if the group does not exist. 1034 */ 1035 public synchronized void renameGroup(Group group, String name) 1036 throws DataBackendException, UnknownEntityException 1037 { 1038 boolean groupExists = false; 1039 try 1040 { 1041 lockExclusive(); 1042 groupExists = checkExists(group); 1043 if (groupExists) 1044 { 1045 group.setName(name); 1046 Criteria criteria = GroupPeerManager.buildCriteria(group); 1047 GroupPeerManager.doUpdate(criteria); 1048 return; 1049 } 1050 } 1051 catch (Exception e) 1052 { 1053 throw new DataBackendException("renameGroup(Group,String)", e); 1054 } 1055 finally 1056 { 1057 unlockExclusive(); 1058 } 1059 throw new UnknownEntityException("Unknown group '" + group + "'"); 1060 } 1061 1062 /** 1063 * Renames an existing Role. 1064 * 1065 * @param role The object describing the role to be renamed. 1066 * @param name the new name for the role. 1067 * @throws DataBackendException if there was an error accessing the data 1068 * backend. 1069 * @throws UnknownEntityException if the role does not exist. 1070 */ 1071 public synchronized void renameRole(Role role, String name) 1072 throws DataBackendException, UnknownEntityException 1073 { 1074 boolean roleExists = false; 1075 try 1076 { 1077 lockExclusive(); 1078 roleExists = checkExists(role); 1079 if (roleExists) 1080 { 1081 role.setName(name); 1082 Criteria criteria = RolePeerManager.buildCriteria(role); 1083 RolePeerManager.doUpdate(criteria); 1084 return; 1085 } 1086 } 1087 catch (Exception e) 1088 { 1089 throw new DataBackendException("renameRole(Role,String)", e); 1090 } 1091 finally 1092 { 1093 unlockExclusive(); 1094 } 1095 throw new UnknownEntityException("Unknown role '" + role + "'"); 1096 } 1097 1098 /** 1099 * Renames an existing Permission. 1100 * 1101 * @param permission The object describing the permission to be renamed. 1102 * @param name the new name for the permission. 1103 * @throws DataBackendException if there was an error accessing the data 1104 * backend. 1105 * @throws UnknownEntityException if the permission does not exist. 1106 */ 1107 public synchronized void renamePermission(Permission permission, 1108 String name) 1109 throws DataBackendException, UnknownEntityException 1110 { 1111 boolean permissionExists = false; 1112 try 1113 { 1114 lockExclusive(); 1115 permissionExists = checkExists(permission); 1116 if (permissionExists) 1117 { 1118 permission.setName(name); 1119 Criteria criteria = PermissionPeerManager.buildCriteria(permission); 1120 PermissionPeerManager.doUpdate(criteria); 1121 return; 1122 } 1123 } 1124 catch (Exception e) 1125 { 1126 throw new DataBackendException( 1127 "renamePermission(Permission,name)", e); 1128 } 1129 finally 1130 { 1131 unlockExclusive(); 1132 } 1133 throw new UnknownEntityException("Unknown permission '" 1134 + permission + "'"); 1135 } 1136 1137 /* Service specific implementation methods */ 1138 1139 /** 1140 * Determines if the <code>Group</code> exists in the security system. 1141 * 1142 * @param group a <code>Group</code> value 1143 * @return true if the group exists in the system, false otherwise 1144 * @throws DataBackendException when more than one Group with 1145 * the same name exists. 1146 * @throws Exception A generic exception. 1147 */ 1148 protected boolean checkExists(Group group) 1149 throws DataBackendException, Exception 1150 { 1151 return GroupPeerManager.checkExists(group); 1152 } 1153 1154 /** 1155 * Determines if the <code>Role</code> exists in the security system. 1156 * 1157 * @param role a <code>Role</code> value 1158 * @return true if the role exists in the system, false otherwise 1159 * @throws DataBackendException when more than one Role with 1160 * the same name exists. 1161 * @throws Exception A generic exception. 1162 */ 1163 protected boolean checkExists(Role role) 1164 throws DataBackendException, Exception 1165 { 1166 return RolePeerManager.checkExists(role); 1167 } 1168 1169 /** 1170 * Determines if the <code>Permission</code> exists in the security system. 1171 * 1172 * @param permission a <code>Permission</code> value 1173 * @return true if the permission exists in the system, false otherwise 1174 * @throws DataBackendException when more than one Permission with 1175 * the same name exists. 1176 * @throws Exception A generic exception. 1177 */ 1178 protected boolean checkExists(Permission permission) 1179 throws DataBackendException, Exception 1180 { 1181 return PermissionPeerManager.checkExists(permission); 1182 } 1183 1184 1185 /** 1186 * Retrieves all groups defined in the system. 1187 * 1188 * @return the names of all groups defined in the system. 1189 * @throws DataBackendException if there was an error accessing the 1190 * data backend. 1191 */ 1192 public GroupSet getAllGroups() throws DataBackendException 1193 { 1194 return getGroups(new Criteria()); 1195 } 1196 1197 1198 /** 1199 * Retrieves all permissions defined in the system. 1200 * 1201 * @return the names of all roles defined in the system. 1202 * @throws DataBackendException if there was an error accessing the 1203 * data backend. 1204 */ 1205 public PermissionSet getAllPermissions() throws DataBackendException 1206 { 1207 return getPermissions(new Criteria()); 1208 } 1209 1210 1211 /** 1212 * Retrieves all roles defined in the system. 1213 * 1214 * @return the names of all roles defined in the system. 1215 * @throws DataBackendException if there was an error accessing the 1216 * data backend. 1217 */ 1218 public RoleSet getAllRoles() throws DataBackendException 1219 { 1220 return getRoles(new Criteria()); 1221 } 1222 1223 1224 /** 1225 * Retrieve a set of users that meet the specified criteria. 1226 * 1227 * As the keys for the criteria, you should use the constants that 1228 * are defined in {@link User} interface, plus the names 1229 * of the custom attributes you added to your user representation 1230 * in the data storage. Use verbatim names of the attributes - 1231 * without table name prefix in case of Torque implementation. 1232 * 1233 * @param criteria The criteria of selection. 1234 * @return a List of users meeting the criteria. 1235 * @throws DataBackendException if there is a problem accessing the 1236 * storage. 1237 */ 1238 public List getUserList(Object criteria) throws DataBackendException 1239 { 1240 return getUserManager().retrieveList(criteria); 1241 } 1242 1243 }