View Javadoc

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