1 package xdoclet.modules.ojb.constraints; 2 3 17 18 import java.lang.reflect.Method ; 19 import java.lang.reflect.Modifier ; 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 31 public class ClassDescriptorConstraints extends ConstraintsBase 32 { 33 34 private final static String ROW_READER_INTERFACE = "org.apache.ojb.broker.accesslayer.RowReader"; 35 36 private final static String OBJECT_CACHE_INTERFACE = "org.apache.ojb.broker.cache.ObjectCache"; 37 38 45 public void check(ClassDescriptorDef classDef, String 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 66 private void ensureNoTableInfoIfNoRepositoryInfo(ClassDescriptorDef classDef, String 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 81 private void checkModifications(ClassDescriptorDef classDef, String 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 Properties mods; 109 String modName; 110 String propName; 111 112 for (Iterator it = classDef.getModificationNames(); it.hasNext();) 113 { 114 modName = (String )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 mods = classDef.getModification(modName); 126 for (Iterator propIt = mods.keySet().iterator(); propIt.hasNext();) 127 { 128 propName = (String )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 144 private void checkExtents(ClassDescriptorDef classDef, String 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 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 ex) 187 { 188 } 190 } 191 if (canBeRemoved) 192 { 193 it.remove(); 194 } 195 processedClasses.put(curExtent, null); 196 } 197 } 198 199 206 private void ensureTableIfNecessary(ClassDescriptorDef classDef, String 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 224 private void checkFactoryClassAndMethod(ClassDescriptorDef classDef, String checkLevel) throws ConstraintException 225 { 226 if (CHECKLEVEL_NONE.equals(checkLevel)) 227 { 228 return; 229 } 230 String factoryClassName = classDef.getProperty(PropertyHelper.OJB_PROPERTY_FACTORY_CLASS); 231 String 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 factoryClass; 249 Method factoryMethod; 250 251 try 252 { 253 factoryClass = InheritanceHelper.getClass(factoryClassName); 254 } 255 catch (ClassNotFoundException 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 [0]); 262 } 263 catch (NoSuchMethodException ex) 264 { 265 factoryMethod = null; 266 } 267 catch (Exception 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 [0]); 276 } 277 catch (NoSuchMethodException 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 ex) 282 { 283 throw new ConstraintException("Exception while checking the factory-class "+factoryClassName+" of class "+classDef.getName()+": "+ex.getMessage()); 284 } 285 } 286 287 Class 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 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 321 private void checkInitializationMethod(ClassDescriptorDef classDef, String checkLevel) throws ConstraintException 322 { 323 if (!CHECKLEVEL_STRICT.equals(checkLevel)) 324 { 325 return; 326 } 327 328 String initMethodName = classDef.getProperty(PropertyHelper.OJB_PROPERTY_INITIALIZATION_METHOD); 329 330 if (initMethodName == null) 331 { 332 return; 333 } 334 335 Class initClass; 336 Method initMethod; 337 338 try 339 { 340 initClass = InheritanceHelper.getClass(classDef.getName()); 341 } 342 catch (ClassNotFoundException 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 [0]); 349 } 350 catch (NoSuchMethodException ex) 351 { 352 initMethod = null; 353 } 354 catch (Exception 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 [0]); 363 } 364 catch (NoSuchMethodException ex) 365 { 366 throw new ConstraintException("No suitable initialization-method "+initMethodName+" found in class "+classDef.getName()); 367 } 368 catch (Exception ex) 369 { 370 throw new ConstraintException("Exception while checking the class "+classDef.getName()+": "+ex.getMessage()); 371 } 372 } 373 374 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 390 private void checkPrimaryKey(ClassDescriptorDef classDef, String 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 414 private void checkRowReader(ClassDescriptorDef classDef, String checkLevel) throws ConstraintException 415 { 416 if (!CHECKLEVEL_STRICT.equals(checkLevel)) 417 { 418 return; 419 } 420 421 String 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 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 450 private void checkObjectCache(ClassDescriptorDef classDef, String 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 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 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 493 private void checkProcedures(ClassDescriptorDef classDef, String checkLevel) throws ConstraintException 494 { 495 if (CHECKLEVEL_NONE.equals(checkLevel)) 496 { 497 return; 498 } 499 500 ProcedureDef procDef; 501 String type; 502 String name; 503 String fieldName; 504 String 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 |