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 534527 2007-05-02 16:10:59Z tv $
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