001 package org.apache.turbine.services.security.torque;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 import java.beans.PropertyDescriptor;
023
024 import java.util.ArrayList;
025 import java.util.Iterator;
026 import java.util.List;
027
028 import org.apache.commons.configuration.Configuration;
029
030 import org.apache.commons.logging.Log;
031 import org.apache.commons.logging.LogFactory;
032
033 import org.apache.torque.TorqueException;
034 import org.apache.torque.om.Persistent;
035 import org.apache.torque.util.BasePeer;
036 import org.apache.torque.util.Criteria;
037
038 import org.apache.turbine.om.security.Group;
039 import org.apache.turbine.services.InitializationException;
040 import org.apache.turbine.services.security.TurbineSecurity;
041 import org.apache.turbine.util.security.DataBackendException;
042 import org.apache.turbine.util.security.GroupSet;
043
044 /**
045 * This class capsulates all direct Peer access for the Group entities.
046 * It allows the exchange of the default Turbine supplied TurbineGroupPeer
047 * class against a custom class.
048 *
049 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
050 * @version $Id: GroupPeerManager.java 1096130 2011-04-23 10:37:19Z ludwig $
051 *
052 */
053 public class GroupPeerManager
054 implements GroupPeerManagerConstants
055 {
056 /** The class of the Peer the TorqueSecurityService uses */
057 private static Class groupPeerClass = null;
058
059 /** The class name of the objects returned by the configured peer. */
060 private static Class groupObject = null;
061
062 /** The name of the Table used for Group Object queries */
063 private static String tableName = null;
064
065 /** The name of the column used as "Name" Column */
066 private static String nameColumn = null;
067
068 /** The name of the column used as "Id" Column */
069 private static String idColumn = null;
070
071 /** The "Name" property descriptor */
072 private static PropertyDescriptor namePropDesc = null;
073
074 /** The "Id" property descriptor */
075 private static PropertyDescriptor idPropDesc = null;
076
077 /** Logging */
078 static Log log = LogFactory.getLog(GroupPeerManager.class);
079
080 /**
081 * Initializes the GroupPeerManager, loading the class object for the
082 * Peer used to retrieve Group objects
083 *
084 * @param conf The configuration object used to configure the Manager
085 *
086 * @exception InitializationException A problem occured during initialization
087 */
088
089 public static void init(Configuration conf)
090 throws InitializationException
091 {
092 String groupPeerClassName = conf.getString(GROUP_PEER_CLASS_KEY,
093 GROUP_PEER_CLASS_DEFAULT);
094 String groupObjectName = null;
095
096 try
097 {
098 groupPeerClass = Class.forName(groupPeerClassName);
099
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