1 22 package org.jboss.ejb.plugins.cmp.jdbc; 23 24 import java.lang.reflect.Method ; 25 import java.util.ArrayList ; 26 import java.util.Collection ; 27 import java.util.HashMap ; 28 import java.util.Map ; 29 import java.util.Set ; 30 import java.util.HashSet ; 31 import java.util.List ; 32 import java.util.Iterator ; 33 import java.rmi.RemoteException ; 34 35 import javax.ejb.CreateException ; 36 import javax.ejb.EJBException ; 37 import javax.ejb.FinderException ; 38 import javax.ejb.RemoveException ; 39 import javax.transaction.Status ; 40 import javax.transaction.Transaction ; 41 import javax.transaction.TransactionManager ; 42 43 import org.jboss.deployment.DeploymentException; 44 import org.jboss.ejb.Container; 45 import org.jboss.ejb.EjbModule; 46 import org.jboss.ejb.EntityContainer; 47 import org.jboss.ejb.EntityEnterpriseContext; 48 import org.jboss.ejb.GenericEntityObjectFactory; 49 import org.jboss.ejb.plugins.cmp.ejbql.Catalog; 50 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCCMPFieldBridge; 51 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCCMRFieldBridge; 52 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCEntityBridge; 53 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCAbstractEntityBridge; 54 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCApplicationMetaData; 55 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCEntityMetaData; 56 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCXmlFileLoader; 57 import org.jboss.logging.Logger; 58 import org.jboss.metadata.ApplicationMetaData; 59 import org.jboss.tm.TransactionLocal; 60 61 79 public final class JDBCStoreManager implements JDBCEntityPersistenceStore 80 { 81 82 private static final Object TX_DATA_KEY = "TX_DATA_KEY"; 83 84 private static final String CATALOG = "CATALOG"; 85 86 private static final String CREATED_MANAGERS = "CREATED_JDBCStoreManagers"; 87 private static final String CMP_JDBC = "CMP-JDBC"; 88 89 private EjbModule ejbModule; 90 private EntityContainer container; 91 private Logger log; 92 93 private JDBCEntityMetaData metaData; 94 private JDBCEntityBridge entityBridge; 95 96 private JDBCTypeFactory typeFactory; 97 private JDBCQueryManager queryManager; 98 99 private JDBCCommandFactory commandFactory; 100 101 private ReadAheadCache readAheadCache; 102 103 private JDBCInitCommand initCommand; 105 private JDBCStartCommand startCommand; 106 private JDBCStopCommand stopCommand; 107 private JDBCDestroyCommand destroyCommand; 108 109 private JDBCCreateBeanClassInstanceCommand createBeanClassInstanceCommand; 111 private JDBCInitEntityCommand initEntityCommand; 112 private JDBCFindEntityCommand findEntityCommand; 113 private JDBCFindEntitiesCommand findEntitiesCommand; 114 private JDBCCreateCommand createEntityCommand; 115 private JDBCPostCreateEntityCommand postCreateEntityCommand; 116 private JDBCRemoveEntityCommand removeEntityCommand; 117 private JDBCLoadEntityCommand loadEntityCommand; 118 private JDBCIsModifiedCommand isModifiedCommand; 119 private JDBCStoreEntityCommand storeEntityCommand; 120 private JDBCActivateEntityCommand activateEntityCommand; 121 private JDBCPassivateEntityCommand passivateEntityCommand; 122 123 private JDBCLoadRelationCommand loadRelationCommand; 125 private JDBCDeleteRelationsCommand deleteRelationsCommand; 126 private JDBCInsertRelationsCommand insertRelationsCommand; 127 128 129 private TransactionManager tm; 130 private TransactionLocal txDataMap; 131 132 133 private TransactionLocal cascadeDeleteSet = new TransactionLocal() 134 { 135 protected Object initialValue() 136 { 137 return new CascadeDeleteRegistry(); 138 } 139 }; 140 141 145 public EntityContainer getContainer() 146 { 147 return container; 148 } 149 150 156 public void setContainer(Container container) 157 { 158 this.container = (EntityContainer)container; 159 if(container != null) 160 { 161 ejbModule = container.getEjbModule(); 162 log = Logger.getLogger( 163 this.getClass().getName() + 164 "." + 165 container.getBeanMetaData().getEjbName()); 166 } 167 else 168 { 169 ejbModule = null; 170 } 171 } 172 173 public JDBCAbstractEntityBridge getEntityBridge() 174 { 175 return entityBridge; 176 } 177 178 public JDBCTypeFactory getJDBCTypeFactory() 179 { 180 return typeFactory; 181 } 182 183 public JDBCEntityMetaData getMetaData() 184 { 185 return metaData; 186 } 187 188 public JDBCQueryManager getQueryManager() 189 { 190 return queryManager; 191 } 192 193 public JDBCCommandFactory getCommandFactory() 194 { 195 return commandFactory; 196 } 197 198 public ReadAheadCache getReadAheadCache() 199 { 200 return readAheadCache; 201 } 202 203 public Map getApplicationDataMap() 207 { 208 return ejbModule.getModuleDataMap(); 209 } 210 211 public Object getApplicationData(Object key) 212 { 213 return ejbModule.getModuleData(key); 214 } 215 216 public void putApplicationData(Object key, Object value) 217 { 218 ejbModule.putModuleData(key, value); 219 } 220 221 private Map getApplicationTxDataMap() 222 { 223 try 224 { 225 Transaction tx = tm.getTransaction(); 226 if(tx == null) 227 { 228 return null; 229 } 230 231 Map txMap = (Map )txDataMap.get(tx); 233 234 if(txMap == null) 236 { 237 int status = tx.getStatus(); 238 if(status == Status.STATUS_ACTIVE || status == Status.STATUS_PREPARING) 239 { 240 txMap = new HashMap (); 242 txDataMap.set(tx, txMap); 243 } 244 } 245 return txMap; 246 } 247 catch(EJBException e) 248 { 249 throw e; 250 } 251 catch(Exception e) 252 { 253 throw new EJBException ("Error getting application tx data map.", e); 254 } 255 } 256 257 260 public void scheduleCascadeDelete(List pks) 261 { 262 CascadeDeleteRegistry registry = (CascadeDeleteRegistry)cascadeDeleteSet.get(); 263 registry.scheduleAll(pks); 264 } 265 266 271 public boolean unscheduledCascadeDelete(Object pk) 272 { 273 CascadeDeleteRegistry registry = (CascadeDeleteRegistry)cascadeDeleteSet.get(); 274 return registry.unschedule(pk); 275 } 276 277 public Object getApplicationTxData(Object key) 278 { 279 Map map = getApplicationTxDataMap(); 280 if(map != null) 281 { 282 return map.get(key); 283 } 284 return null; 285 } 286 287 public void putApplicationTxData(Object key, Object value) 288 { 289 Map map = getApplicationTxDataMap(); 290 if(map != null) 291 { 292 map.put(key, value); 293 } 294 } 295 296 private Map getEntityTxDataMap() 297 { 298 Map entityTxDataMap = (Map )getApplicationTxData(this); 299 if(entityTxDataMap == null) 300 { 301 entityTxDataMap = new HashMap (); 302 putApplicationTxData(this, entityTxDataMap); 303 } 304 return entityTxDataMap; 305 } 306 307 public Object getEntityTxData(Object key) 308 { 309 return getEntityTxDataMap().get(key); 310 } 311 312 public void putEntityTxData(Object key, Object value) 313 { 314 getEntityTxDataMap().put(key, value); 315 } 316 317 public void removeEntityTxData(Object key) 318 { 319 getEntityTxDataMap().remove(key); 320 } 321 322 public Catalog getCatalog() 323 { 324 return (Catalog)getApplicationData(CATALOG); 325 } 326 327 private void initApplicationDataMap() 328 { 329 Map moduleData = ejbModule.getModuleDataMap(); 330 synchronized(moduleData) 331 { 332 txDataMap = (TransactionLocal)moduleData.get(TX_DATA_KEY); 333 if(txDataMap == null) 334 { 335 txDataMap = new TransactionLocal(); 336 moduleData.put(TX_DATA_KEY, txDataMap); 337 } 338 } 339 } 340 341 345 public void create() throws Exception 346 { 347 HashMap managersMap = (HashMap )getApplicationData(CREATED_MANAGERS); 351 if(managersMap == null) 352 { 353 managersMap = new HashMap (); 354 putApplicationData(CREATED_MANAGERS, managersMap); 355 } 356 managersMap.put(container.getBeanMetaData().getEjbName(), this); 357 } 358 359 362 public void start() throws Exception 363 { 364 initStoreManager(); 369 370 371 Catalog catalog = getCatalog(); 374 HashMap managersMap = (HashMap )getApplicationData(CREATED_MANAGERS); 375 if(catalog.getEntityCount() == managersMap.size() 376 && catalog.getEJBNames().equals(managersMap.keySet())) 377 { 378 ArrayList managers = new ArrayList (managersMap.values()); 380 381 for(int i = 0; i < managers.size(); ++i) 385 { 386 JDBCStoreManager manager = (JDBCStoreManager)managers.get(i); 387 manager.resolveRelationships(); 388 } 389 390 for(int i = 0; i < managers.size(); ++i) 394 { 395 JDBCStoreManager manager = (JDBCStoreManager)managers.get(i); 396 manager.startStoreManager(); 397 } 398 399 for(int i = 0; i < managers.size(); ++i) 401 { 402 JDBCStoreManager manager = (JDBCStoreManager)managers.get(i); 403 manager.startCommand.addForeignKeyConstraints(); 404 } 405 } 406 } 407 408 412 private void initStoreManager() throws Exception 413 { 414 if(log.isDebugEnabled()) 415 log.debug("Initializing CMP plugin for " + container.getBeanMetaData().getEjbName()); 416 417 tm = container.getTransactionManager(); 419 420 initApplicationDataMap(); 422 423 metaData = loadJDBCEntityMetaData(); 425 426 typeFactory = new JDBCTypeFactory( 428 metaData.getTypeMapping(), 429 metaData.getJDBCApplication().getValueClasses(), 430 metaData.getJDBCApplication().getUserTypeMappings() 431 ); 432 433 entityBridge = new JDBCEntityBridge(metaData, this); 435 entityBridge.init(); 436 437 Catalog catalog = getCatalog(); 439 if(catalog == null) 440 { 441 catalog = new Catalog(); 442 putApplicationData(CATALOG, catalog); 443 } 444 catalog.addEntity(entityBridge); 445 446 readAheadCache = new ReadAheadCache(this); 448 readAheadCache.create(); 449 450 commandFactory = new JDBCCommandFactory(this); 452 453 initCommand = commandFactory.createInitCommand(); 455 initCommand.execute(); 456 } 457 458 private void resolveRelationships() throws Exception 459 { 460 entityBridge.resolveRelationships(); 461 } 462 463 467 private void startStoreManager() throws Exception 468 { 469 entityBridge.start(); 470 471 startCommand = commandFactory.createStartCommand(); 473 stopCommand = commandFactory.createStopCommand(); 474 destroyCommand = commandFactory.createDestroyCommand(); 475 476 initEntityCommand = commandFactory.createInitEntityCommand(); 478 createBeanClassInstanceCommand = commandFactory.createCreateBeanClassInstanceCommand(); 479 findEntityCommand = commandFactory.createFindEntityCommand(); 480 findEntitiesCommand = commandFactory.createFindEntitiesCommand(); 481 createEntityCommand = commandFactory.createCreateEntityCommand(); 482 postCreateEntityCommand = commandFactory.createPostCreateEntityCommand(); 483 removeEntityCommand = commandFactory.createRemoveEntityCommand(); 484 loadEntityCommand = commandFactory.createLoadEntityCommand(); 485 isModifiedCommand = commandFactory.createIsModifiedCommand(); 486 storeEntityCommand = commandFactory.createStoreEntityCommand(); 487 activateEntityCommand = commandFactory.createActivateEntityCommand(); 488 passivateEntityCommand = commandFactory.createPassivateEntityCommand(); 489 490 loadRelationCommand = commandFactory.createLoadRelationCommand(); 492 deleteRelationsCommand = commandFactory.createDeleteRelationsCommand(); 493 insertRelationsCommand = commandFactory.createInsertRelationsCommand(); 494 495 queryManager = new JDBCQueryManager(this); 497 498 startCommand.execute(); 500 501 queryManager.start(); 506 507 readAheadCache.start(); 508 } 509 510 public void stop() 511 { 512 if(stopCommand != null) 514 { 515 Map managersMap = (HashMap )getApplicationData(CREATED_MANAGERS); 516 while(!managersMap.isEmpty()) 517 { 518 int stoppedInIteration = 0; 519 for(Iterator i = managersMap.values().iterator(); i.hasNext();) 520 { 521 JDBCStoreManager manager = (JDBCStoreManager)i.next(); 522 if(manager.stopCommand == null || manager.stopCommand.execute()) 523 { 524 i.remove(); 525 ++stoppedInIteration; 526 } 527 } 528 529 if(stoppedInIteration == 0) 530 { 531 break; 532 } 533 } 534 } 535 readAheadCache.stop(); 536 } 537 538 public void destroy() 539 { 540 if(destroyCommand != null) 542 { 543 destroyCommand.execute(); 544 } 545 546 if(readAheadCache != null) 547 { 548 readAheadCache.destroy(); 549 } 550 551 readAheadCache = null; 552 if(queryManager != null) 553 { 554 queryManager.clear(); 555 } 556 queryManager = null; 557 if(createBeanClassInstanceCommand != null) 559 { 560 createBeanClassInstanceCommand.destroy(); 561 } } 563 564 572 public Object createBeanClassInstance() throws Exception 573 { 574 if(createBeanClassInstanceCommand == null) 575 throw new IllegalStateException ("createBeanClassInstanceCommand == null"); 576 return createBeanClassInstanceCommand.execute(); 577 } 578 579 public void initEntity(EntityEnterpriseContext ctx) 580 { 581 initEntityCommand.execute(ctx); 582 } 583 584 public Object createEntity(Method createMethod, Object [] args, EntityEnterpriseContext ctx) 585 throws CreateException 586 { 587 Object pk = createEntityCommand.execute(createMethod, args, ctx); 588 if(pk == null) 589 throw new CreateException ("Primary key for created instance is null."); 590 return pk; 591 } 592 593 public Object postCreateEntity(Method createMethod, Object [] args, EntityEnterpriseContext ctx) 594 { 595 return postCreateEntityCommand.execute(createMethod, args, ctx); 596 } 597 598 public Object findEntity(Method finderMethod, 599 Object [] args, 600 EntityEnterpriseContext ctx, 601 GenericEntityObjectFactory factory) 602 throws FinderException 603 { 604 return findEntityCommand.execute(finderMethod, args, ctx, factory); 605 } 606 607 public Collection findEntities(Method finderMethod, 608 Object [] args, 609 EntityEnterpriseContext ctx, 610 GenericEntityObjectFactory factory) 611 throws FinderException 612 { 613 return findEntitiesCommand.execute(finderMethod, args, ctx, factory); 614 } 615 616 public void activateEntity(EntityEnterpriseContext ctx) 617 { 618 activateEntityCommand.execute(ctx); 619 } 620 621 626 public void loadEntity(EntityEnterpriseContext ctx) 627 { 628 loadEntity(ctx, true); 629 } 630 631 public boolean loadEntity(EntityEnterpriseContext ctx, boolean failIfNotFound) 632 { 633 if(!ctx.isValid()) 635 { 636 if(log.isTraceEnabled()) 637 { 638 log.trace("RESET PERSISTENCE CONTEXT: id=" + ctx.getId()); 639 } 640 entityBridge.resetPersistenceContext(ctx); 641 } 642 643 JDBCEntityBridge.setCreated(ctx); 645 646 return loadEntityCommand.execute(ctx, failIfNotFound); 647 } 648 649 public void loadField(JDBCCMPFieldBridge field, EntityEnterpriseContext ctx) 650 { 651 loadEntityCommand.execute(field, ctx); 652 } 653 654 public boolean isStoreRequired(EntityEnterpriseContext ctx) 655 { 656 return isModifiedCommand.execute(ctx); 657 } 658 659 public boolean isModified(EntityEnterpriseContext ctx) 660 { 661 return entityBridge.isModified(ctx); 662 } 663 664 public void storeEntity(EntityEnterpriseContext ctx) 665 { 666 storeEntityCommand.execute(ctx); 667 synchronizeRelationData(); 668 } 669 670 private void synchronizeRelationData() 671 { 672 final JDBCCMRFieldBridge[] cmrFields = (JDBCCMRFieldBridge[]) entityBridge.getCMRFields(); 673 for(int i = 0; i < cmrFields.length; ++i) 674 { 675 final JDBCCMRFieldBridge.RelationDataManager relationManager = cmrFields[i].getRelationDataManager(); 676 if(relationManager.isDirty()) 677 { 678 final RelationData relationData = relationManager.getRelationData(); 679 680 deleteRelations(relationData); 681 insertRelations(relationData); 682 683 relationData.addedRelations.clear(); 684 relationData.removedRelations.clear(); 685 relationData.notRelatedPairs.clear(); 686 } 687 } 688 } 689 690 public void passivateEntity(EntityEnterpriseContext ctx) 691 { 692 passivateEntityCommand.execute(ctx); 693 } 694 695 public void removeEntity(EntityEnterpriseContext ctx) throws RemoveException , RemoteException 696 { 697 removeEntityCommand.execute(ctx); 698 } 699 700 public Collection loadRelation(JDBCCMRFieldBridge cmrField, Object pk) 704 { 705 return loadRelationCommand.execute(cmrField, pk); 706 } 707 708 private void deleteRelations(RelationData relationData) 709 { 710 deleteRelationsCommand.execute(relationData); 711 } 712 713 private void insertRelations(RelationData relationData) 714 { 715 insertRelationsCommand.execute(relationData); 716 } 717 718 private JDBCEntityMetaData loadJDBCEntityMetaData() 719 throws DeploymentException 720 { 721 ApplicationMetaData amd = container.getBeanMetaData().getApplicationMetaData(); 722 723 JDBCApplicationMetaData jamd = (JDBCApplicationMetaData)amd.getPluginData(CMP_JDBC); 725 726 if(jamd == null) 727 { 728 JDBCXmlFileLoader jfl = new JDBCXmlFileLoader(container, log); 731 732 jamd = jfl.load(); 733 amd.addPluginData(CMP_JDBC, jamd); 734 } 735 736 String ejbName = container.getBeanMetaData().getEjbName(); 738 JDBCEntityMetaData metadata = jamd.getBeanByEjbName(ejbName); 739 if(metadata == null) 740 { 741 throw new DeploymentException("No metadata found for bean " + ejbName); 742 } 743 return metadata; 744 } 745 746 748 private final class CascadeDeleteRegistry 749 { 750 private Set scheduled; 751 752 public void scheduleAll(List pks) 753 { 754 if(scheduled == null) 755 { 756 scheduled = new HashSet (); 757 } 758 scheduled.addAll(pks); 759 } 760 761 public boolean unschedule(Object pk) 762 { 763 return scheduled.remove(pk); 764 } 765 } 766 } 767 | Popular Tags |