View Javadoc

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