1 29 30 package com.caucho.amber.cfg; 31 32 import com.caucho.amber.field.IdField; 33 import com.caucho.amber.table.ForeignColumn; 34 import com.caucho.amber.type.AbstractStatefulType; 35 import com.caucho.amber.type.RelatedType; 36 import com.caucho.bytecode.JAccessibleObject; 37 import com.caucho.bytecode.JAnnotation; 38 import com.caucho.bytecode.JClass; 39 import com.caucho.bytecode.JMethod; 40 import com.caucho.config.ConfigException; 41 import com.caucho.util.L10N; 42 43 import java.util.ArrayList ; 44 import java.util.HashMap ; 45 import java.util.HashSet ; 46 import java.util.Iterator ; 47 import java.util.logging.Logger ; 48 49 50 53 abstract public class AbstractConfigIntrospector { 54 private static final Logger log 55 = Logger.getLogger(AbstractConfigIntrospector.class.getName()); 56 private static final L10N L = new L10N(AbstractConfigIntrospector.class); 57 58 static HashSet <String > _propertyAnnotations 60 = new HashSet <String >(); 61 62 static HashSet <String > _basicTypes = new HashSet <String >(); 64 65 static HashSet <String > _basicAnnotations = new HashSet <String >(); 67 68 static HashSet <String > _idTypes = new HashSet <String >(); 70 71 static HashSet <String > _idAnnotations = new HashSet <String >(); 73 74 static HashSet <String > _manyToOneAnnotations = new HashSet <String >(); 76 77 static HashSet <String > _oneToManyAnnotations = new HashSet <String >(); 79 80 static HashSet <String > _oneToManyTypes = new HashSet <String >(); 82 83 static HashSet <String > _manyToManyAnnotations = new HashSet <String >(); 85 86 static HashSet <String > _manyToManyTypes = new HashSet <String >(); 88 89 static HashSet <String > _oneToOneAnnotations = new HashSet <String >(); 91 92 static HashSet <String > _embeddedAnnotations = new HashSet <String >(); 94 95 static HashSet <String > _embeddedIdAnnotations = new HashSet <String >(); 97 98 static HashSet <String > _versionAnnotations = new HashSet <String >(); 100 101 static HashSet <String > _versionTypes = new HashSet <String >(); 103 104 AnnotationConfig _annotationCfg = new AnnotationConfig(); 105 106 107 110 void validateCallback(String callbackName, 111 JMethod method, 112 boolean isListener) 113 throws ConfigException 114 { 115 if (method.isFinal()) 116 throw new ConfigException(L.l("'{0}' must not be final. @{1} methods may not be final.", 117 method.getFullName(), 118 callbackName)); 119 120 if (method.isStatic()) 121 throw new ConfigException(L.l("'{0}' must not be static. @{1} methods may not be static.", 122 method.getFullName(), 123 callbackName)); 124 125 JClass params[] = method.getParameterTypes(); 126 127 if (isListener) { 128 if (params.length != 1) { 129 throw new ConfigException(L.l("'{0}' must have the <METHOD>(Object) signature for entity listeners.", 130 method.getFullName())); 131 } 132 } 133 else if (params.length != 0) { 134 throw new ConfigException(L.l("'{0}' must not have any arguments. @{1} methods have zero arguments for entities or mapped superclasses.", 135 method.getFullName(), 136 callbackName)); 137 } 138 } 139 140 143 public void validateType(JClass type) 144 throws ConfigException 145 { 146 if (type.isFinal()) 147 throw new ConfigException(L.l("'{0}' must not be final. Entity beans may not be final.", 148 type.getName())); 149 150 152 validateConstructor(type); 153 154 for (JMethod method : type.getMethods()) { 155 if (method.getDeclaringClass().getName().equals("java.lang.Object")) { 156 } 157 else if (method.isFinal()) 158 throw error(method, L.l("'{0}' must not be final. Entity beans methods may not be final.", 159 method.getFullName())); 160 } 161 } 162 163 166 public void validateConstructor(JClass type) 167 throws ConfigException 168 { 169 for (JMethod ctor : type.getConstructors()) { 170 JClass []param = ctor.getParameterTypes(); 171 172 if (param.length == 0 && ctor.isPublic()) 173 return; 174 } 175 176 throw new ConfigException(L.l("'{0}' needs a public, no-arg constructor. Entity beans must have public, no-arg constructors.", 177 type.getName())); 178 } 179 180 183 public void validateNonGetter(JMethod method) 184 throws ConfigException 185 { 186 JAnnotation ann = isAnnotatedMethod(method); 187 188 if ((ann != null) && (! ann.getType().equals("javax.persistence.Version"))) { 189 throw error(method, 190 L.l("'{0}' is not a valid annotation for {1}. Only public getters and fields may have property annotations.", 191 ann.getType(), method.getFullName())); 192 } 193 } 194 195 198 JAnnotation isAnnotatedMethod(JMethod method) 199 throws ConfigException 200 { 201 for (JAnnotation ann : method.getDeclaredAnnotations()) { 202 if (_propertyAnnotations.contains(ann.getType())) { 203 return ann; 204 } 205 } 206 207 return null; 208 } 209 210 static boolean containsFieldOrCompletion(AbstractStatefulType type, 211 String fieldName) 212 { 213 215 while (type != null) { 216 217 if (type.getField(fieldName) != null) 218 return true; 219 220 if (type.containsCompletionField(fieldName)) 221 return true; 222 223 if (type instanceof RelatedType) 224 type = ((RelatedType) type).getParentType(); 225 } 226 227 return false; 228 } 229 230 static void validateAnnotations(JAccessibleObject field, 231 HashSet <String > validAnnotations) 232 throws ConfigException 233 { 234 for (JAnnotation ann : field.getDeclaredAnnotations()) { 235 String name = ann.getType(); 236 237 if (! name.startsWith("javax.persistence")) 238 continue; 239 240 if (! validAnnotations.contains(name)) { 241 throw error(field, L.l("{0} may not have a @{1} annotation.", 242 field.getName(), 243 name)); 244 } 245 } 246 } 247 248 static ConfigException error(JAccessibleObject field, 249 String msg) 250 { 251 253 String className = field.getDeclaringClass().getName(); 254 255 int line = field.getLine(); 256 257 if (line > 0) 258 return new ConfigException(className + ":" + line + ": " + msg); 259 else 260 return new ConfigException(className + ": " + msg); 261 } 262 263 static String toFieldName(String name) 264 { 265 if (Character.isLowerCase(name.charAt(0))) 266 return name; 267 else if (name.length() == 1 || 268 Character.isLowerCase(name.charAt(1))) 269 return Character.toLowerCase(name.charAt(0)) + name.substring(1); 270 else 271 return name; 272 } 273 274 static ArrayList <ForeignColumn> calculateColumns(com.caucho.amber.table.Table mapTable, 275 RelatedType type, 276 Object []joinColumnsAnn) 277 { 278 if (joinColumnsAnn == null || joinColumnsAnn.length == 0) 279 return calculateColumns(mapTable, type); 280 281 ArrayList <ForeignColumn> columns = new ArrayList <ForeignColumn>(); 282 283 for (int i = 0; i < joinColumnsAnn.length; i++) { 284 ForeignColumn foreignColumn; 285 JAnnotation joinColumnAnn = (JAnnotation) joinColumnsAnn[i]; 286 287 foreignColumn = 288 mapTable.createForeignColumn(joinColumnAnn.getString("name"), 289 type.getId().getKey().getColumns().get(0)); 290 291 columns.add(foreignColumn); 292 } 293 294 return columns; 295 } 296 297 static ArrayList <ForeignColumn> 298 calculateColumns(JAccessibleObject field, 299 com.caucho.amber.table.Table mapTable, 300 String prefix, 301 RelatedType type, 302 Object []joinColumnsAnn, 303 HashMap <String , JoinColumnConfig> joinColumnsConfig) 304 throws ConfigException 305 { 306 if ((joinColumnsAnn == null || joinColumnsAnn.length == 0) && 307 (joinColumnsConfig == null || joinColumnsConfig.size() == 0)) 308 return calculateColumns(mapTable, prefix, type); 309 310 ArrayList <ForeignColumn> columns = new ArrayList <ForeignColumn>(); 311 312 if (type.getId() == null) 314 throw error(field, L.l("Entity {0} has no primary key defined.", 315 type.getName())); 316 317 ArrayList <IdField> idFields = type.getId().getKeys(); 318 319 int len; 320 321 if (joinColumnsAnn != null) 322 len = joinColumnsAnn.length; 323 else 324 len = joinColumnsConfig.size(); 325 326 if (len != idFields.size()) { 327 throw error(field, L.l("@JoinColumns for {0} do not match number of the primary key columns in {1}. The foreign key columns must match the primary key columns.", 328 field.getName(), 329 type.getName())); 330 } 331 332 Iterator it = null; 333 334 if (joinColumnsConfig != null) 335 it = joinColumnsConfig.values().iterator(); 336 337 for (int i = 0; i < len; i++) { 338 ForeignColumn foreignColumn; 339 340 String name; 341 342 if (joinColumnsAnn != null) { 343 JAnnotation joinColumnAnn = (JAnnotation) joinColumnsAnn[i]; 344 name = joinColumnAnn.getString("name"); 345 } 346 else { 347 JoinColumnConfig joinColumnConfig = (JoinColumnConfig) it.next(); 348 name = joinColumnConfig.getName(); 349 } 350 351 foreignColumn = 352 mapTable.createForeignColumn(name, 353 idFields.get(i).getColumns().get(0)); 354 355 columns.add(foreignColumn); 356 } 357 358 return columns; 359 } 360 361 static ArrayList <ForeignColumn> calculateColumns(com.caucho.amber.table.Table mapTable, 362 RelatedType type) 363 { 364 ArrayList <ForeignColumn> columns = new ArrayList <ForeignColumn>(); 365 366 RelatedType parentType = type; 367 368 ArrayList <com.caucho.amber.table.Column> targetIdColumns; 369 370 targetIdColumns = type.getId().getColumns(); 371 372 while (targetIdColumns.size() == 0) { 373 374 parentType = parentType.getParentType(); 375 376 if (parentType == null) 377 break; 378 379 targetIdColumns = parentType.getId().getColumns(); 380 } 381 382 for (com.caucho.amber.table.Column key : targetIdColumns) { 383 columns.add(mapTable.createForeignColumn(key.getName(), key)); 384 } 385 386 return columns; 387 } 388 389 static ArrayList <ForeignColumn> calculateColumns(com.caucho.amber.table.Table mapTable, 390 String prefix, 391 RelatedType type) 392 { 393 ArrayList <ForeignColumn> columns = new ArrayList <ForeignColumn>(); 394 395 RelatedType parentType = type; 396 397 ArrayList <com.caucho.amber.table.Column> targetIdColumns; 398 399 targetIdColumns = type.getId().getColumns(); 400 401 while (targetIdColumns.size() == 0) { 402 403 parentType = parentType.getParentType(); 404 405 if (parentType == null) 406 break; 407 408 targetIdColumns = parentType.getId().getColumns(); 409 } 410 411 for (com.caucho.amber.table.Column key : targetIdColumns) { 412 columns.add(mapTable.createForeignColumn(prefix + key.getName(), key)); 413 } 414 415 return columns; 416 } 417 418 public static String toSqlName(String name) 419 { 420 return name.toUpperCase(); 421 } 422 423 class AnnotationConfig { 424 private JAnnotation _annotation; 425 private Object _config; 426 427 public JAnnotation getAnnotation() 428 { 429 return _annotation; 430 } 431 432 public Object getConfig() 433 { 434 return _config; 435 } 436 437 public void setAnnotation(JAnnotation annotation) 438 { 439 _annotation = annotation; 440 } 441 442 public void setConfig(Object config) 443 { 444 _config = config; 445 } 446 447 public boolean isNull() 448 { 449 return (_annotation == null) && (_config == null); 450 } 451 452 public void reset() 453 { 454 _annotation = null; 455 _config = null; 456 } 457 458 public void reset(JClass type, Class cl) 459 { 460 _annotation = type.getAnnotation(cl); 461 _config = null; 462 } 463 464 public void reset(JAccessibleObject field, Class cl) 465 { 466 _annotation = field.getAnnotation(cl); 467 _config = null; 468 } 469 470 public EmbeddableConfig getEmbeddableConfig() 471 { 472 return (EmbeddableConfig) _config; 473 } 474 475 public EntityConfig getEntityConfig() 476 { 477 return (EntityConfig) _config; 478 } 479 480 public MappedSuperclassConfig getMappedSuperclassConfig() 481 { 482 return (MappedSuperclassConfig) _config; 483 } 484 485 public EntityListenersConfig getEntityListenersConfig() 486 { 487 return (EntityListenersConfig) _config; 488 } 489 490 public TableConfig getTableConfig() { 491 return (TableConfig) _config; 492 } 493 494 public SecondaryTableConfig getSecondaryTableConfig() { 495 return (SecondaryTableConfig) _config; 496 } 497 498 public IdClassConfig getIdClassConfig() { 499 return (IdClassConfig) _config; 500 } 501 502 public PostLoadConfig getPostLoadConfig() { 503 return (PostLoadConfig) _config; 504 } 505 506 public PrePersistConfig getPrePersistConfig() { 507 return (PrePersistConfig) _config; 508 } 509 510 public PostPersistConfig getPostPersistConfig() { 511 return (PostPersistConfig) _config; 512 } 513 514 public PreUpdateConfig getPreUpdateConfig() { 515 return (PreUpdateConfig) _config; 516 } 517 518 public PostUpdateConfig getPostUpdateConfig() { 519 return (PostUpdateConfig) _config; 520 } 521 522 public PreRemoveConfig getPreRemoveConfig() { 523 return (PreRemoveConfig) _config; 524 } 525 526 public PostRemoveConfig getPostRemoveConfig() { 527 return (PostRemoveConfig) _config; 528 } 529 530 public InheritanceConfig getInheritanceConfig() { 531 return (InheritanceConfig) _config; 532 } 533 534 public NamedQueryConfig getNamedQueryConfig() { 535 return (NamedQueryConfig) _config; 536 } 537 538 public NamedNativeQueryConfig getNamedNativeQueryConfig() { 539 return (NamedNativeQueryConfig) _config; 540 } 541 542 public SqlResultSetMappingConfig getSqlResultSetMappingConfig() { 543 return (SqlResultSetMappingConfig) _config; 544 } 545 546 public PrimaryKeyJoinColumnConfig getPrimaryKeyJoinColumnConfig() { 547 return (PrimaryKeyJoinColumnConfig) _config; 548 } 549 550 public DiscriminatorColumnConfig getDiscriminatorColumnConfig() { 551 return (DiscriminatorColumnConfig) _config; 552 } 553 554 public IdConfig getIdConfig() { 555 return (IdConfig) _config; 556 } 557 558 public EmbeddedIdConfig getEmbeddedIdConfig() { 559 return (EmbeddedIdConfig) _config; 560 } 561 562 public ColumnConfig getColumnConfig() { 563 return (ColumnConfig) _config; 564 } 565 566 public GeneratedValueConfig getGeneratedValueConfig() { 567 return (GeneratedValueConfig) _config; 568 } 569 570 public BasicConfig getBasicConfig() { 571 return (BasicConfig) _config; 572 } 573 574 public VersionConfig getVersionConfig() { 575 return (VersionConfig) _config; 576 } 577 578 public ManyToOneConfig getManyToOneConfig() { 579 return (ManyToOneConfig) _config; 580 } 581 582 public OneToOneConfig getOneToOneConfig() { 583 return (OneToOneConfig) _config; 584 } 585 586 public ManyToManyConfig getManyToManyConfig() { 587 return (ManyToManyConfig) _config; 588 } 589 590 public OneToManyConfig getOneToManyConfig() { 591 return (OneToManyConfig) _config; 592 } 593 594 public MapKeyConfig getMapKeyConfig() { 595 return (MapKeyConfig) _config; 596 } 597 598 public JoinTableConfig getJoinTableConfig() { 599 return (JoinTableConfig) _config; 600 } 601 602 public JoinColumnConfig getJoinColumnConfig() { 603 return (JoinColumnConfig) _config; 604 } 605 606 public AttributeOverrideConfig getAttributeOverrideConfig() { 607 return (AttributeOverrideConfig) _config; 608 } 609 610 614 public AssociationOverrideConfig getAssociationOverrideConfig() { 615 return (AssociationOverrideConfig) _config; 616 } 617 618 } 622 623 static { 624 _basicAnnotations.add("javax.persistence.Basic"); 626 _basicAnnotations.add("javax.persistence.Column"); 627 _basicAnnotations.add("javax.persistence.Enumerated"); 628 _basicAnnotations.add("javax.persistence.Lob"); 629 _basicAnnotations.add("javax.persistence.Temporal"); 630 631 _basicTypes.add("boolean"); 633 _basicTypes.add("byte"); 634 _basicTypes.add("char"); 635 _basicTypes.add("short"); 636 _basicTypes.add("int"); 637 _basicTypes.add("long"); 638 _basicTypes.add("float"); 639 _basicTypes.add("double"); 640 _basicTypes.add("[byte"); 641 _basicTypes.add("[char"); 642 _basicTypes.add("[java.lang.Byte"); 643 _basicTypes.add("[java.lang.Character"); 644 645 _idAnnotations.add("javax.persistence.Column"); 647 _idAnnotations.add("javax.persistence.GeneratedValue"); 648 _idAnnotations.add("javax.persistence.Id"); 649 _idAnnotations.add("javax.persistence.SequenceGenerator"); 650 _idAnnotations.add("javax.persistence.TableGenerator"); 651 _idAnnotations.add("javax.persistence.Temporal"); 652 653 _idTypes.add("boolean"); 655 _idTypes.add("byte"); 656 _idTypes.add("char"); 657 _idTypes.add("short"); 658 _idTypes.add("int"); 659 _idTypes.add("long"); 660 _idTypes.add("float"); 661 _idTypes.add("double"); 662 _idTypes.add("java.lang.Boolean"); 663 _idTypes.add("java.lang.Byte"); 664 _idTypes.add("java.lang.Character"); 665 _idTypes.add("java.lang.Short"); 666 _idTypes.add("java.lang.Integer"); 667 _idTypes.add("java.lang.Long"); 668 _idTypes.add("java.lang.Float"); 669 _idTypes.add("java.lang.Double"); 670 _idTypes.add("java.lang.String"); 671 _idTypes.add("java.util.Date"); 672 _idTypes.add("java.sql.Date"); 673 674 _manyToOneAnnotations.add("javax.persistence.ManyToOne"); 676 _manyToOneAnnotations.add("javax.persistence.JoinColumn"); 677 _manyToOneAnnotations.add("javax.persistence.JoinColumns"); 678 679 _oneToManyAnnotations.add("javax.persistence.OneToMany"); 681 _oneToManyAnnotations.add("javax.persistence.JoinTable"); 682 _oneToManyAnnotations.add("javax.persistence.MapKey"); 683 _oneToManyAnnotations.add("javax.persistence.OrderBy"); 684 685 _oneToManyTypes.add("java.util.Collection"); 687 _oneToManyTypes.add("java.util.List"); 688 _oneToManyTypes.add("java.util.Set"); 689 _oneToManyTypes.add("java.util.Map"); 690 691 _manyToManyAnnotations.add("javax.persistence.ManyToMany"); 693 _manyToManyAnnotations.add("javax.persistence.JoinTable"); 694 _manyToManyAnnotations.add("javax.persistence.MapKey"); 695 _manyToManyAnnotations.add("javax.persistence.OrderBy"); 696 697 _manyToManyTypes.add("java.util.Collection"); 699 _manyToManyTypes.add("java.util.List"); 700 _manyToManyTypes.add("java.util.Set"); 701 _manyToManyTypes.add("java.util.Map"); 702 703 _oneToOneAnnotations.add("javax.persistence.OneToOne"); 705 _oneToOneAnnotations.add("javax.persistence.JoinColumn"); 706 _oneToOneAnnotations.add("javax.persistence.JoinColumns"); 707 708 _embeddedAnnotations.add("javax.persistence.Embedded"); 710 _embeddedAnnotations.add("javax.persistence.AttributeOverride"); 711 _embeddedAnnotations.add("javax.persistence.AttributeOverrides"); 712 _embeddedAnnotations.add("javax.persistence.Column"); 713 714 _embeddedIdAnnotations.add("javax.persistence.EmbeddedId"); 716 _embeddedIdAnnotations.add("javax.persistence.AttributeOverride"); 717 _embeddedIdAnnotations.add("javax.persistence.AttributeOverrides"); 718 719 _propertyAnnotations.add("javax.persistence.Basic"); 721 _propertyAnnotations.add("javax.persistence.Column"); 722 _propertyAnnotations.add("javax.persistence.Id"); 723 _propertyAnnotations.add("javax.persistence.Transient"); 724 _propertyAnnotations.add("javax.persistence.OneToOne"); 725 _propertyAnnotations.add("javax.persistence.ManyToOne"); 726 _propertyAnnotations.add("javax.persistence.OneToMany"); 727 _propertyAnnotations.add("javax.persistence.ManyToMany"); 728 _propertyAnnotations.add("javax.persistence.JoinColumn"); 729 _propertyAnnotations.add("javax.persistence.Embedded"); 730 _propertyAnnotations.add("javax.persistence.EmbeddedId"); 731 _propertyAnnotations.add("javax.persistence.Version"); 732 733 _versionAnnotations.add("javax.persistence.Version"); 735 _versionAnnotations.add("javax.persistence.Column"); 736 _versionAnnotations.add("javax.persistence.Temporal"); 737 738 _versionTypes.add("short"); 740 _versionTypes.add("int"); 741 _versionTypes.add("long"); 742 _versionTypes.add("java.lang.Short"); 743 _versionTypes.add("java.lang.Integer"); 744 _versionTypes.add("java.lang.Long"); 745 _versionTypes.add("java.sql.Timestamp"); 746 } 747 } 748 | Popular Tags |