1 22 package org.jboss.ejb.plugins.cmp.jdbc.metadata; 23 24 import java.util.ArrayList ; 25 import java.util.Iterator ; 26 import javax.ejb.EJBException ; 27 import javax.naming.InitialContext ; 28 import javax.naming.NamingException ; 29 import javax.sql.DataSource ; 30 import org.jboss.deployment.DeploymentException; 31 import org.jboss.metadata.MetaData; 32 import org.jboss.metadata.RelationMetaData; 33 import org.jboss.metadata.RelationshipRoleMetaData; 34 import org.w3c.dom.Element ; 35 36 45 public final class JDBCRelationMetaData 46 { 47 private final static int TABLE = 1; 48 49 private final static int FOREIGN_KEY = 2; 50 51 52 private final String relationName; 53 54 58 private final JDBCRelationshipRoleMetaData left; 59 60 64 private final JDBCRelationshipRoleMetaData right; 65 66 69 private final int mappingStyle; 70 71 72 private final String dataSourceName; 73 74 75 private final String datasourceMappingName; 76 77 78 private transient DataSource dataSource; 79 80 81 private final JDBCTypeMappingMetaData datasourceMapping; 82 83 84 private final String tableName; 85 86 87 private boolean tableCreated; 88 89 90 private boolean tableDropped; 91 92 93 private final boolean createTable; 94 95 96 private final boolean removeTable; 97 98 99 private final boolean alterTable; 100 101 104 private final ArrayList tablePostCreateCmd; 105 106 107 private final boolean rowLocking; 108 109 110 private final boolean primaryKeyConstraint; 111 112 113 private final boolean readOnly; 114 115 116 private final int readTimeOut; 117 118 126 public JDBCRelationMetaData(JDBCApplicationMetaData jdbcApplication, RelationMetaData relationMetaData) 127 throws DeploymentException 128 { 129 130 relationName = relationMetaData.getRelationName(); 131 132 RelationshipRoleMetaData leftRole = relationMetaData.getLeftRelationshipRole(); 133 RelationshipRoleMetaData rightRole = relationMetaData.getRightRelationshipRole(); 134 135 if (leftRole.isMultiplicityMany() && rightRole.isMultiplicityMany()) 137 { 138 mappingStyle = TABLE; 139 } 140 else 141 { 142 mappingStyle = FOREIGN_KEY; 143 } 144 145 dataSourceName = null; 146 datasourceMappingName = null; 147 datasourceMapping = null; 148 createTable = false; 149 removeTable = false; 150 alterTable = false; 151 rowLocking = false; 152 primaryKeyConstraint = false; 153 readOnly = false; 154 readTimeOut = -1; 155 156 left = new JDBCRelationshipRoleMetaData(this, jdbcApplication, leftRole); 157 158 right = new JDBCRelationshipRoleMetaData(this, jdbcApplication, rightRole); 159 left.init(right); 160 right.init(left); 161 162 if (mappingStyle == TABLE) 163 { 164 tableName = createDefaultTableName(); 165 tablePostCreateCmd = getDefaultTablePostCreateCmd(); 166 } 167 else 168 { 169 tableName = null; 170 tablePostCreateCmd = null; 171 } 172 } 173 174 189 public JDBCRelationMetaData(JDBCApplicationMetaData jdbcApplication, Element element, 190 JDBCRelationMetaData defaultValues) throws DeploymentException 191 { 192 193 relationName = defaultValues.getRelationName(); 194 mappingStyle = loadMappingStyle(element, defaultValues); 195 196 String readOnlyString = MetaData.getOptionalChildContent(element, "read-only"); 198 if (readOnlyString != null) 199 { 200 readOnly = Boolean.valueOf(readOnlyString).booleanValue(); 201 } 202 else 203 { 204 readOnly = defaultValues.isReadOnly(); 205 } 206 207 String readTimeOutString = MetaData.getOptionalChildContent(element, "read-time-out"); 209 if (readTimeOutString != null) 210 { 211 try 212 { 213 readTimeOut = Integer.parseInt(readTimeOutString); 214 } 215 catch (NumberFormatException e) 216 { 217 throw new DeploymentException("Invalid number format in " + "read-time-out '" + readTimeOutString + "': " 218 + e); 219 } 220 } 221 else 222 { 223 readTimeOut = defaultValues.getReadTimeOut(); 224 } 225 226 Element mappingElement = getMappingElement(element); 231 232 String dataSourceNameString = MetaData.getOptionalChildContent(mappingElement, "datasource"); 234 if (dataSourceNameString != null) 235 dataSourceName = dataSourceNameString; 236 else 237 dataSourceName = defaultValues.getDataSourceName(); 238 239 String datasourceMappingString = MetaData.getOptionalChildContent(mappingElement, "datasource-mapping"); 242 if (datasourceMappingString != null) 243 { 244 datasourceMappingName = datasourceMappingString; 245 datasourceMapping = jdbcApplication.getTypeMappingByName(datasourceMappingString); 246 if (datasourceMapping == null) 247 { 248 throw new DeploymentException("Error in jbosscmp-jdbc.xml : " + "datasource-mapping " 249 + datasourceMappingString + " not found"); 250 } 251 } 252 else if(defaultValues.datasourceMappingName != null && defaultValues.getTypeMapping() != null) 253 { 254 datasourceMappingName = null; 255 datasourceMapping = defaultValues.getTypeMapping(); 256 } 257 else 258 { 259 datasourceMappingName = null; 260 datasourceMapping = JDBCEntityMetaData.obtainTypeMappingFromLibrary(dataSourceName); 261 } 262 263 String tableNameString = MetaData.getOptionalChildContent(mappingElement, "table-name"); 265 if (tableNameString == null) 266 { 267 tableNameString = defaultValues.getDefaultTableName(); 268 if (tableNameString == null) 269 { 270 tableNameString = defaultValues.createDefaultTableName(); 274 } 275 } 276 tableName = tableNameString; 277 278 String createString = MetaData.getOptionalChildContent(mappingElement, "create-table"); 280 if (createString != null) 281 { 282 createTable = Boolean.valueOf(createString).booleanValue(); 283 } 284 else 285 { 286 createTable = defaultValues.getCreateTable(); 287 } 288 289 String removeString = MetaData.getOptionalChildContent(mappingElement, "remove-table"); 291 if (removeString != null) 292 { 293 removeTable = Boolean.valueOf(removeString).booleanValue(); 294 } 295 else 296 { 297 removeTable = defaultValues.getRemoveTable(); 298 } 299 300 Element posttc = MetaData.getOptionalChild(mappingElement, "post-table-create"); 302 if (posttc != null) 303 { 304 Iterator it = MetaData.getChildrenByTagName(posttc, "sql-statement"); 305 tablePostCreateCmd = new ArrayList (); 306 while (it.hasNext()) 307 { 308 Element etmp = (Element ) it.next(); 309 tablePostCreateCmd.add(MetaData.getElementContent(etmp)); 310 } 311 } 312 else 313 { 314 tablePostCreateCmd = defaultValues.getDefaultTablePostCreateCmd(); 315 } 316 317 String alterString = MetaData.getOptionalChildContent(mappingElement, "alter-table"); 319 if (alterString != null) 320 { 321 alterTable = Boolean.valueOf(alterString).booleanValue(); 322 } 323 else 324 { 325 alterTable = defaultValues.getAlterTable(); 326 } 327 328 String sForUpString = MetaData.getOptionalChildContent(mappingElement, "row-locking"); 330 if (sForUpString != null) 331 { 332 rowLocking = !isReadOnly() && (Boolean.valueOf(sForUpString).booleanValue()); 333 } 334 else 335 { 336 rowLocking = defaultValues.hasRowLocking(); 337 } 338 339 String pkString = MetaData.getOptionalChildContent(mappingElement, "pk-constraint"); 341 if (pkString != null) 342 { 343 primaryKeyConstraint = Boolean.valueOf(pkString).booleanValue(); 344 } 345 else 346 { 347 primaryKeyConstraint = defaultValues.hasPrimaryKeyConstraint(); 348 } 349 350 JDBCRelationshipRoleMetaData defaultLeft = defaultValues.getLeftRelationshipRole(); 354 JDBCRelationshipRoleMetaData defaultRight = defaultValues.getRightRelationshipRole(); 355 356 if (!MetaData.getChildrenByTagName(element, "ejb-relationship-role").hasNext()) 357 { 358 359 left = new JDBCRelationshipRoleMetaData(this, jdbcApplication, element, defaultLeft); 361 362 right = new JDBCRelationshipRoleMetaData(this, jdbcApplication, element, defaultRight); 363 364 left.init(right); 365 right.init(left); 366 } 367 else 368 { 369 Element leftElement = getEJBRelationshipRoleElement(element, defaultLeft); 370 left = new JDBCRelationshipRoleMetaData(this, jdbcApplication, leftElement, defaultLeft); 371 372 Element rightElement = getEJBRelationshipRoleElement(element, defaultRight); 373 right = new JDBCRelationshipRoleMetaData(this, jdbcApplication, rightElement, defaultRight); 374 375 left.init(right, leftElement); 376 right.init(left, rightElement); 377 } 378 379 if (isForeignKeyMappingStyle() && left.getKeyFields().isEmpty() && right.getKeyFields().isEmpty()) 381 { 382 throw new DeploymentException("Atleast one role of a foreign-key " 383 + "mapped relationship must have key fields " + "(or <primkey-field> is missing from ejb-jar.xml): " 384 + "ejb-relation-name=" + relationName); 385 } 386 387 if (isTableMappingStyle() && (left.getKeyFields().isEmpty() || right.getKeyFields().isEmpty())) 389 { 390 throw new DeploymentException("Both roles of a relation-table " + "mapped relationship must have key fields: " 391 + "ejb-relation-name=" + relationName); 392 } 393 } 394 395 private int loadMappingStyle(Element element, JDBCRelationMetaData defaultValues) throws DeploymentException 396 { 397 398 if ("defaults".equals(element.getTagName())) 400 { 401 String perferredRelationMapping = MetaData.getOptionalChildContent(element, "preferred-relation-mapping"); 403 404 if ("relation-table".equals(perferredRelationMapping) || defaultValues.isManyToMany()) 405 { 406 return TABLE; 407 } 408 else 409 { 410 return FOREIGN_KEY; 411 } 412 } 413 414 if (MetaData.getOptionalChild(element, "relation-table-mapping") != null) 416 { 417 return TABLE; 418 } 419 420 if (MetaData.getOptionalChild(element, "foreign-key-mapping") != null) 422 { 423 if (defaultValues.isManyToMany()) 424 { 425 throw new DeploymentException("Foreign key mapping-style " 426 + "is not allowed for many-to-many relationsips."); 427 } 428 return FOREIGN_KEY; 429 } 430 431 return defaultValues.mappingStyle; 433 } 434 435 private static Element getMappingElement(Element element) throws DeploymentException 436 { 437 438 if ("defaults".equals(element.getTagName())) 440 { 441 return element; 442 } 443 444 Element tableMappingElement = MetaData.getOptionalChild(element, "relation-table-mapping"); 446 if (tableMappingElement != null) 447 { 448 return tableMappingElement; 449 } 450 451 Element foreignKeyMappingElement = MetaData.getOptionalChild(element, "foreign-key-mapping"); 453 if (foreignKeyMappingElement != null) 454 { 455 return foreignKeyMappingElement; 456 } 457 return null; 458 } 459 460 private static Element getEJBRelationshipRoleElement(Element element, JDBCRelationshipRoleMetaData defaultRole) 461 throws DeploymentException 462 { 463 464 String roleName = defaultRole.getRelationshipRoleName(); 465 466 if (roleName == null) 467 throw new DeploymentException("No ejb-relationship-role-name element found"); 468 469 Iterator iter = MetaData.getChildrenByTagName(element, "ejb-relationship-role"); 470 if (!iter.hasNext()) 471 { 472 throw new DeploymentException("No ejb-relationship-role " + "elements found"); 473 } 474 475 Element roleElement = null; 476 for (int i = 0; iter.hasNext(); i++) 477 { 478 if (i > 1) 480 { 481 throw new DeploymentException("Expected only 2 " + "ejb-relationship-role but found more then 2"); 482 } 483 484 Element tempElement = (Element ) iter.next(); 485 if (roleName.equals(MetaData.getUniqueChildContent(tempElement, "ejb-relationship-role-name"))) 486 { 487 roleElement = tempElement; 488 } 489 } 490 491 if (roleElement == null) 492 { 493 throw new DeploymentException("An ejb-relationship-role element was " + "not found for role '" + roleName 494 + "'"); 495 } 496 return roleElement; 497 } 498 499 505 public String getRelationName() 506 { 507 return relationName; 508 } 509 510 517 public JDBCRelationshipRoleMetaData getLeftRelationshipRole() 518 { 519 return left; 520 } 521 522 529 public JDBCRelationshipRoleMetaData getRightRelationshipRole() 530 { 531 return right; 532 } 533 534 541 public JDBCRelationshipRoleMetaData getOtherRelationshipRole(JDBCRelationshipRoleMetaData role) 542 { 543 544 if (left == role) 545 { 546 return right; 547 } 548 else if (right == role) 549 { 550 return left; 551 } 552 else 553 { 554 throw new IllegalArgumentException ("Specified role is not the left " + "or right role. role=" + role); 555 } 556 } 557 558 563 public boolean isTableMappingStyle() 564 { 565 return mappingStyle == TABLE; 566 } 567 568 573 public boolean isForeignKeyMappingStyle() 574 { 575 return mappingStyle == FOREIGN_KEY; 576 } 577 578 583 private String getDataSourceName() 584 { 585 return dataSourceName; 586 } 587 588 593 public JDBCTypeMappingMetaData getTypeMapping() throws DeploymentException 594 { 595 if(datasourceMapping == null) 596 { 597 throw new DeploymentException("type-mapping is not initialized: " + dataSourceName 598 + " was not deployed or type-mapping was not configured."); 599 } 600 601 return datasourceMapping; 602 } 603 604 609 public String getDefaultTableName() 610 { 611 return tableName; 612 } 613 614 620 public ArrayList getDefaultTablePostCreateCmd() 621 { 622 return tablePostCreateCmd; 623 } 624 625 633 public boolean isTableCreated() 634 { 635 return tableCreated; 636 } 637 638 public void setTableCreated() 639 { 640 tableCreated = true; 641 } 642 643 646 public void setTableDropped() 647 { 648 this.tableDropped = true; 649 } 650 651 public boolean isTableDropped() 652 { 653 return tableDropped; 654 } 655 656 662 public boolean getCreateTable() 663 { 664 return createTable; 665 } 666 667 673 public boolean getRemoveTable() 674 { 675 return removeTable; 676 } 677 678 681 public boolean getAlterTable() 682 { 683 return alterTable; 684 } 685 686 693 public boolean hasPrimaryKeyConstraint() 694 { 695 return primaryKeyConstraint; 696 } 697 698 701 public boolean isReadOnly() 702 { 703 return readOnly; 704 } 705 706 709 public int getReadTimeOut() 710 { 711 return readTimeOut; 712 } 713 714 717 public boolean hasRowLocking() 718 { 719 return rowLocking; 720 } 721 722 private String createDefaultTableName() 723 { 724 String defaultTableName = left.getEntity().getName(); 725 if (left.getCMRFieldName() != null) 726 { 727 defaultTableName += "_" + left.getCMRFieldName(); 728 } 729 defaultTableName += "_" + right.getEntity().getName(); 730 if (right.getCMRFieldName() != null) 731 { 732 defaultTableName += "_" + right.getCMRFieldName(); 733 } 734 return defaultTableName; 735 } 736 737 private boolean isManyToMany() 738 { 739 return left.isMultiplicityMany() && right.isMultiplicityMany(); 740 } 741 742 public synchronized DataSource getDataSource() 743 { 744 if (dataSource == null) 745 { 746 try 747 { 748 InitialContext context = new InitialContext (); 749 dataSource = (DataSource ) context.lookup(dataSourceName); 750 } 751 catch (NamingException e) 752 { 753 throw new EJBException ("Data source for relationship named " + relationName + " not found " 754 + dataSourceName); 755 } 756 } 757 return dataSource; 758 } 759 } 760 | Popular Tags |