View Javadoc

    1   package org.apache.turbine.services.security.torque;
    2
    3   /*
    4    * Licensed to the Apache Software Foundation (ASF) under one
    5    * or more contributor license agreements.  See the NOTICE file
    6    * distributed with this work for additional information
    7    * regarding copyright ownership.  The ASF licenses this file
    8    * to you under the Apache License, Version 2.0 (the
    9    * "License"); you may not use this file except in compliance
    10   * with the License.  You may obtain a copy of the License at
    11   *
    12   *   http://www.apache.org/licenses/LICENSE-2.0
    13   *
    14   * Unless required by applicable law or agreed to in writing,
    15   * software distributed under the License is distributed on an
    16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    17   * KIND, either express or implied.  See the License for the
    18   * specific language governing permissions and limitations
    19   * under the License.
    20   */
    21
    22  import java.beans.PropertyDescriptor;
    23
    24  import java.util.ArrayList;
    25  import java.util.Iterator;
    26  import java.util.List;
    27
    28  import org.apache.commons.configuration.Configuration;
    29
    30  import org.apache.commons.logging.Log;
    31  import org.apache.commons.logging.LogFactory;
    32
    33  import org.apache.turbine.om.security.Group;
    34  import org.apache.turbine.om.security.Role;
    35  import org.apache.turbine.om.security.User;
    36  import org.apache.turbine.services.InitializationException;
    37  import org.apache.turbine.services.security.TurbineSecurity;
    38  import org.apache.turbine.services.security.torque.om.TurbineUserGroupRolePeer;
    39  import org.apache.turbine.util.security.DataBackendException;
    40  import org.apache.turbine.util.security.RoleSet;
    41
    42  import org.apache.torque.TorqueException;
    43  import org.apache.torque.om.Persistent;
    44  import org.apache.torque.util.BasePeer;
    45  import org.apache.torque.util.Criteria;
    46
    47  /**
    48   * This class capsulates all direct Peer access for the Role entities.
    49   * It allows the exchange of the default Turbine supplied TurbineRolePeer
    50   * class against a custom class
    51   *
    52   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    53   * @version $Id: RolePeerManager.java 1096130 2011-04-23 10:37:19Z ludwig $
    54   */
    55
    56  public class RolePeerManager
    57      implements RolePeerManagerConstants
    58  {
    59      /** The class of the Peer the TorqueSecurityService uses */
    60      private static Class rolePeerClass = null;
    61
    62      /** The class name of the objects returned by the configured peer. */
    63      private static Class roleObject = null;
    64
    65      /** The name of the Table used for Role Object queries  */
    66      private static String tableName = null;
    67
    68      /** The name of the column used as "Name" Column */
    69      private static String nameColumn = null;
    70
    71      /** The name of the column used as "Id" Column */
    72      private static String idColumn = null;
    73
    74      /** The "Name" property descriptor */
    75      private static PropertyDescriptor namePropDesc = null;
    76
    77      /** The "Id" property descriptor */
    78      private static PropertyDescriptor idPropDesc = null;
    79
    80      /** Logging */
    81      static Log log = LogFactory.getLog(RolePeerManager.class);
    82
    83      /**
    84       * Initializes the RolePeerManager, loading the class object for the
    85       * Peer used to retrieve Role objects
    86       *
    87       * @param conf The configuration object used to configure the Manager
    88       *
    89       * @exception InitializationException A problem occured during
    90       *            initialization
    91       */
    92
    93      public static void init(Configuration conf)
    94          throws InitializationException
    95      {
    96          String rolePeerClassName = conf.getString(ROLE_PEER_CLASS_KEY,
    97                                                    ROLE_PEER_CLASS_DEFAULT);
    98
    99          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