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.torque.TorqueException;
    34  import org.apache.torque.om.Persistent;
    35  import org.apache.torque.util.BasePeer;
    36  import org.apache.torque.util.Criteria;
    37
    38  import org.apache.turbine.om.security.Group;
    39  import org.apache.turbine.services.InitializationException;
    40  import org.apache.turbine.services.security.TurbineSecurity;
    41  import org.apache.turbine.util.security.DataBackendException;
    42  import org.apache.turbine.util.security.GroupSet;
    43
    44  /**
    45   * This class capsulates all direct Peer access for the Group entities.
    46   * It allows the exchange of the default Turbine supplied TurbineGroupPeer
    47   * class against a custom class.
    48   *
    49   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    50   * @version $Id: GroupPeerManager.java 1096130 2011-04-23 10:37:19Z ludwig $
    51   *
    52   */
    53  public class GroupPeerManager
    54      implements GroupPeerManagerConstants
    55  {
    56      /** The class of the Peer the TorqueSecurityService uses */
    57      private static Class groupPeerClass = null;
    58
    59      /** The class name of the objects returned by the configured peer. */
    60      private static Class groupObject = null;
    61
    62      /** The name of the Table used for Group Object queries  */
    63      private static String tableName = null;
    64
    65      /** The name of the column used as "Name" Column */
    66      private static String nameColumn = null;
    67
    68      /** The name of the column used as "Id" Column */
    69      private static String idColumn = null;
    70
    71      /** The "Name" property descriptor */
    72      private static PropertyDescriptor namePropDesc = null;
    73
    74      /** The "Id" property descriptor */
    75      private static PropertyDescriptor idPropDesc = null;
    76
    77      /** Logging */
    78      static Log log = LogFactory.getLog(GroupPeerManager.class);
    79
    80      /**
    81       * Initializes the GroupPeerManager, loading the class object for the
    82       * Peer used to retrieve Group objects
    83       *
    84       * @param conf The configuration object used to configure the Manager
    85       *
    86       * @exception InitializationException A problem occured during initialization
    87       */
    88
    89      public static void init(Configuration conf)
    90          throws InitializationException
    91      {
    92          String groupPeerClassName = conf.getString(GROUP_PEER_CLASS_KEY,
    93                                                     GROUP_PEER_CLASS_DEFAULT);
    94          String groupObjectName = null;
    95
    96          try
    97          {
    98              groupPeerClass = Class.forName(groupPeerClassName);
    99
    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