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