1 29 30 package com.caucho.ejb.entity; 31 32 import com.caucho.amber.AmberException; 33 import com.caucho.amber.entity.AmberEntityHome; 34 import com.caucho.amber.entity.EntityItem; 35 import com.caucho.amber.manager.AmberConnection; 36 import com.caucho.ejb.AbstractContext; 37 import com.caucho.ejb.AbstractServer; 38 import com.caucho.ejb.EJBExceptionWrapper; 39 import com.caucho.ejb.EjbServerManager; 40 import com.caucho.ejb.FinderExceptionWrapper; 41 import com.caucho.ejb.protocol.AbstractHandle; 42 import com.caucho.ejb.protocol.JVMObject; 43 import com.caucho.util.Alarm; 44 import com.caucho.util.CharBuffer; 45 import com.caucho.util.L10N; 46 47 import javax.ejb.EJBHome ; 48 import javax.ejb.EJBLocalHome ; 49 import javax.ejb.FinderException ; 50 import javax.ejb.HomeHandle ; 51 import javax.ejb.ObjectNotFoundException ; 52 import javax.sql.DataSource ; 53 import java.lang.reflect.Constructor ; 54 import java.lang.reflect.Field ; 55 import java.rmi.RemoteException ; 56 import java.sql.Connection ; 57 import java.util.ArrayList ; 58 import java.util.Collections ; 59 import java.util.Comparator ; 60 import java.util.logging.Level ; 61 62 65 public class EntityServer extends AbstractServer { 66 private static final L10N L = new L10N(EntityServer.class); 67 68 private DataSource _dataSource; 69 70 private HomeHandle _homeHandle; 71 private QEntityContext _homeContext; 72 73 private int _random; 74 75 private boolean _isInit; 76 private boolean _isCMP; 77 78 private boolean _isLoadLazyOnTransaction = true; 79 80 private Field []_primaryKeyFields; 81 82 private Throwable _exception; 83 84 private AmberEntityHome _amberEntityHome; 85 86 private ArrayList <RemoveListener> _removeListeners = 87 new ArrayList <RemoveListener>(); 88 private ArrayList <EntityServer> _updateListeners; 89 90 private Constructor _contextConstructor; 91 92 private boolean _isCacheable = true; 93 private long _cacheTimeout = 1000; 95 private long _invalidateTime; 96 97 private int _jdbcIsolation = -1; 98 99 106 public EntityServer(EjbServerManager ejbManager) 107 { 108 super(ejbManager); 109 110 113 } 116 117 120 public Class getPrimaryKeyClass() 121 { 122 return _primaryKeyClass; 123 } 124 125 128 public void setCMP(boolean isCMP) 129 { 130 _isCMP = isCMP; 131 } 132 133 136 public boolean isCMP() 137 { 138 return _isCMP; 139 } 140 141 144 public boolean getBeanManagedPersistence() 145 { 146 return ! _isCMP; 147 } 148 149 152 public boolean isLoadLazyOnTransaction() 153 { 154 return _isLoadLazyOnTransaction; 155 } 156 157 160 public void setLoadLazyOnTransaction(boolean isLoadLazy) 161 { 162 _isLoadLazyOnTransaction = isLoadLazy; 163 } 164 165 170 public boolean doLoad(long loadTime) 171 { 172 if (loadTime <= _invalidateTime) 173 return true; 174 175 long expiresTime = Alarm.getCurrentTime() - _cacheTimeout; 176 177 return loadTime <= expiresTime; 178 } 179 180 183 public void setAmberEntityHome(AmberEntityHome home) 184 { 185 _amberEntityHome = home; 186 } 187 188 191 198 199 202 public void invalidateCache() 203 { 204 _invalidateTime = Alarm.getCurrentTime(); 205 } 206 207 210 public void setPrimaryKeyClass(Class cl) 211 { 212 _primaryKeyClass = cl; 213 } 214 215 219 public void init() 220 throws Exception 221 { 222 super.init(); 223 224 try { 225 228 232 233 _jdbcIsolation = _ejbManager.getJDBCIsolation(); 234 Class []param = new Class [] { EntityServer.class }; 235 _contextConstructor = _contextImplClass.getConstructor(param); 236 237 _homeContext = (QEntityContext) _contextConstructor.newInstance(this); 238 239 _localHome = _homeContext.createLocalHome(); 240 _remoteHomeView = _homeContext.createRemoteHomeView(); 241 242 252 253 initRelations(); 254 255 if (_isCMP) { 256 _amberEntityHome.setEntityFactory(new AmberEntityFactory(this)); 259 } 260 261 Class primaryKeyClass = getPrimaryKeyClass(); 262 263 if (primaryKeyClass != null && 264 ! primaryKeyClass.isPrimitive() && 265 ! primaryKeyClass.getName().startsWith("java.lang.")) { 266 _primaryKeyFields = primaryKeyClass.getFields(); 267 } 268 269 log.config("initialized entity bean: " + this); 270 } catch (Exception e) { 271 _exception = e; 272 273 throw e; 274 } 275 } 276 277 282 private void initRelations() 283 { 284 if (! isCMP()) 285 return; 286 287 299 } 300 321 322 325 protected AbstractHandle createHandle(Object primaryKey) 326 { 327 return getHandleEncoder().createHandle(encodeId(primaryKey)); 328 } 329 330 333 public String encodeId(Object primaryKey) 334 { 335 if (_primaryKeyFields == null) 336 return String.valueOf(primaryKey); 337 338 try { 339 CharBuffer cb = new CharBuffer(); 340 341 for (int i = 0; i < _primaryKeyFields.length; i++) { 342 if (i != 0) 343 cb.append(','); 344 345 cb.append(_primaryKeyFields[i].get(primaryKey)); 346 } 347 348 return cb.toString(); 349 } catch (IllegalAccessException e) { 350 throw new EJBExceptionWrapper(e); 351 } 352 } 353 354 357 public void postCreate(Object key, QEntityContext cxt) 358 { 359 _ejbManager.putEntityIfNew(this, key, cxt); 360 } 361 362 368 public void addRemoveListener(QEntityContext context) 369 { 370 RemoveListener listener = null; 372 374 if (! _removeListeners.contains(listener)) 375 _removeListeners.add(listener); 376 } 377 378 381 public void addUpdateListener(EntityServer listener) 382 { 383 if (_updateListeners == null) 384 _updateListeners = new ArrayList <EntityServer>(); 385 386 if (! _updateListeners.contains(listener)) 387 _updateListeners.add(listener); 388 } 389 390 393 public void remove(Object key) 394 { 395 for (int i = _removeListeners.size() - 1; i >= 0; i--) { 396 RemoveListener listener = _removeListeners.get(i); 397 398 try { 399 listener._listener._caucho_remove_callback(listener._listenClass, key); 400 } catch (Throwable e) { 401 EJBExceptionWrapper.createRuntime(e); 402 } 403 } 404 } 405 406 public void removeCache(Object key) 407 { 408 _ejbManager.removeEntity(this, key); 409 } 410 411 414 public AbstractContext findByPrimaryKey(Object key) 415 throws FinderException 416 { 417 return getContext(key, _isCMP); 418 } 419 420 423 public AbstractContext findByPrimaryKey(int key) 424 throws FinderException 425 { 426 return getContext(new Long (key), _isCMP); 427 } 428 429 434 public AbstractContext findKnownObjectByPrimaryKey(Object key) 435 { 436 if (key == null) 438 return null; 439 440 try { 441 return getContext(key, false); 442 } catch (FinderException e) { 443 throw EJBExceptionWrapper.createRuntime(e); 444 } 445 } 446 447 452 public Object findKnownObjectByPrimaryKey(int key) 453 { 454 return findKnownObjectByPrimaryKey(new Integer (key)); 455 } 456 457 460 public EJBHome getClientHome() 461 throws RemoteException 462 { 463 if (! _isInit) { 464 471 472 _isInit = true; 473 } 474 475 if (_remoteHome == null) { 476 try { 477 _remoteHome = _jvmClient.createHomeStub(); 478 } catch (Exception e) { 479 EJBExceptionWrapper.createRuntime(e); 480 } 481 } 482 483 return _remoteHome; 484 } 485 486 489 public EJBHome getEJBHome() 490 throws RemoteException 491 { 492 return _remoteHomeView; 493 514 } 515 516 519 public EJBLocalHome getClientLocalHome() 520 { 521 if (! _isInit) { 522 529 530 _isInit = true; 531 } 532 533 return _localHome; 534 } 535 536 public Object getHomeObject() 537 { 538 if (! _isInit) { 539 546 547 _isInit = true; 548 } 549 550 return _remoteHomeView; 551 } 552 553 556 573 574 577 JVMObject createEJBObject(Object primaryKey) 578 { 579 if (_remoteStubClass == null) 580 throw new IllegalStateException (L.l("`{0}' has no remote interface. Local beans must be called from a local context. Remote beans need a home and a remote interface.", 581 getEJBName())); 582 583 try { 584 JVMObject obj = (JVMObject) _remoteStubClass.newInstance(); 585 obj._init(this, primaryKey); 586 587 return obj; 588 } catch (Exception e) { 589 throw new EJBExceptionWrapper(e); 590 } 591 } 592 593 public AbstractContext getContext(Object key) 594 throws FinderException 595 { 596 return getContext(key, _isCMP); 597 } 598 599 606 public AbstractContext getContext(Object key, boolean forceLoad) 607 throws FinderException 608 { 609 if (key == null) 610 return null; 611 612 QEntityContext cxt = _ejbManager.getEntity(this, key); 613 614 try { 615 if (cxt == null) { 616 EntityItem amberItem = null; 617 618 if (_isCMP) { 619 AmberConnection aConn; 620 aConn = _amberEntityHome.getManager().getCacheConnection(); 621 622 try { 623 628 amberItem = _amberEntityHome.findEntityItem(aConn, 630 key, 631 forceLoad); 632 } catch (AmberException e) { 633 String name = getEJBName(); 634 635 FinderException exn = new ObjectNotFoundException (L.l("'{0}' is an unknown entity.", 636 name + "[" + key + "]")); 637 exn.initCause(e); 638 throw exn; 639 } finally { 640 aConn.freeConnection(); 641 } 642 } 643 644 cxt = (QEntityContext) _contextConstructor.newInstance(this); 645 cxt.setPrimaryKey(key); 646 647 if (amberItem != null) 648 cxt.__caucho_setAmber(amberItem); 649 } 650 651 if (forceLoad && 653 (! _isLoadLazyOnTransaction || 654 getTransactionManager().getTransaction() != null)) { 655 try { 656 cxt._caucho_load(); 657 } catch (Exception e) { 658 throw e; 659 } 660 } 661 662 669 cxt = _ejbManager.putEntityIfNew(this, key, cxt); 670 671 return cxt; 672 } catch (FinderException e) { 673 throw e; 674 } catch (Exception e) { 675 throw FinderExceptionWrapper.create(e); 676 } 677 } 678 679 682 public Connection getConnection(boolean isReadOnly) 683 throws java.sql.SQLException 684 { 685 if (isReadOnly) 686 return _dataSource.getConnection(); 687 else { 688 Connection conn = _dataSource.getConnection(); 689 690 if (_jdbcIsolation > 0) 691 conn.setTransactionIsolation(_jdbcIsolation); 692 693 return conn; 694 } 695 } 696 697 700 public void update(Object key) 701 { 702 if (key == null) 703 return; 704 705 QEntityContext cxt = _ejbManager.getEntity(this, key); 706 707 if (cxt == null) 708 return; 709 710 cxt.update(); 713 } 714 715 718 public void updateView(Object key) 719 { 720 if (_updateListeners == null) 721 return; 722 723 for (int i = _updateListeners.size() - 1; i >= 0; i--) { 724 EntityServer server = _updateListeners.get(i); 725 726 server.update(key); 727 } 728 } 729 730 736 public String randomString(int max, int i) 737 { 738 return String.valueOf(++_random); 739 } 740 741 747 public int randomInt(int max, int i) 748 { 749 return max; 750 } 751 752 public static IllegalStateException createGetStateException(int state) 753 { 754 switch (state) { 755 case QEntity._CAUCHO_IS_REMOVED: 756 return new IllegalStateException (L.l("Can't access CMP field for a removed object.")); 757 758 case QEntity._CAUCHO_IS_DEAD: 759 return new IllegalStateException (L.l("Can't access CMP field for a dead object. The object is dead due to a runtime exception and rollback.")); 760 761 case QEntity._CAUCHO_IS_NEW: 762 return new IllegalStateException (L.l("Can't access CMP field for an uninitialized object.")); 763 764 case QEntity._CAUCHO_IS_HOME: 765 return new IllegalStateException (L.l("Can't access CMP field from a Home object.")); 766 767 default: 768 return new IllegalStateException (L.l("Can't access CMP field from an unknown state.")); 769 } 770 } 771 772 public static IllegalStateException createSetStateException(int state) 773 { 774 switch (state) { 775 case QEntity._CAUCHO_IS_REMOVED: 776 return new IllegalStateException (L.l("Can't set CMP field for a removed object.")); 777 778 case QEntity._CAUCHO_IS_DEAD: 779 return new IllegalStateException (L.l("Can't set CMP field for a dead object. The object is dead due to a runtime exception and rollback.")); 780 781 case QEntity._CAUCHO_IS_NEW: 782 return new IllegalStateException (L.l("Can't set CMP field for an uninitialized object.")); 783 784 case QEntity._CAUCHO_IS_HOME: 785 return new IllegalStateException (L.l("Can't set CMP field from a Home object.")); 786 787 default: 788 return new IllegalStateException (L.l("Can't set CMP field from an unknown state.")); 789 } 790 } 791 792 795 public void destroy() 796 { 797 ArrayList <QEntityContext> beans = new ArrayList <QEntityContext>(); 798 799 _ejbManager.removeBeans(beans, this); 800 801 Collections.sort(beans, new EntityCmp()); 803 804 for (int i = 0; i < beans.size(); i++) { 805 QEntityContext cxt = beans.get(i); 806 807 try { 808 cxt.destroy(); 809 } catch (Exception e) { 810 log.log(Level.WARNING, e.toString(), e); 811 } 812 } 813 814 QEntityContext homeContext = _homeContext; 815 _homeContext = null; 816 817 try { 818 if (homeContext != null) 819 homeContext.destroy(); 820 } catch (Exception e) { 821 log.log(Level.WARNING, e.toString(), e); 822 } 823 824 super.destroy(); 825 } 826 827 static class RemoveListener { 828 QEntityContext _listener; 829 Class _listenClass; 830 831 RemoveListener(QEntityContext listener, Class listenClass) 832 { 833 _listener = listener; 834 _listenClass = listenClass; 835 } 836 837 public boolean equals(Object o) 838 { 839 if (! (o instanceof RemoveListener)) 840 return false; 841 842 RemoveListener listener = (RemoveListener) o; 843 844 return (_listener.equals(listener._listener) && 845 _listenClass.equals(listener._listenClass)); 846 } 847 848 public String toString() 849 { 850 return "RemoveListener[" + _listener + "]"; 851 } 852 } 853 854 static class EntityCmp 855 implements Comparator <QEntityContext> { 856 public int compare(QEntityContext ca, QEntityContext cb) 857 { 858 try { 859 String sa = String.valueOf(ca.getPrimaryKey()); 860 String sb = String.valueOf(cb.getPrimaryKey()); 861 862 return sa.compareTo(sb); 863 } catch (Exception e) { 864 return 0; 865 } 866 } 867 } 868 } 869 | Popular Tags |