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 534527 2007-05-02 16:10:59Z tv $
051: *
052: */
053: public class GroupPeerManager implements GroupPeerManagerConstants {
054: /** The class of the Peer the TorqueSecurityService uses */
055: private static Class groupPeerClass = null;
056:
057: /** The class name of the objects returned by the configured peer. */
058: private static Class groupObject = null;
059:
060: /** The name of the Table used for Group Object queries */
061: private static String tableName = null;
062:
063: /** The name of the column used as "Name" Column */
064: private static String nameColumn = null;
065:
066: /** The name of the column used as "Id" Column */
067: private static String idColumn = null;
068:
069: /** The "Name" property descriptor */
070: private static PropertyDescriptor namePropDesc = null;
071:
072: /** The "Id" property descriptor */
073: private static PropertyDescriptor idPropDesc = null;
074:
075: /** Logging */
076: static Log log = LogFactory.getLog(GroupPeerManager.class);
077:
078: /**
079: * Initializes the GroupPeerManager, loading the class object for the
080: * Peer used to retrieve Group objects
081: *
082: * @param conf The configuration object used to configure the Manager
083: *
084: * @exception InitializationException A problem occured during initialization
085: */
086:
087: public static void init(Configuration conf)
088: throws InitializationException {
089: String groupPeerClassName = conf.getString(
090: GROUP_PEER_CLASS_KEY, GROUP_PEER_CLASS_DEFAULT);
091: String groupObjectName = null;
092:
093: try {
094: groupPeerClass = Class.forName(groupPeerClassName);
095:
096: tableName = (String) groupPeerClass.getField("TABLE_NAME")
097: .get(null);
098:
099: //
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(
114: conf.getString(GROUP_NAME_COLUMN_KEY,
115: GROUP_NAME_COLUMN_DEFAULT)).get(null);
116:
117: idColumn = (String) groupPeerClass.getField(
118: conf.getString(GROUP_ID_COLUMN_KEY,
119: GROUP_ID_COLUMN_DEFAULT)).get(null);
120:
121: namePropDesc = new PropertyDescriptor(conf.getString(
122: GROUP_NAME_PROPERTY_KEY,
123: GROUP_NAME_PROPERTY_DEFAULT), groupObject);
124:
125: idPropDesc = new PropertyDescriptor(conf.getString(
126: GROUP_ID_PROPERTY_KEY, GROUP_ID_PROPERTY_DEFAULT),
127: groupObject);
128: } catch (Exception e) {
129: if (groupPeerClassName == null || groupPeerClass == null) {
130: throw new InitializationException(
131: "Could not find GroupPeer class ("
132: + groupPeerClassName + ")", e);
133: }
134: if (tableName == null) {
135: throw new InitializationException(
136: "Failed to get the table name from the Peer object",
137: e);
138: }
139:
140: if (groupObject == null || groupObjectName == null) {
141: throw new InitializationException(
142: "Failed to get the object type from the Peer object",
143: e);
144: }
145:
146: if (nameColumn == null || namePropDesc == null) {
147: throw new InitializationException("GroupPeer "
148: + groupPeerClassName
149: + " has no name column information!", e);
150: }
151: if (idColumn == null || idPropDesc == null) {
152: throw new InitializationException("GroupPeer "
153: + groupPeerClassName
154: + " has no id column information!", e);
155: }
156: }
157: }
158:
159: /**
160: * Get the name of this table.
161: *
162: * @return A String with the name of the table.
163: */
164: public static String getTableName() {
165: return tableName;
166: }
167:
168: /**
169: * Returns the fully qualified name of the Column to
170: * use as the Name Column for a group
171: *
172: * @return A String containing the column name
173: */
174: public static String getNameColumn() {
175: return nameColumn;
176: }
177:
178: /**
179: * Returns the fully qualified name of the Column to
180: * use as the Id Column for a group
181: *
182: * @return A String containing the column id
183: */
184: public static String getIdColumn() {
185: return idColumn;
186: }
187:
188: /**
189: * Returns the full name of a column.
190: *
191: * @param name The column to fully qualify
192: *
193: * @return A String with the full name of the column.
194: */
195: public static String getColumnName(String name) {
196: StringBuffer sb = new StringBuffer();
197: sb.append(getTableName());
198: sb.append(".");
199: sb.append(name);
200: return sb.toString();
201: }
202:
203: /**
204: * Returns a new, empty object for the underlying peer.
205: * Used to create a new underlying object
206: *
207: * @return A new object which is compatible to the Peer
208: * and can be used as a Group object
209: *
210: */
211:
212: public static Persistent newPersistentInstance() {
213: Persistent obj = null;
214:
215: if (groupObject == null) {
216: // This can happen if the Turbine wants to determine the
217: // name of the anonymous user before the security service
218: // has been initialized. In this case, the Peer Manager
219: // has not yet been inited and the groupObject is still
220: // null. Return null in this case.
221: //
222: return obj;
223: }
224:
225: try {
226: obj = (Persistent) groupObject.newInstance();
227: } catch (Exception e) {
228: log.error("Could not instantiate a group object", e);
229: obj = null;
230: }
231: return obj;
232: }
233:
234: /**
235: * Retrieves/assembles a GroupSet of all of the Groups.
236: *
237: * @return A set of all the Groups in the system
238: * @exception Exception A generic exception.
239: */
240: public static GroupSet retrieveSet() throws Exception {
241: return retrieveSet(new Criteria());
242: }
243:
244: /**
245: * Retrieves/assembles a GroupSet based on the Criteria passed in
246: *
247: * @param criteria A criteria containing a pre-assembled set of criterias
248: * for the GroupSet
249: *
250: * @return A Set of groups which fulfil the required criterias
251: *
252: * @exception Exception A generic exception
253: *
254: */
255: public static GroupSet retrieveSet(Criteria criteria)
256: throws Exception {
257: List results = doSelect(criteria);
258: GroupSet gs = new GroupSet();
259:
260: for (Iterator it = results.iterator(); it.hasNext();) {
261: gs.add((Group) it.next());
262: }
263: return gs;
264: }
265:
266: /**
267: * Checks if a Group is defined in the system. The name
268: * is used as query criteria.
269: *
270: * @param group The Group to be checked.
271: * @return <code>true</code> if given Group exists in the system.
272: * @throws DataBackendException when more than one Group with
273: * the same name exists.
274: * @throws Exception A generic exception.
275: */
276: public static boolean checkExists(Group group)
277: throws DataBackendException, Exception {
278: Criteria criteria = new Criteria();
279:
280: criteria.addSelectColumn(getIdColumn());
281:
282: criteria.add(getNameColumn(), group.getName());
283:
284: List results = BasePeer.doSelect(criteria);
285:
286: if (results.size() > 1) {
287: throw new DataBackendException("Multiple groups named '"
288: + group.getName() + "' exist!");
289: }
290:
291: return (results.size() == 1);
292: }
293:
294: /*
295: * ========================================================================
296: *
297: * WARNING! Do not read on if you have a weak stomach. What follows here
298: * are some abominations thanks to the braindead static peers of Torque
299: * and the rigidity of Java....
300: *
301: * ========================================================================
302: *
303: */
304:
305: /**
306: * Calls buildCriteria(Group group) in the configured GroupPeer. If you get
307: * a ClassCastException in this routine, you put a Group object into this
308: * method which can't be cast into an object for the TorqueSecurityService. This is a
309: * configuration error most of the time.
310: *
311: * @param group An object which implements the Group interface
312: *
313: * @return A criteria for the supplied group object
314: */
315:
316: public static Criteria buildCriteria(Group group) {
317: Criteria crit;
318:
319: try {
320: Class[] clazz = new Class[] { groupObject };
321: Object[] params = new Object[] { ((TorqueGroup) group)
322: .getPersistentObj() };
323:
324: crit = (Criteria) groupPeerClass.getMethod("buildCriteria",
325: clazz).invoke(null, params);
326: } catch (Exception e) {
327: crit = null;
328: }
329:
330: return crit;
331: }
332:
333: /**
334: * Invokes doUpdate(Criteria c) on the configured Peer Object
335: *
336: * @param criteria A Criteria Object
337: *
338: * @exception TorqueException A problem occured.
339: */
340:
341: public static void doUpdate(Criteria criteria)
342: throws TorqueException {
343: try {
344: Class[] clazz = new Class[] { Criteria.class };
345: Object[] params = new Object[] { criteria };
346:
347: groupPeerClass.getMethod("doUpdate", clazz).invoke(null,
348: params);
349: } catch (Exception e) {
350: throw new TorqueException("doUpdate failed", e);
351: }
352: }
353:
354: /**
355: * Invokes doInsert(Criteria c) on the configured Peer Object
356: *
357: * @param criteria A Criteria Object
358: *
359: * @exception TorqueException A problem occured.
360: */
361:
362: public static void doInsert(Criteria criteria)
363: throws TorqueException {
364: try {
365: Class[] clazz = new Class[] { Criteria.class };
366: Object[] params = new Object[] { criteria };
367:
368: groupPeerClass.getMethod("doInsert", clazz).invoke(null,
369: params);
370: } catch (Exception e) {
371: throw new TorqueException("doInsert failed", e);
372: }
373: }
374:
375: /**
376: * Invokes doSelect(Criteria c) on the configured Peer Object
377: *
378: * @param criteria A Criteria Object
379: *
380: * @return A List of Group Objects selected by the Criteria
381: *
382: * @exception TorqueException A problem occured.
383: */
384: public static List doSelect(Criteria criteria)
385: throws TorqueException {
386: List list;
387:
388: try {
389: Class[] clazz = new Class[] { Criteria.class };
390: Object[] params = new Object[] { criteria };
391:
392: list = (List) groupPeerClass.getMethod("doSelect", clazz)
393: .invoke(null, params);
394: } catch (Exception e) {
395: throw new TorqueException("doSelect failed", e);
396: }
397: List newList = new ArrayList(list.size());
398:
399: //
400: // Wrap the returned Objects into the configured Peer Objects.
401: //
402: for (Iterator it = list.iterator(); it.hasNext();) {
403: Group dr = getNewGroup((Persistent) it.next());
404: newList.add(dr);
405: }
406:
407: return newList;
408: }
409:
410: /**
411: * Invokes doDelete(Criteria c) on the configured Peer Object
412: *
413: * @param criteria A Criteria Object
414: *
415: * @exception TorqueException A problem occured.
416: */
417: public static void doDelete(Criteria criteria)
418: throws TorqueException {
419: try {
420: Class[] clazz = new Class[] { Criteria.class };
421: Object[] params = new Object[] { criteria };
422:
423: groupPeerClass.getMethod("doDelete", clazz).invoke(null,
424: params);
425: } catch (Exception e) {
426: throw new TorqueException("doDelete failed", e);
427: }
428: }
429:
430: /**
431: * Invokes setName(String s) on the supplied base object
432: *
433: * @param obj The object to use for setting the name
434: *
435: * @param name The Name to set
436: */
437: public static void setGroupName(Persistent obj, String name) {
438: if (obj == null) {
439: return;
440: }
441:
442: try {
443: Object[] params = new Object[] { name };
444: namePropDesc.getWriteMethod().invoke(obj, params);
445: } catch (ClassCastException cce) {
446: String msg = obj.getClass().getName()
447: + " does not seem to be a Group Object!";
448: log.error(msg);
449: throw new RuntimeException(msg);
450: } catch (Exception e) {
451: log.error(e, e);
452: }
453: }
454:
455: /**
456: * Invokes getName() on the supplied base object
457: *
458: * @param obj The object to use for getting the name
459: *
460: * @return A string containing the name
461: */
462: public static String getGroupName(Persistent obj) {
463: String name = null;
464:
465: if (obj == null) {
466: return null;
467: }
468:
469: try {
470: name = (String) namePropDesc.getReadMethod().invoke(obj,
471: new Object[] {});
472: } catch (ClassCastException cce) {
473: String msg = obj.getClass().getName()
474: + " does not seem to be a Group Object!";
475: log.error(msg);
476: throw new RuntimeException(msg);
477: } catch (Exception e) {
478: log.error(e, e);
479: }
480: return name;
481: }
482:
483: /**
484: * Invokes setId(int n) on the supplied base object
485: *
486: * @param obj The object to use for setting the name
487: * @param id The new Id
488: */
489: public static void setId(Persistent obj, int id) {
490: if (obj == null) {
491: return;
492: }
493:
494: try {
495: Object[] params = new Object[] { Integer.TYPE };
496: idPropDesc.getWriteMethod().invoke(obj, params);
497: } catch (ClassCastException cce) {
498: String msg = obj.getClass().getName()
499: + " does not seem to be a Group Object!";
500: log.error(msg);
501: throw new RuntimeException(msg);
502: } catch (Exception e) {
503: log.error(e, e);
504: }
505: }
506:
507: /**
508: * Invokes getId() on the supplied base object
509: *
510: * @param obj The object to use for getting the id
511: *
512: * @return The Id of this object
513: */
514: public static Integer getIdAsObj(Persistent obj) {
515: Integer id = null;
516:
517: if (obj == null) {
518: return new Integer(0);
519: }
520:
521: try {
522: id = (Integer) idPropDesc.getReadMethod().invoke(obj,
523: new Object[] {});
524: } catch (ClassCastException cce) {
525: String msg = obj.getClass().getName()
526: + " does not seem to be a Group Object!";
527: log.error(msg);
528: throw new RuntimeException(msg);
529: } catch (Exception e) {
530: log.error(e, e);
531: }
532: return id;
533: }
534:
535: /**
536: * Returns the Class of the configured Object class
537: * from the peer
538: *
539: * @return The class of the objects returned by the configured peer
540: *
541: */
542:
543: private static Class getPersistenceClass() {
544: Class persistenceClass = null;
545:
546: try {
547: Object[] params = new Object[0];
548:
549: persistenceClass = (Class) groupPeerClass.getMethod(
550: "getOMClass", (Class[]) null).invoke(null, params);
551: } catch (Exception e) {
552: persistenceClass = null;
553: }
554:
555: return persistenceClass;
556: }
557:
558: /**
559: * Returns a new, configured Group Object with
560: * a supplied Persistent object at its core
561: *
562: * @param p The persistent object
563: *
564: * @return a new, configured Group Object
565: *
566: * @exception Exception Could not create a new Object
567: *
568: */
569:
570: public static Group getNewGroup(Persistent p) {
571: Group g = null;
572: try {
573: Class groupWrapperClass = TurbineSecurity.getGroupClass();
574:
575: Class[] clazz = new Class[] { Persistent.class };
576: Object[] params = new Object[] { p };
577:
578: g = (Group) groupWrapperClass.getConstructor(clazz)
579: .newInstance(params);
580: } catch (Exception e) {
581: log
582: .error(
583: "Could not instantiate a new group from supplied persistent: ",
584: e);
585: }
586:
587: return g;
588: }
589: }
|