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