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.beans.PropertyDescriptor; 023 024 import java.util.ArrayList; 025 import java.util.Iterator; 026 import java.util.List; 027 028 import org.apache.commons.configuration.Configuration; 029 030 import org.apache.commons.logging.Log; 031 import org.apache.commons.logging.LogFactory; 032 033 import org.apache.turbine.om.security.Group; 034 import org.apache.turbine.om.security.Role; 035 import org.apache.turbine.om.security.User; 036 import org.apache.turbine.services.InitializationException; 037 import org.apache.turbine.services.security.TurbineSecurity; 038 import org.apache.turbine.services.security.torque.om.TurbineUserGroupRolePeer; 039 import org.apache.turbine.util.security.DataBackendException; 040 import org.apache.turbine.util.security.RoleSet; 041 042 import org.apache.torque.TorqueException; 043 import org.apache.torque.om.Persistent; 044 import org.apache.torque.util.BasePeer; 045 import org.apache.torque.util.Criteria; 046 047 /** 048 * This class capsulates all direct Peer access for the Role entities. 049 * It allows the exchange of the default Turbine supplied TurbineRolePeer 050 * class against a custom class 051 * 052 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> 053 * @version $Id: RolePeerManager.java 1096130 2011-04-23 10:37:19Z ludwig $ 054 */ 055 056 public class RolePeerManager 057 implements RolePeerManagerConstants 058 { 059 /** The class of the Peer the TorqueSecurityService uses */ 060 private static Class rolePeerClass = null; 061 062 /** The class name of the objects returned by the configured peer. */ 063 private static Class roleObject = null; 064 065 /** The name of the Table used for Role Object queries */ 066 private static String tableName = null; 067 068 /** The name of the column used as "Name" Column */ 069 private static String nameColumn = null; 070 071 /** The name of the column used as "Id" Column */ 072 private static String idColumn = null; 073 074 /** The "Name" property descriptor */ 075 private static PropertyDescriptor namePropDesc = null; 076 077 /** The "Id" property descriptor */ 078 private static PropertyDescriptor idPropDesc = null; 079 080 /** Logging */ 081 static Log log = LogFactory.getLog(RolePeerManager.class); 082 083 /** 084 * Initializes the RolePeerManager, loading the class object for the 085 * Peer used to retrieve Role objects 086 * 087 * @param conf The configuration object used to configure the Manager 088 * 089 * @exception InitializationException A problem occured during 090 * initialization 091 */ 092 093 public static void init(Configuration conf) 094 throws InitializationException 095 { 096 String rolePeerClassName = conf.getString(ROLE_PEER_CLASS_KEY, 097 ROLE_PEER_CLASS_DEFAULT); 098 099 String roleObjectName = null; 100 101 try 102 { 103 rolePeerClass = Class.forName(rolePeerClassName); 104 105 tableName = 106 (String) rolePeerClass.getField("TABLE_NAME").get(null); 107 108 // 109 // We have either an user configured Object class or we use the 110 // default as supplied by the Peer class 111 // 112 113 // Default from Peer, can be overridden 114 115 roleObject = getPersistenceClass(); 116 117 roleObjectName = conf.getString(ROLE_CLASS_KEY, 118 roleObject.getName()); 119 120 // Maybe the user set a new value... 121 roleObject = Class.forName(roleObjectName); 122 123 /* If any of the following Field queries fails, the role 124 * subsystem is unusable. So check this right here at init time, 125 * which saves us much time and hassle if it fails... 126 */ 127 128 nameColumn = (String) rolePeerClass.getField( 129 conf.getString(ROLE_NAME_COLUMN_KEY, 130 ROLE_NAME_COLUMN_DEFAULT) 131 ).get(null); 132 133 idColumn = (String) rolePeerClass.getField( 134 conf.getString(ROLE_ID_COLUMN_KEY, 135 ROLE_ID_COLUMN_DEFAULT) 136 ).get(null); 137 138 namePropDesc = new PropertyDescriptor( 139 conf.getString(ROLE_NAME_PROPERTY_KEY, 140 ROLE_NAME_PROPERTY_DEFAULT), 141 roleObject); 142 143 idPropDesc = new PropertyDescriptor( 144 conf.getString(ROLE_ID_PROPERTY_KEY, 145 ROLE_ID_PROPERTY_DEFAULT), 146 roleObject); 147 148 } 149 catch (Exception e) 150 { 151 if (rolePeerClassName == null || rolePeerClass == null) 152 { 153 throw new InitializationException( 154 "Could not find RolePeer class (" 155 + rolePeerClassName + ")", e); 156 } 157 if (tableName == null) 158 { 159 throw new InitializationException( 160 "Failed to get the table name from the Peer object", e); 161 } 162 163 if (roleObject == null || roleObjectName == null) 164 { 165 throw new InitializationException( 166 "Failed to get the object type from the Peer object", e); 167 } 168 169 170 if (nameColumn == null || namePropDesc == null) 171 { 172 throw new InitializationException( 173 "RolePeer " + rolePeerClassName 174 + " has no name column information!", e); 175 } 176 if (idColumn == null || idPropDesc == null) 177 { 178 throw new InitializationException( 179 "RolePeer " + rolePeerClassName 180 + " has no id column information!", e); 181 } 182 } 183 } 184 185 /** 186 * Get the name of this table. 187 * 188 * @return A String with the name of the table. 189 */ 190 public static String getTableName() 191 { 192 return tableName; 193 } 194 195 /** 196 * Returns the fully qualified name of the Column to 197 * use as the Name Column for a role 198 * 199 * @return A String containing the column name 200 */ 201 public static String getNameColumn() 202 { 203 return nameColumn; 204 } 205 206 /** 207 * Returns the fully qualified name of the Column to 208 * use as the Id Column for a role 209 * 210 * @return A String containing the column id 211 */ 212 public static String getIdColumn() 213 { 214 return idColumn; 215 } 216 217 /** 218 * Returns the full name of a column. 219 * 220 * @param name The column to fully qualify 221 * 222 * @return A String with the full name of the column. 223 */ 224 public static String getColumnName(String name) 225 { 226 StringBuffer sb = new StringBuffer(); 227 sb.append(getTableName()); 228 sb.append("."); 229 sb.append(name); 230 return sb.toString(); 231 } 232 233 /** 234 * Returns a new, empty object for the underlying peer. 235 * Used to create a new underlying object 236 * 237 * @return A new object which is compatible to the Peer 238 * and can be used as a User object 239 * 240 */ 241 242 public static Persistent newPersistentInstance() 243 { 244 Persistent obj = null; 245 246 if (roleObject == null) 247 { 248 // This can happen if the Turbine wants to determine the 249 // name of the anonymous user before the security service 250 // has been initialized. In this case, the Peer Manager 251 // has not yet been inited and the roleObject is still 252 // null. Return null in this case. 253 // 254 return obj; 255 } 256 257 try 258 { 259 obj = (Persistent) roleObject.newInstance(); 260 } 261 catch (Exception e) 262 { 263 log.error("Could not instantiate a role object", e); 264 obj = null; 265 } 266 return obj; 267 } 268 269 /** 270 * Retrieves/assembles a RoleSet based on the Criteria passed in 271 * 272 * @param criteria A criteria containing a pre-assembled set of criterias 273 * for the RoleSet 274 * 275 * @return A Set of roles which fulfil the required criterias 276 * 277 * @exception Exception A generic exception. 278 * 279 */ 280 public static RoleSet retrieveSet(Criteria criteria) 281 throws Exception 282 { 283 List results = doSelect(criteria); 284 RoleSet rs = new RoleSet(); 285 286 for (Iterator it = results.iterator(); it.hasNext(); ) 287 { 288 rs.add((Role) it.next()); 289 } 290 return rs; 291 } 292 293 /** 294 * Retrieves a set of Roles that an User was assigned in a Group 295 * 296 * @param user An user object 297 * @param group A group object 298 * 299 * @return A Set of Roles of this User in the Group 300 * 301 * @exception Exception A generic exception. 302 */ 303 public static RoleSet retrieveSet(User user, Group group) 304 throws Exception 305 { 306 Criteria criteria = new Criteria(); 307 308 criteria.add(UserPeerManager.getNameColumn(), 309 user.getName()); 310 311 criteria.add(TurbineUserGroupRolePeer.GROUP_ID, 312 ((Persistent) group).getPrimaryKey()); 313 314 criteria.addJoin(UserPeerManager.getIdColumn(), 315 TurbineUserGroupRolePeer.USER_ID); 316 317 criteria.addJoin(TurbineUserGroupRolePeer.ROLE_ID, getIdColumn()); 318 319 return retrieveSet(criteria); 320 } 321 322 /** 323 * Checks if a Role is defined in the system. The name 324 * is used as query criteria. 325 * 326 * @param role The Role to be checked. 327 * @return <code>true</code> if given Role exists in the system. 328 * @throws DataBackendException when more than one Role with 329 * the same name exists. 330 * @throws Exception A generic exception. 331 */ 332 public static boolean checkExists(Role role) 333 throws DataBackendException, Exception 334 { 335 Criteria criteria = new Criteria(); 336 337 criteria.addSelectColumn(getIdColumn()); 338 339 criteria.add(getNameColumn(), role.getName()); 340 341 List results = BasePeer.doSelect(criteria); 342 343 if (results.size() > 1) 344 { 345 throw new DataBackendException("Multiple roles named '" + 346 role.getName() + "' exist!"); 347 } 348 return (results.size() == 1); 349 } 350 351 /* 352 * ======================================================================== 353 * 354 * WARNING! Do not read on if you have a weak stomach. What follows here 355 * are some abominations thanks to the braindead static peers of Torque 356 * and the rigidity of Java.... 357 * 358 * ======================================================================== 359 * 360 */ 361 362 /** 363 * Calls buildCriteria(Role role) in the configured RolePeer. If you get 364 * a ClassCastException in this routine, you put a Role object into this 365 * method which can't be cast into an object for the TorqueSecurityService. This is a 366 * configuration error most of the time. 367 * 368 * @param role An object which implements the Role interface 369 * 370 * @return A criteria for the supplied role object 371 */ 372 373 public static Criteria buildCriteria(Role role) 374 { 375 Criteria crit; 376 377 try 378 { 379 Class[] clazz = new Class[] { roleObject }; 380 Object[] params = 381 new Object[] { ((TorqueRole) role).getPersistentObj() }; 382 383 crit = (Criteria) rolePeerClass 384 .getMethod("buildCriteria", clazz) 385 .invoke(null, params); 386 } 387 catch (Exception e) 388 { 389 crit = null; 390 } 391 392 return crit; 393 } 394 395 /** 396 * Invokes doUpdate(Criteria c) on the configured Peer Object 397 * 398 * @param criteria A Criteria Object 399 * 400 * @exception TorqueException A problem occured. 401 */ 402 403 public static void doUpdate(Criteria criteria) 404 throws TorqueException 405 { 406 try 407 { 408 Class[] clazz = new Class[] { Criteria.class }; 409 Object[] params = new Object[] { criteria }; 410 411 rolePeerClass 412 .getMethod("doUpdate", clazz) 413 .invoke(null, params); 414 } 415 catch (Exception e) 416 { 417 throw new TorqueException("doUpdate failed", e); 418 } 419 } 420 421 /** 422 * Invokes doInsert(Criteria c) on the configured Peer Object 423 * 424 * @param criteria A Criteria Object 425 * 426 * @exception TorqueException A problem occured. 427 */ 428 429 public static void doInsert(Criteria criteria) 430 throws TorqueException 431 { 432 try 433 { 434 Class[] clazz = new Class[] { Criteria.class }; 435 Object[] params = new Object[] { criteria }; 436 437 rolePeerClass 438 .getMethod("doInsert", clazz) 439 .invoke(null, params); 440 } 441 catch (Exception e) 442 { 443 throw new TorqueException("doInsert failed", e); 444 } 445 } 446 447 /** 448 * Invokes doSelect(Criteria c) on the configured Peer Object 449 * 450 * @param criteria A Criteria Object 451 * 452 * @return A List of Role Objects selected by the Criteria 453 * 454 * @exception TorqueException A problem occured. 455 */ 456 public static List doSelect(Criteria criteria) 457 throws TorqueException 458 { 459 List list; 460 461 try 462 { 463 Class[] clazz = 464 new Class[] { Criteria.class }; 465 Object[] params = new Object[] { criteria }; 466 467 list = (List) rolePeerClass 468 .getMethod("doSelect", clazz) 469 .invoke(null, params); 470 } 471 catch (Exception e) 472 { 473 throw new TorqueException("doSelect failed", e); 474 } 475 List newList = new ArrayList(list.size()); 476 477 // 478 // Wrap the returned Objects into TorqueRoles. 479 // 480 for (Iterator it = list.iterator(); it.hasNext(); ) 481 { 482 Role r = getNewRole((Persistent) it.next()); 483 newList.add(r); 484 } 485 486 return newList; 487 } 488 489 /** 490 * Invokes doDelete(Criteria c) on the configured Peer Object 491 * 492 * @param criteria A Criteria Object 493 * 494 * @exception TorqueException A problem occured. 495 */ 496 public static void doDelete(Criteria criteria) 497 throws TorqueException 498 { 499 try 500 { 501 Class[] clazz = new Class[] { Criteria.class }; 502 Object[] params = new Object[] { criteria }; 503 504 rolePeerClass 505 .getMethod("doDelete", clazz) 506 .invoke(null, params); 507 } 508 catch (Exception e) 509 { 510 throw new TorqueException("doDelete failed", e); 511 } 512 } 513 514 /** 515 * Invokes setName(String s) on the supplied base object 516 * 517 * @param obj The object to use for setting the name 518 * @param name The Name to set 519 * 520 */ 521 public static void setRoleName(Persistent obj, String name) 522 { 523 if (obj == null) 524 { 525 return; 526 } 527 528 try 529 { 530 Object[] params = new Object[] { name }; 531 namePropDesc.getWriteMethod().invoke(obj, params); 532 } 533 catch (ClassCastException cce) 534 { 535 String msg = obj.getClass().getName() + " does not seem to be a Role Object!"; 536 log.error(msg); 537 throw new RuntimeException(msg); 538 } 539 catch (Exception e) 540 { 541 log.error(e, e); 542 } 543 } 544 545 /** 546 * Invokes getName() on the supplied base object 547 * 548 * @param obj The object to use for getting the name 549 * 550 * @return A string containing the name 551 */ 552 public static String getRoleName(Persistent obj) 553 { 554 String name = null; 555 556 if (obj == null) 557 { 558 return null; 559 } 560 561 try 562 { 563 name = (String) namePropDesc 564 .getReadMethod() 565 .invoke(obj, new Object[] {}); 566 } 567 catch (ClassCastException cce) 568 { 569 String msg = obj.getClass().getName() + " does not seem to be a Role Object!"; 570 log.error(msg); 571 throw new RuntimeException(msg); 572 } 573 catch (Exception e) 574 { 575 log.error(e, e); 576 } 577 return name; 578 } 579 580 /** 581 * Invokes setId(int n) on the supplied base object 582 * 583 * @param obj The object to use for setting the name 584 * @param id The new Id 585 */ 586 public static void setId(Persistent obj, int id) 587 { 588 if (obj == null) 589 { 590 return; 591 } 592 593 try 594 { 595 Object[] params = new Object[] { Integer.TYPE }; 596 idPropDesc.getWriteMethod().invoke(obj, params); 597 } 598 catch (ClassCastException cce) 599 { 600 String msg = obj.getClass().getName() + " does not seem to be a Role Object!"; 601 log.error(msg); 602 throw new RuntimeException(msg); 603 } 604 catch (Exception e) 605 { 606 log.error(e, e); 607 } 608 } 609 610 /** 611 * Invokes getId() on the supplied base object 612 * 613 * @param obj The object to use for getting the id 614 * 615 * @return The Id of this object 616 */ 617 public static Integer getIdAsObj(Persistent obj) 618 { 619 Integer id = null; 620 621 if (obj == null) 622 { 623 return new Integer(0); 624 } 625 626 try 627 { 628 id = (Integer) idPropDesc 629 .getReadMethod() 630 .invoke(obj, new Object[] {}); 631 } 632 catch (ClassCastException cce) 633 { 634 String msg = obj.getClass().getName() + " does not seem to be a Role Object!"; 635 log.error(msg); 636 throw new RuntimeException(msg); 637 } 638 catch (Exception e) 639 { 640 log.error(e, e); 641 } 642 return id; 643 } 644 645 /** 646 * Returns the Class of the configured Object class 647 * from the peer 648 * 649 * @return The class of the objects returned by the configured peer 650 */ 651 652 private static Class getPersistenceClass() 653 { 654 Class persistenceClass = null; 655 656 try 657 { 658 Object[] params = new Object[0]; 659 660 persistenceClass = (Class) rolePeerClass 661 .getMethod("getOMClass", (Class[])null) 662 .invoke(null, params); 663 } 664 catch (Exception e) 665 { 666 persistenceClass = null; 667 } 668 669 return persistenceClass; 670 } 671 672 673 /** 674 * Returns a new, configured Role Object with 675 * a supplied Persistent object at its core 676 * 677 * @param p The persistent object 678 * 679 * @return a new, configured Role Object 680 * 681 * @exception Exception Could not create a new Object 682 * 683 */ 684 685 public static Role getNewRole(Persistent p) 686 { 687 Role r = null; 688 try 689 { 690 Class roleWrapperClass = TurbineSecurity.getRoleClass(); 691 692 Class [] clazz = new Class [] { Persistent.class }; 693 Object [] params = new Object [] { p }; 694 695 r = (Role) roleWrapperClass 696 .getConstructor(clazz) 697 .newInstance(params); 698 } 699 catch (Exception e) 700 { 701 log.error("Could not instantiate a new role from supplied persistent: ", e); 702 } 703 704 return r; 705 } 706 } 707