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