KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > xdoclet > modules > ojb > constraints > ClassDescriptorConstraints


1 package xdoclet.modules.ojb.constraints;
2
3 /* Copyright 2004-2005 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 import java.lang.reflect.Method JavaDoc;
19 import java.lang.reflect.Modifier JavaDoc;
20 import java.util.*;
21
22 import xdoclet.modules.ojb.CommaListIterator;
23 import xdoclet.modules.ojb.LogHelper;
24 import xdoclet.modules.ojb.model.*;
25
26 /**
27  * Checks constraints for class descriptors. Note that constraints may modify the class descriptor.
28  *
29  * @author <a HREF="mailto:tomdz@users.sourceforge.net">Thomas Dudziak (tomdz@users.sourceforge.net)</a>
30  */

31 public class ClassDescriptorConstraints extends ConstraintsBase
32 {
33     /** The interface that row readers must implement */
34     private final static String JavaDoc ROW_READER_INTERFACE = "org.apache.ojb.broker.accesslayer.RowReader";
35     /** The interface that object caches must implement */
36     private final static String JavaDoc OBJECT_CACHE_INTERFACE = "org.apache.ojb.broker.cache.ObjectCache";
37     
38     /**
39      * Checks the given class descriptor.
40      *
41      * @param classDef The class descriptor
42      * @param checkLevel The amount of checks to perform
43      * @exception ConstraintException If a constraint has been violated
44      */

45     public void check(ClassDescriptorDef classDef, String JavaDoc checkLevel) throws ConstraintException
46     {
47         ensureNoTableInfoIfNoRepositoryInfo(classDef, checkLevel);
48         checkModifications(classDef, checkLevel);
49         checkExtents(classDef, checkLevel);
50         ensureTableIfNecessary(classDef, checkLevel);
51         checkFactoryClassAndMethod(classDef, checkLevel);
52         checkInitializationMethod(classDef, checkLevel);
53         checkPrimaryKey(classDef, checkLevel);
54         checkProxyPrefetchingLimit(classDef, checkLevel);
55         checkRowReader(classDef, checkLevel);
56         checkObjectCache(classDef, checkLevel);
57         checkProcedures(classDef, checkLevel);
58     }
59
60     /**
61      * Ensures that generate-table-info is set to false if generate-repository-info is set to false.
62      *
63      * @param classDef The class descriptor
64      * @param checkLevel The current check level (this constraint is checked in all levels)
65      */

66     private void ensureNoTableInfoIfNoRepositoryInfo(ClassDescriptorDef classDef, String JavaDoc checkLevel)
67     {
68         if (!classDef.getBooleanProperty(PropertyHelper.OJB_PROPERTY_GENERATE_REPOSITORY_INFO, true))
69         {
70             classDef.setProperty(PropertyHelper.OJB_PROPERTY_GENERATE_TABLE_INFO, "false");
71         }
72     }
73
74     /**
75      * Checks that the modified features exist.
76      *
77      * @param classDef The class descriptor
78      * @param checkLevel The current check level (this constraint is checked in basic and strict)
79      * @exception ConstraintException If the constraint has been violated
80      */

81     private void checkModifications(ClassDescriptorDef classDef, String JavaDoc checkLevel) throws ConstraintException
82     {
83         if (CHECKLEVEL_NONE.equals(checkLevel))
84         {
85             return;
86         }
87
88         HashMap features = new HashMap();
89         FeatureDescriptorDef def;
90
91         for (Iterator it = classDef.getFields(); it.hasNext();)
92         {
93             def = (FeatureDescriptorDef)it.next();
94             features.put(def.getName(), def);
95         }
96         for (Iterator it = classDef.getReferences(); it.hasNext();)
97         {
98             def = (FeatureDescriptorDef)it.next();
99             features.put(def.getName(), def);
100         }
101         for (Iterator it = classDef.getCollections(); it.hasNext();)
102         {
103             def = (FeatureDescriptorDef)it.next();
104             features.put(def.getName(), def);
105         }
106
107         // now checking the modifications
108
Properties mods;
109         String JavaDoc modName;
110         String JavaDoc propName;
111
112         for (Iterator it = classDef.getModificationNames(); it.hasNext();)
113         {
114             modName = (String JavaDoc)it.next();
115             if (!features.containsKey(modName))
116             {
117                 throw new ConstraintException("Class "+classDef.getName()+" contains a modification for an unknown feature "+modName);
118             }
119             def = (FeatureDescriptorDef)features.get(modName);
120             if (def.getOriginal() == null)
121             {
122                 throw new ConstraintException("Class "+classDef.getName()+" contains a modification for a feature "+modName+" that is not inherited but defined in the same class");
123             }
124             // checking modification
125
mods = classDef.getModification(modName);
126             for (Iterator propIt = mods.keySet().iterator(); propIt.hasNext();)
127             {
128                 propName = (String JavaDoc)propIt.next();
129                 if (!PropertyHelper.isPropertyAllowed(def.getClass(), propName))
130                 {
131                     throw new ConstraintException("The modification of attribute "+propName+" in class "+classDef.getName()+" is not applicable to the feature "+modName);
132                 }
133             }
134         }
135     }
136
137     /**
138      * Checks the extents specifications and removes unnecessary entries.
139      *
140      * @param classDef The class descriptor
141      * @param checkLevel The current check level (this constraint is checked in basic and strict)
142      * @exception ConstraintException If the constraint has been violated
143      */

144     private void checkExtents(ClassDescriptorDef classDef, String JavaDoc checkLevel) throws ConstraintException
145     {
146         if (CHECKLEVEL_NONE.equals(checkLevel))
147         {
148             return;
149         }
150
151         HashMap processedClasses = new HashMap();
152         InheritanceHelper helper = new InheritanceHelper();
153         ClassDescriptorDef curExtent;
154         boolean canBeRemoved;
155
156         for (Iterator it = classDef.getExtentClasses(); it.hasNext();)
157         {
158             curExtent = (ClassDescriptorDef)it.next();
159             canBeRemoved = false;
160             if (classDef.getName().equals(curExtent.getName()))
161             {
162                 throw new ConstraintException("The class "+classDef.getName()+" specifies itself as an extent-class");
163             }
164             else if (processedClasses.containsKey(curExtent))
165             {
166                 canBeRemoved = true;
167             }
168             else
169             {
170                 try
171                 {
172                     if (!helper.isSameOrSubTypeOf(curExtent, classDef.getName(), false))
173                     {
174                         throw new ConstraintException("The class "+classDef.getName()+" specifies an extent-class "+curExtent.getName()+" that is not a sub-type of it");
175                     }
176                     // now we check whether we already have an extent for a base-class of this extent-class
177
for (Iterator processedIt = processedClasses.keySet().iterator(); processedIt.hasNext();)
178                     {
179                         if (helper.isSameOrSubTypeOf(curExtent, ((ClassDescriptorDef)processedIt.next()).getName(), false))
180                         {
181                             canBeRemoved = true;
182                             break;
183                         }
184                     }
185                 }
186                 catch (ClassNotFoundException JavaDoc ex)
187                 {
188                     // won't happen because we don't use lookup of the actual classes
189
}
190             }
191             if (canBeRemoved)
192             {
193                 it.remove();
194             }
195             processedClasses.put(curExtent, null);
196         }
197     }
198     
199     /**
200      * Makes sure that the class descriptor has a table attribute if it requires it (i.e. it is
201      * relevant for the repository descriptor).
202      *
203      * @param classDef The class descriptor
204      * @param checkLevel The current check level (this constraint is checked in all levels)
205      */

206     private void ensureTableIfNecessary(ClassDescriptorDef classDef, String JavaDoc checkLevel)
207     {
208         if (classDef.getBooleanProperty(PropertyHelper.OJB_PROPERTY_OJB_PERSISTENT, false))
209         {
210             if (!classDef.hasProperty(PropertyHelper.OJB_PROPERTY_TABLE))
211             {
212                 classDef.setProperty(PropertyHelper.OJB_PROPERTY_TABLE, classDef.getDefaultTableName());
213             }
214         }
215     }
216
217     /**
218      * Checks the given class descriptor for correct factory-class and factory-method.
219      *
220      * @param classDef The class descriptor
221      * @param checkLevel The current check level (this constraint is checked in basic (partly) and strict)
222      * @exception ConstraintException If the constraint has been violated
223      */

224     private void checkFactoryClassAndMethod(ClassDescriptorDef classDef, String JavaDoc checkLevel) throws ConstraintException
225     {
226         if (CHECKLEVEL_NONE.equals(checkLevel))
227         {
228             return;
229         }
230         String JavaDoc factoryClassName = classDef.getProperty(PropertyHelper.OJB_PROPERTY_FACTORY_CLASS);
231         String JavaDoc factoryMethodName = classDef.getProperty(PropertyHelper.OJB_PROPERTY_FACTORY_METHOD);
232
233         if ((factoryClassName == null) && (factoryMethodName == null))
234         {
235             return;
236         }
237         if ((factoryClassName != null) && (factoryMethodName == null))
238         {
239             throw new ConstraintException("Class "+classDef.getName()+" has a factory-class but no factory-method.");
240         }
241         if ((factoryClassName == null) && (factoryMethodName != null))
242         {
243             throw new ConstraintException("Class "+classDef.getName()+" has a factory-method but no factory-class.");
244         }
245
246         if (CHECKLEVEL_STRICT.equals(checkLevel))
247         {
248             Class JavaDoc factoryClass;
249             Method JavaDoc factoryMethod;
250     
251             try
252             {
253                 factoryClass = InheritanceHelper.getClass(factoryClassName);
254             }
255             catch (ClassNotFoundException JavaDoc ex)
256             {
257                 throw new ConstraintException("The class "+factoryClassName+" specified as factory-class of class "+classDef.getName()+" was not found on the classpath");
258             }
259             try
260             {
261                 factoryMethod = factoryClass.getDeclaredMethod(factoryMethodName, new Class JavaDoc[0]);
262             }
263             catch (NoSuchMethodException JavaDoc ex)
264             {
265                 factoryMethod = null;
266             }
267             catch (Exception JavaDoc ex)
268             {
269                 throw new ConstraintException("Exception while checking the factory-class "+factoryClassName+" of class "+classDef.getName()+": "+ex.getMessage());
270             }
271             if (factoryMethod == null)
272             {
273                 try
274                 {
275                     factoryMethod = factoryClass.getMethod(factoryMethodName, new Class JavaDoc[0]);
276                 }
277                 catch (NoSuchMethodException JavaDoc ex)
278                 {
279                     throw new ConstraintException("No suitable factory-method "+factoryMethodName+" found in the factory-class "+factoryClassName+" of class "+classDef.getName());
280                 }
281                 catch (Exception JavaDoc ex)
282                 {
283                     throw new ConstraintException("Exception while checking the factory-class "+factoryClassName+" of class "+classDef.getName()+": "+ex.getMessage());
284                 }
285             }
286     
287             // checking return type and modifiers
288
Class JavaDoc returnType = factoryMethod.getReturnType();
289             InheritanceHelper helper = new InheritanceHelper();
290     
291             if ("void".equals(returnType.getName()))
292             {
293                 throw new ConstraintException("The factory-method "+factoryMethodName+" in factory-class "+factoryClassName+" of class "+classDef.getName()+" must return a value");
294             }
295             try
296             {
297                 if (!helper.isSameOrSubTypeOf(returnType.getName(), classDef.getName()))
298                 {
299                     throw new ConstraintException("The method "+factoryMethodName+" in factory-class "+factoryClassName+" of class "+classDef.getName()+" must return the type "+classDef.getName()+" or a subtype of it");
300                 }
301             }
302             catch (ClassNotFoundException JavaDoc ex)
303             {
304                 throw new ConstraintException("Could not find the class "+ex.getMessage()+" on the classpath while checking the factory-method "+factoryMethodName+" in the factory-class "+factoryClassName+" of class "+classDef.getName());
305             }
306             
307             if (!Modifier.isStatic(factoryMethod.getModifiers()))
308             {
309                 throw new ConstraintException("The factory-method "+factoryMethodName+" in factory-class "+factoryClassName+" of class "+classDef.getName()+" must be static");
310             }
311         }
312     }
313
314     /**
315      * Checks the initialization-method of given class descriptor.
316      *
317      * @param classDef The class descriptor
318      * @param checkLevel The current check level (this constraint is only checked in strict)
319      * @exception ConstraintException If the constraint has been violated
320      */

321     private void checkInitializationMethod(ClassDescriptorDef classDef, String JavaDoc checkLevel) throws ConstraintException
322     {
323         if (!CHECKLEVEL_STRICT.equals(checkLevel))
324         {
325             return;
326         }
327         
328         String JavaDoc initMethodName = classDef.getProperty(PropertyHelper.OJB_PROPERTY_INITIALIZATION_METHOD);
329
330         if (initMethodName == null)
331         {
332             return;
333         }
334
335         Class JavaDoc initClass;
336         Method JavaDoc initMethod;
337
338         try
339         {
340             initClass = InheritanceHelper.getClass(classDef.getName());
341         }
342         catch (ClassNotFoundException JavaDoc ex)
343         {
344             throw new ConstraintException("The class "+classDef.getName()+" was not found on the classpath");
345         }
346         try
347         {
348             initMethod = initClass.getDeclaredMethod(initMethodName, new Class JavaDoc[0]);
349         }
350         catch (NoSuchMethodException JavaDoc ex)
351         {
352             initMethod = null;
353         }
354         catch (Exception JavaDoc ex)
355         {
356             throw new ConstraintException("Exception while checking the class "+classDef.getName()+": "+ex.getMessage());
357         }
358         if (initMethod == null)
359         {
360             try
361             {
362                 initMethod = initClass.getMethod(initMethodName, new Class JavaDoc[0]);
363             }
364             catch (NoSuchMethodException JavaDoc ex)
365             {
366                 throw new ConstraintException("No suitable initialization-method "+initMethodName+" found in class "+classDef.getName());
367             }
368             catch (Exception JavaDoc ex)
369             {
370                 throw new ConstraintException("Exception while checking the class "+classDef.getName()+": "+ex.getMessage());
371             }
372         }
373
374         // checking modifiers
375
int mods = initMethod.getModifiers();
376
377         if (Modifier.isStatic(mods) || Modifier.isAbstract(mods))
378         {
379             throw new ConstraintException("The initialization-method "+initMethodName+" in class "+classDef.getName()+" must be a concrete instance method");
380         }
381     }
382
383     /**
384      * Checks whether given class descriptor has a primary key.
385      *
386      * @param classDef The class descriptor
387      * @param checkLevel The current check level (this constraint is only checked in strict)
388      * @exception ConstraintException If the constraint has been violated
389      */

390     private void checkPrimaryKey(ClassDescriptorDef classDef, String JavaDoc checkLevel) throws ConstraintException
391     {
392         if (CHECKLEVEL_NONE.equals(checkLevel))
393         {
394             return;
395         }
396
397         if (classDef.getBooleanProperty(PropertyHelper.OJB_PROPERTY_GENERATE_TABLE_INFO, true) &&
398             classDef.getPrimaryKeys().isEmpty())
399         {
400             LogHelper.warn(true,
401                            getClass(),
402                            "checkPrimaryKey",
403                            "The class "+classDef.getName()+" has no primary key");
404         }
405     }
406
407     /**
408      * Checks the given class descriptor for correct row-reader setting.
409      *
410      * @param classDef The class descriptor
411      * @param checkLevel The current check level (this constraint is only checked in strict)
412      * @exception ConstraintException If the constraint has been violated
413      */

414     private void checkRowReader(ClassDescriptorDef classDef, String JavaDoc checkLevel) throws ConstraintException
415     {
416         if (!CHECKLEVEL_STRICT.equals(checkLevel))
417         {
418             return;
419         }
420         
421         String JavaDoc rowReaderName = classDef.getProperty(PropertyHelper.OJB_PROPERTY_ROW_READER);
422
423         if (rowReaderName == null)
424         {
425             return;
426         }
427
428         try
429         {
430             InheritanceHelper helper = new InheritanceHelper();
431
432             if (!helper.isSameOrSubTypeOf(rowReaderName, ROW_READER_INTERFACE))
433             {
434                 throw new ConstraintException("The class "+rowReaderName+" specified as row-reader of class "+classDef.getName()+" does not implement the interface "+ROW_READER_INTERFACE);
435             }
436         }
437         catch (ClassNotFoundException JavaDoc ex)
438         {
439             throw new ConstraintException("Could not find the class "+ex.getMessage()+" on the classpath while checking the row-reader class "+rowReaderName+" of class "+classDef.getName());
440         }
441     }
442
443     /**
444      * Checks the given class descriptor for correct object cache setting.
445      *
446      * @param classDef The class descriptor
447      * @param checkLevel The current check level (this constraint is only checked in strict)
448      * @exception ConstraintException If the constraint has been violated
449      */

450     private void checkObjectCache(ClassDescriptorDef classDef, String JavaDoc checkLevel) throws ConstraintException
451     {
452         if (!CHECKLEVEL_STRICT.equals(checkLevel))
453         {
454             return;
455         }
456         
457         ObjectCacheDef objCacheDef = classDef.getObjectCache();
458
459         if (objCacheDef == null)
460         {
461             return;
462         }
463
464         String JavaDoc objectCacheName = objCacheDef.getName();
465
466         if ((objectCacheName == null) || (objectCacheName.length() == 0))
467         {
468             throw new ConstraintException("No class specified for the object-cache of class "+classDef.getName());
469         }
470
471         try
472         {
473             InheritanceHelper helper = new InheritanceHelper();
474
475             if (!helper.isSameOrSubTypeOf(objectCacheName, OBJECT_CACHE_INTERFACE))
476             {
477                 throw new ConstraintException("The class "+objectCacheName+" specified as object-cache of class "+classDef.getName()+" does not implement the interface "+OBJECT_CACHE_INTERFACE);
478             }
479         }
480         catch (ClassNotFoundException JavaDoc ex)
481         {
482             throw new ConstraintException("Could not find the class "+ex.getMessage()+" on the classpath while checking the object-cache class "+objectCacheName+" of class "+classDef.getName());
483         }
484     }
485
486     /**
487      * Checks the given class descriptor for correct procedure settings.
488      *
489      * @param classDef The class descriptor
490      * @param checkLevel The current check level (this constraint is checked in basic and strict)
491      * @exception ConstraintException If the constraint has been violated
492      */

493     private void checkProcedures(ClassDescriptorDef classDef, String JavaDoc checkLevel) throws ConstraintException
494     {
495         if (CHECKLEVEL_NONE.equals(checkLevel))
496         {
497             return;
498         }
499
500         ProcedureDef procDef;
501         String JavaDoc type;
502         String JavaDoc name;
503         String JavaDoc fieldName;
504         String JavaDoc argName;
505         
506         for (Iterator it = classDef.getProcedures(); it.hasNext();)
507         {
508             procDef = (ProcedureDef)it.next();
509             type = procDef.getName();
510             name = procDef.getProperty(PropertyHelper.OJB_PROPERTY_NAME);
511             if ((name == null) || (name.length() == 0))
512             {
513                 throw new ConstraintException("The "+type+"-procedure in class "+classDef.getName()+" doesn't have a name");
514             }
515             fieldName = procDef.getProperty(PropertyHelper.OJB_PROPERTY_RETURN_FIELD_REF);
516             if ((fieldName != null) && (fieldName.length() > 0))
517             {
518                 if (classDef.getField(fieldName) == null)
519                 {
520                     throw new ConstraintException("The "+type+"-procedure "+name+" in class "+classDef.getName()+" references an unknown or non-persistent return field "+fieldName);
521                 }
522             }
523             for (CommaListIterator argIt = new CommaListIterator(procDef.getProperty(PropertyHelper.OJB_PROPERTY_ARGUMENTS)); argIt.hasNext();)
524             {
525                 argName = argIt.getNext();
526                 if (classDef.getProcedureArgument(argName) == null)
527                 {
528                     throw new ConstraintException("The "+type+"-procedure "+name+" in class "+classDef.getName()+" references an unknown argument "+argName);
529                 }
530             }
531         }
532
533         ProcedureArgumentDef argDef;
534
535         for (Iterator it = classDef.getProcedureArguments(); it.hasNext();)
536         {
537             argDef = (ProcedureArgumentDef)it.next();
538             type = argDef.getProperty(PropertyHelper.OJB_PROPERTY_TYPE);
539             if ("runtime".equals(type))
540             {
541                 fieldName = argDef.getProperty(PropertyHelper.OJB_PROPERTY_FIELD_REF);
542                 if ((fieldName != null) && (fieldName.length() > 0))
543                 {
544                     if (classDef.getField(fieldName) == null)
545                     {
546                         throw new ConstraintException("The "+type+"-argument "+argDef.getName()+" in class "+classDef.getName()+" references an unknown or non-persistent return field "+fieldName);
547                     }
548                 }
549             }
550         }
551     }
552 }
553
Popular Tags