    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