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