1 27 28 package org.objectweb.speedo.pm.lib; 29 30 import java.util.ArrayList ; 31 import java.util.Collection ; 32 import java.util.Collections ; 33 import java.util.HashMap ; 34 import java.util.Iterator ; 35 import java.util.Map ; 36 import java.util.Set ; 37 38 import javax.jdo.Extent; 39 import javax.jdo.FetchPlan; 40 import javax.jdo.JDODataStoreException; 41 import javax.jdo.JDOException; 42 import javax.jdo.JDOFatalInternalException; 43 import javax.jdo.JDOFatalUserException; 44 import javax.jdo.JDOUnsupportedOptionException; 45 import javax.jdo.JDOUserException; 46 import javax.jdo.PersistenceManager; 47 import javax.jdo.PersistenceManagerFactory; 48 import javax.jdo.Query; 49 import javax.jdo.datastore.JDOConnection; 50 import javax.jdo.datastore.Sequence; 51 import javax.jdo.listener.InstanceLifecycleEvent; 52 import javax.jdo.listener.InstanceLifecycleListener; 53 import javax.transaction.Status ; 54 55 import org.objectweb.fractal.api.Component; 56 import org.objectweb.fractal.api.Interface; 57 import org.objectweb.fractal.api.NoSuchInterfaceException; 58 import org.objectweb.fractal.api.control.BindingController; 59 import org.objectweb.fractal.util.Fractal; 60 import org.objectweb.jorm.api.PClassMapping; 61 import org.objectweb.jorm.api.PException; 62 import org.objectweb.jorm.naming.api.PName; 63 import org.objectweb.jorm.naming.api.PNameCoder; 64 import org.objectweb.jorm.util.api.Loggable; 65 import org.objectweb.perseus.cache.api.CacheEntry; 66 import org.objectweb.perseus.concurrency.lib.Semaphore; 67 import org.objectweb.perseus.persistence.api.NoDSIPersistenceException; 68 import org.objectweb.perseus.persistence.api.PersistenceException; 69 import org.objectweb.perseus.persistence.api.RolledBackPersistenceException; 70 import org.objectweb.perseus.persistence.api.State; 71 import org.objectweb.perseus.persistence.api.StateFilter; 72 import org.objectweb.perseus.persistence.api.TransactionalPersistenceManager; 73 import org.objectweb.perseus.persistence.api.TransactionalWorkingSet; 74 import org.objectweb.perseus.persistence.api.VirtualState; 75 import org.objectweb.speedo.api.ExceptionHelper; 76 import org.objectweb.speedo.api.SpeedoProperties; 77 import org.objectweb.speedo.genclass.api.SpeedoGenClassProxy; 78 import org.objectweb.speedo.mapper.api.JormFactory; 79 import org.objectweb.speedo.metadata.SpeedoVersion; 80 import org.objectweb.speedo.mim.api.DetachedLifeCycle; 81 import org.objectweb.speedo.mim.api.LifeCycle; 82 import org.objectweb.speedo.mim.api.SpeedoAccessor; 83 import org.objectweb.speedo.mim.api.SpeedoHome; 84 import org.objectweb.speedo.mim.api.SpeedoProxy; 85 import org.objectweb.speedo.mim.lib.SpeedoFetchPlan; 86 import org.objectweb.speedo.pm.api.ProxyManager; 87 import org.objectweb.speedo.pm.api.ProxyManagerFactory; 88 import org.objectweb.speedo.query.api.QueryDefinition; 89 import org.objectweb.speedo.query.api.QueryManager; 90 import org.objectweb.speedo.query.api.QueryManagerAttribute; 91 import org.objectweb.speedo.query.lib.SpeedoExtent; 92 import org.objectweb.speedo.query.lib.SpeedoQuery; 93 import org.objectweb.speedo.workingset.api.Transaction; 94 import org.objectweb.util.monolog.api.BasicLevel; 95 import org.objectweb.util.monolog.api.Logger; 96 import org.objectweb.util.monolog.api.LoggerFactory; 97 98 99 126 public class SpeedoProxyManager 127 implements PersistenceManager, 128 ProxyManager, 129 BindingController{ 130 131 public final static String PROXY_MANAGER_FACTORY_BINDING = "proxy-manager-factory"; 132 public final static String TRANSACTIONAL_PERSISTENCE_MANAGER_BINDING = "transactional-persistence-manager"; 133 public final static String QUERY_MANAGER_BINDING = "query-manager"; 134 public final static String TRANSACTION_BINDING = "transaction"; 135 public final static String JORM_FACTORY_BINDING = "jorm-factory"; 136 public final static String PNAME_CODER_BINDING = "pname-coder"; 137 public final static String COMPONENT_BINDING = "component"; 138 public final static String LOGGER_NAME 139 = SpeedoProperties.LOGGER_NAME + ".rt.SpeedoProxyManager"; 140 141 private Logger logger; 142 private LoggerFactory loggerFactory; 143 144 147 private ProxyManagerFactory pmf = null; 148 149 153 private QueryManager queryManager = null; 154 155 158 private Transaction tx; 159 160 163 private TransactionalPersistenceManager tpm = null; 164 165 168 private JormFactory jf = null; 169 170 173 private PNameCoder pnc = null; 174 175 178 private Object connectionSpec = null; 179 180 184 private short nbUse = 0; 185 186 189 private Object userObject = null; 190 191 194 boolean ignoreCache = true; 195 196 199 private ProxyManager thisPM = null; 200 201 204 private Thread currentThread = null; 205 206 209 private Semaphore semaphore; 210 211 private boolean prefetchOnExtent = true; 212 private boolean prefetchOnQuery = true; 213 214 private FetchPlan fetchPlan; 215 216 private HashMap userObjects = new HashMap (); 217 218 public SpeedoProxyManager() { 219 semaphore = new Semaphore(false); 220 } 221 222 public Query createQuery(Object o) { 223 SpeedoQuery sq = new SpeedoQuery(); 224 sq.withPrefetch(prefetchOnQuery); 225 sq.setProxyManager(this); 226 sq.setFetchPlan(getFetchPlan()); 228 sq.setQueryManager(queryManager); 229 sq.setIgnoreCache(ignoreCache); 230 sq.setLogger(loggerFactory.getLogger(logger.getName() + ".query")); 231 if (o!= null && o instanceof QueryDefinition) { 232 sq.defineWith((QueryDefinition) o); 233 } 234 return sq; 235 } 236 237 238 241 public String [] listFc() { 242 return new String [] { 243 PROXY_MANAGER_FACTORY_BINDING, 244 QUERY_MANAGER_BINDING, 245 TRANSACTIONAL_PERSISTENCE_MANAGER_BINDING, 246 TRANSACTION_BINDING, 247 JORM_FACTORY_BINDING, 248 PNAME_CODER_BINDING 249 }; 250 } 251 252 public Object lookupFc(String s) { 253 if (PROXY_MANAGER_FACTORY_BINDING.equals(s)) { 254 return pmf; 255 } else if (QUERY_MANAGER_BINDING.equals(s)) { 256 return queryManager; 257 } else if (TRANSACTIONAL_PERSISTENCE_MANAGER_BINDING.equals(s)) { 258 return tpm; 259 } else if (TRANSACTION_BINDING.equals(s)) { 260 return tx; 261 } else if (PNAME_CODER_BINDING.equals(s)) { 262 return pnc; 263 } else if (JORM_FACTORY_BINDING.equals(s)) { 264 return jf; 265 } else { 266 return null; 267 } 268 } 269 270 public void bindFc(String s, Object o) { 271 if ("monolog-factory".equals(s)) { 272 loggerFactory = (LoggerFactory) o; 273 } else if ("logger".equals(s)) { 274 logger = (Logger) o; 275 } else if (PROXY_MANAGER_FACTORY_BINDING.equals(s)) { 276 pmf = (ProxyManagerFactory) o; 277 } else if (QUERY_MANAGER_BINDING.equals(s)) { 278 queryManager = (QueryManager) o; 279 if (queryManager != null) { 280 try { 281 QueryManagerAttribute qma = (QueryManagerAttribute) 282 Fractal.getAttributeController( 283 ((Interface) queryManager).getFcItfOwner()) ; 284 prefetchOnExtent = qma.getPrefetchActivatedOnExtent(); 285 prefetchOnQuery = qma.getPrefetchActivatedOnQuery(); 286 } catch (Exception e) { 287 logger.log(BasicLevel.WARN, 288 "impossible to fetch the attribute prefetchActivatedOnExtent: ", e); 289 } 290 } 291 } else if (TRANSACTIONAL_PERSISTENCE_MANAGER_BINDING.equals(s)) { 292 tpm = (TransactionalPersistenceManager) o; 293 } else if (TRANSACTION_BINDING.equals(s)) { 294 tx = (Transaction) o; 295 } else if (PNAME_CODER_BINDING.equals(s)) { 296 pnc = (PNameCoder) o; 297 } else if (JORM_FACTORY_BINDING.equals(s)) { 298 jf = (JormFactory) o; 299 } else if (COMPONENT_BINDING.equals(s)) { 300 try { 301 thisPM = (ProxyManager) ((Component) o).getFcInterface("proxy-manager"); 302 } catch (NoSuchInterfaceException e) { 303 304 } 305 } 306 } 307 308 public void unbindFc(String s) { 309 if (PROXY_MANAGER_FACTORY_BINDING.equals(s)) 310 pmf = null; 311 else if (TRANSACTIONAL_PERSISTENCE_MANAGER_BINDING.equals(s)) 312 tpm = null; 313 else if (TRANSACTION_BINDING.equals(s)) 314 tx = null; 315 else if (QUERY_MANAGER_BINDING.equals(s)) 316 queryManager = null; 317 else if (PNAME_CODER_BINDING.equals(s)) 318 pnc = null; 319 else if (JORM_FACTORY_BINDING.equals(s)) 320 jf = null; 321 } 322 323 326 public Object getNativeConnection() { 327 try { 328 if (tx.getOptimistic()) { 329 return new DSConnectionFilter( 330 tx.getConnectionHolder().getCHConnectionForRead(), 331 true); 332 } else { 333 return new DSConnectionFilter( 334 tx.getConnectionHolder().getCHConnectionForWrite(), 335 false); 336 } 337 } catch(PersistenceException e) { 338 throw new JDODataStoreException("Impossible to allocate a native connection:", e); 339 } 340 } 341 342 public void addInstanceLifecycleListener(InstanceLifecycleListener l, Class [] classes) { 345 } 347 public void removeInstanceLifecycleListener(InstanceLifecycleListener classes) { 348 } 350 public void flush() { 351 try { 352 tpm.flush(tx, (StateFilter) null); 353 } catch (PersistenceException e) { 354 throw new JDODataStoreException("Impossible to flush the working set"); 355 } 356 } 357 358 public JDOConnection getDataStoreConnection() { 359 return this; 360 } 361 362 public FetchPlan getFetchPlan() { 363 if(fetchPlan == null){ 364 fetchPlan = new SpeedoFetchPlan(); 365 } 366 return fetchPlan; 367 } 368 369 372 public java.lang.Class getObjectIdClass(Class cls) { 373 bindPMThread(); 374 if (cls == null) { 375 return null; 376 } 377 try { 378 return jf.getPBinder(cls).getNull().getClass(); 379 } catch (PException e) { 380 Exception ie = ExceptionHelper.getNested(e); 381 logger.log(BasicLevel.ERROR, 382 "Error during the fetching of the manager of the class " 383 + cls.getName(), ie); 384 throw new JDOException("", ie); 385 } 386 } 387 388 393 public boolean isClosed() { 394 bindPMThread(); 395 return nbUse == 0; 396 } 397 398 405 public void close() { 406 if (semaphore.on) { 407 semaphore.P(); 408 } 409 if (nbUse == 0) { 410 return; 411 } else if (nbUse > 1) { 412 nbUse--; 413 logger.log(BasicLevel.DEBUG, "Imbricated persistence Manager closed (" 414 + nbUse + ")"); 415 return; 416 } 417 bindPMThread(); 418 try { 419 tpm.close(tx); 420 } catch (PersistenceException e) { 421 throw new JDOFatalInternalException( 422 "Impossible to close the persistence manager", 423 ExceptionHelper.getNested(e)); 424 } finally { 425 nbUse--; 426 userObject = null; 427 connectionSpec = null; 429 currentThread = null; 430 try { 431 pmf.proxyManagerClosed(thisPM); 432 } finally { 433 if (semaphore.on) { 434 semaphore.V(); 435 } 436 if (logger.isLoggable(BasicLevel.INFO)) 437 logger.log(BasicLevel.INFO, "Persistence Manager closed"); 438 } 439 } 440 } 441 442 447 public javax.jdo.Transaction currentTransaction() { 448 bindPMThread(); 449 return tx; 450 } 451 452 456 public void evict(Object o) { 457 if (o == null) 458 return; 459 assertIsOpen(); 460 bindPMThread(); 461 SpeedoProxy sp = (SpeedoProxy) o; 462 if (tx.isActive() && sp.jdoIsDirty()) 463 throw new JDOUserException("Impossible to evict a dirty " + 464 "instance attached to an active transaction"); 465 try { 466 tpm.evict(tx, sp.getCeIdentifier(), false); 467 } catch (PersistenceException e) { 468 throw new JDOUserException( 469 "Impossible to evict the persistent object from the cache", e); 470 } 471 } 472 473 478 public void evictAll(Object [] pcs) { 479 Throwable [] th = new Throwable [pcs.length]; 480 int lg = 0; 481 for (int i = 0; i < pcs.length; i++) { 482 try { 483 if (pcs[i] != null) { 484 evict(pcs[i]); 485 } 486 } catch (Throwable e) { 487 th[lg] = e; 488 lg++; 489 } 490 } 491 if (lg > 0) { 492 Throwable [] tfin = new Throwable [lg]; 493 System.arraycopy(th, 0, tfin, 0, lg); 494 throw new JDOUserException("Impossible to evict", tfin); 495 } 496 } 497 498 502 public void evictAll(Collection pcs) { 503 evictAll(pcs.toArray()); 504 } 505 506 512 public void evictAll() { 513 assertIsOpen(); 514 try { 515 tpm.evictAll(tx, false); 516 } catch (PersistenceException e) { 517 throw new JDOException("Error during the eviction of all cache entries: ", 518 ExceptionHelper.getNested(e)); 519 } 520 } 521 522 531 public void refresh(Object o) { 532 if (o == null) 533 return; 534 SpeedoProxy sp = (SpeedoProxy) o; 535 assertIsOpen(); 536 bindPMThread(); 537 assertIsSpeedoProxy(sp, "refresh"); 538 assertPersistenceManager(sp); 539 if (!sp.jdoIsPersistent()) 540 throw new JDOUserException("Refresh on a transient instance."); 541 speedoRefresh(sp, new HashMap (), new ArrayList ()); 542 } 543 544 public void speedoRefresh(SpeedoProxy sp, Map map, Collection fgHints){ 545 try { 546 if (map != null && !map.containsKey(sp.getPName())) { 547 map.put(sp.getPName(), sp); 548 tpm.refresh(tx, sp); 549 SpeedoAccessor sa = (SpeedoAccessor) tpm.readIntention(tx, sp, null); 550 sa.refresh(this, map, fgHints); 551 } 552 } catch (PersistenceException e) { 553 throw new JDOException("Impossible to refresh a persistent instance", e); 554 } 555 } 556 557 562 public void refreshAll(Object [] pcs) { 563 Throwable [] th = new Throwable [pcs.length]; 564 int lg = 0; 565 for (int i = 0; i < pcs.length; i++) { 566 try { 567 if (pcs[i] != null) { 568 refresh(pcs[i]); 569 } 570 } catch (Throwable e) { 571 th[lg] = e; 572 lg++; 573 } 574 } 575 if (lg > 0) { 576 Throwable [] tfin = new Throwable [lg]; 577 System.arraycopy(th, 0, tfin, 0, lg); 578 throw new JDOUserException("Impossible to refresh", tfin); 579 } 580 } 581 582 586 public void refreshAll(Collection pcs) { 587 refreshAll(pcs.toArray()); 588 } 589 590 596 public void refreshAll() { 597 assertIsOpen(); 598 if (!tx.isActive()) { 599 return; 600 } 601 Set entries = tx.entries(); 602 int size = entries.size(); 603 if (size == 0) { 604 return; 605 } 606 Object [] sps = new Object [size]; 607 Iterator it = entries.iterator(); 608 int i=0; 609 while(it.hasNext() && i<sps.length) { 610 State s = (State) it.next(); 611 sps[i] = s.getCacheEntry(); 612 i++; 613 } 614 refreshAll(sps); 615 } 616 617 public void refreshAll(JDOException arg0) { 618 refreshAll(); 620 } 621 622 623 627 public Query newQuery() { 628 assertIsOpen(); 629 bindPMThread(); 630 return createQuery(null); 631 } 632 633 public Query newQuery(String query) { 634 assertIsOpen(); 635 bindPMThread(); 636 return createQuery(null); 638 } 639 640 public Query newNamedQuery(Class klass, String name) { 641 try { 642 QueryDefinition qd = ((SpeedoHome) jf.getPClassMapping(klass)).getNamedQuery(name); 643 return createQuery(qd); 644 } catch (PException e) { 645 Exception ie = ExceptionHelper.getNested(e); 646 logger.log(BasicLevel.ERROR, 647 "Error during the fetching of the manager of the class " 648 + klass.getName(), ie); 649 throw new JDOException("Error during the fetching of the manager of the class ", ie); 650 } 651 } 652 653 663 public Query newQuery(Object compiled) { 664 assertIsOpen(); 665 bindPMThread(); 666 return createQuery(compiled); 667 } 668 669 675 public Query newQuery(String language, Object query) { 676 assertIsOpen(); 677 bindPMThread(); 678 if (language.compareTo("java.jdo.query.toVerify") == 0) { 679 return createQuery(query); 680 } else 681 throw new JDOUnsupportedOptionException("Language \"" + language 682 + "\"" + " is not supported by this jdo implementation"); 683 } 684 685 690 public Query newQuery(Class cls) { 691 assertIsOpen(); 692 bindPMThread(); 693 Query q = createQuery(null); 694 q.setClass(cls); 695 if (getObjectIdClass(cls) == null) 696 throw new JDOUnsupportedOptionException( 697 "There is a problem with the specified class"); 698 return q; 699 } 700 701 public Query newQuery(Extent extent) { 702 assertIsOpen(); 703 bindPMThread(); 704 Query q = createQuery(null); 705 Class c = extent.getCandidateClass(); 706 q.setClass(c); 707 if (getObjectIdClass(c) == null) 708 throw new JDOUnsupportedOptionException( 709 "There is a problem with the specified class"); 710 return q; 711 } 712 713 public Query newQuery(Extent extent, String filter) { 714 assertIsOpen(); 715 bindPMThread(); 716 Query q = newQuery(extent); 717 q.setFilter(filter); 718 return q; 719 } 720 721 728 public Query newQuery(Class cls, Collection cln) { 729 assertIsOpen(); 730 bindPMThread(); 731 Query q = createQuery(null); 732 q.setClass(cls); 733 q.setCandidates(cln); 734 return q; 735 } 736 737 743 public Query newQuery(Class cls, String filter) { 744 assertIsOpen(); 745 bindPMThread(); 746 Query q = createQuery(null); 747 q.setClass(cls); 748 q.setFilter(filter); 749 return q; 750 } 751 752 760 public Query newQuery(Class cls, Collection cln, String filter) { 761 assertIsOpen(); 762 bindPMThread(); 763 Query q = createQuery(null); 764 q.setClass(cls); 765 q.setCandidates(cln); 766 q.setFilter(filter); 767 return q; 768 } 769 770 780 public Extent getExtent(Class persistenceCapableClass, 781 boolean subclasses) { 782 assertIsOpen(); 783 bindPMThread(); 784 return new SpeedoExtent( 785 persistenceCapableClass, subclasses, this, jf, prefetchOnExtent, logger); 786 } 787 788 public Extent getExtent(Class arg0) { 789 return getExtent(arg0, true); 790 } 791 792 793 807 public Object getObjectById(Object oid, boolean validate) { 808 assertIsOpen(); 809 bindPMThread(); 810 return speedoGetObjectById(oid, validate); 811 } 812 813 public Object getObjectById(Class arg0, Object oid) { 814 assertIsOpen(); 815 bindPMThread(); 816 return speedoGetObjectById(oid, false); 817 } 818 819 public Object getObjectById(Object oid) { 820 assertIsOpen(); 821 bindPMThread(); 822 return speedoGetObjectById(oid, false); 823 } 824 825 public Collection getObjectsById(Collection arg0, boolean validate) { 826 if (arg0 == null) { 827 return Collections.EMPTY_LIST; 828 } 829 assertIsOpen(); 830 bindPMThread(); 831 ArrayList al = new ArrayList (arg0.size()); 832 for(Iterator it = arg0.iterator(); it.hasNext();) { 833 Object oid = it.next(); 834 if (oid == null) { 835 al.add(null); 836 continue; 837 } 838 try { 839 al.add(speedoGetObjectById(oid, validate)); 840 } catch (Exception e) { 841 al.add(null); 842 } 843 } 844 return al; 845 } 846 847 public Collection getObjectsById(Collection arg0) { 848 return getObjectsById(arg0, true); 849 } 850 851 public Object [] getObjectsById(Object [] arg0, boolean arg1) { 852 if (arg0 == null) { 853 return new Object [0]; 854 } 855 assertIsOpen(); 856 bindPMThread(); 857 Object [] objs = new Object [arg0.length]; 858 for(int i=0; i<arg0.length; i++) { 859 Object oid = arg0[i]; 860 if (oid == null) { 861 objs[i] = null; 862 continue; 863 } 864 try { 865 objs[i] = speedoGetObjectById(oid, arg1); 866 } catch (Exception e) { 867 objs[i] = null; 868 } 869 } 870 return objs; 871 } 872 873 public Object [] getObjectsById(Object [] arg0) { 874 return getObjectsById(arg0, true); 875 } 876 877 public Object speedoGetObjectById(Object oid, boolean validate) { 878 if (oid == null) 879 return null; 880 try { 881 PName pn = pnc.decodeAbstract(oid, tx.getConnectionHolder()); 882 if (pn.isNull()) { 883 return null; 884 } else { 885 if (validate) { 886 State s = tx.lookup(pn); 887 if (s != null && s != VirtualState.instance) { 888 return s.getCacheEntry(); 889 } else { 890 CacheEntry ce = tpm.getObjectById(tx, pn); 892 tpm.refresh(tx, ce); 894 tpm.readIntention(tx, ce, null); 896 return ce; 897 } 898 } else { 899 return tpm.readIntention(tx, pn, null).getCacheEntry(); 901 } 902 } 903 } catch (NoDSIPersistenceException e) { 904 throw new JDOUserException( 905 "No data store instance matching to the specified identifier: " 906 + oid, ExceptionHelper.getNested(e)); 907 } catch (RolledBackPersistenceException e) { 908 throw tx.rollBackOnInternalError(e); 909 } catch (Exception e) { 910 Exception ie = ExceptionHelper.getNested(e); 911 logger.log(BasicLevel.ERROR, 912 "Impossible to fetch a persistent object with the identifier: " + oid, ie); 913 throw new JDOException("", ie); 914 } 915 } 916 917 926 public Object getObjectId(Object pc) { 927 assertIsOpen(); 928 bindPMThread(); 929 try { 932 assertIsSpeedoProxy(pc, ""); 933 } catch (Exception e) { 934 return null; 935 } 936 SpeedoProxy sp = (SpeedoProxy) pc; 937 if (!sp.jdoIsPersistent()) 938 throw new JDOUserException("Object non persistent."); 939 assertPersistenceManager(sp); 940 try { 941 return pnc.encodeAbstract(sp.getPName()); 942 } catch (PException e) { 943 throw new JDOException( 944 "Problem while encoding persistent name.", 945 new Exception []{ExceptionHelper.getNested(e)}); 946 } 947 } 948 949 964 public Object getTransactionalObjectId(Object o) { 965 assertIsOpen(); 966 bindPMThread(); 967 throw new JDOUnsupportedOptionException("Not implemented."); 968 } 969 970 983 public void makePersistent(Object o) { 984 assertIsOpen(); 985 bindPMThread(); 986 assertIsSpeedoProxy(o, ""); 987 speedoMakePersistent((SpeedoProxy) o, false); 988 } 989 990 public void speedoMakePersistent(SpeedoProxy sp, boolean byAttach) { 991 if (sp.jdoIsPersistent()) 992 return; 993 if (!sp.jdoIsActive()) { 994 if (sp.getReferenceAccessor().getDetachedStatus() != DetachedLifeCycle.DETACHED_NONE) { 995 return; 996 } 997 } 998 synchronized(sp) { 999 if (sp.jdoIsPersistent()) 1000 return; 1001 SpeedoAccessor sa; 1002 try { 1003 PClassMapping pcm; 1005 if (sp instanceof SpeedoGenClassProxy) { 1006 pcm = jf.getGenClassMapping( 1007 ((SpeedoGenClassProxy) sp).jdoGetGenClassId()); 1008 ((SpeedoGenClassProxy) sp).jdoSetPBinding(pcm.createPBinding()); 1010 if (sp instanceof Loggable) { 1011 ((Loggable) sp).setLogger(logger); 1012 } 1013 } else { 1014 pcm = jf.getPClassMapping(sp.getClass()); 1015 } 1016 sp.init(pcm); 1017 Object hints = sp.jdoGetPNameHints(); 1018 if (hints == null) { 1019 sa = (SpeedoAccessor) tpm.export(tx, sp); 1020 } else { 1021 sa = (SpeedoAccessor) tpm.export(tx, sp, hints); 1022 } 1023 if (logger.isLoggable(BasicLevel.DEBUG)) { 1024 logger.log(BasicLevel.DEBUG, 1025 "New persistent instance, identifier=" + sp.getPName()); 1026 } 1027 } catch (Exception e) { 1028 try { 1029 sp.init(null); 1030 } catch (PException e1) { 1031 logger.log(BasicLevel.WARN, "Error during unbinding:", e1); 1032 } 1033 if (e instanceof RolledBackPersistenceException) { 1034 throw tx.rollBackOnInternalError(e); 1035 } else { 1036 throw new JDODataStoreException( 1037 "Problem while making persistent.", 1038 new Exception []{ExceptionHelper.getNested(e)}); 1039 } 1040 } 1041 sa.makePersistent(this); 1043 sp.getSpeedoHome().sendEvent(InstanceLifecycleEvent.CREATE, sp, null, false); 1044 } 1045 } 1046 1047 1052 public void makePersistentAll(Object [] pcs) { 1053 if (pcs == null || pcs.length == 0) 1054 return; 1055 assertIsOpen(); 1056 bindPMThread(); 1057 Exception [] th = new Exception [pcs.length]; 1058 int lg = 0; 1059 for (int i = 0; i < pcs.length; i++) { 1060 try { 1061 assertIsSpeedoProxy(pcs[i], ""); 1062 speedoMakePersistent((SpeedoProxy) pcs[i], false); 1063 } catch (Exception e) { 1064 th[lg] = e; 1065 lg++; 1066 } 1067 } 1068 if (lg > 0) { 1069 Exception [] tfin = new Exception [lg]; 1070 System.arraycopy(th, 0, tfin, 0, lg); 1071 throw new JDOUserException("Impossible to make persistent : ", tfin); 1072 } 1073 } 1074 1075 1079 public void makePersistentAll(Collection pcs) { 1080 if (pcs == null) 1081 return; 1082 makePersistentAll(pcs.toArray()); 1083 } 1084 1085 1097 public void deletePersistent(Object o) { 1098 assertIsOpen(); 1099 bindPMThread(); 1100 speedoDeletePersistent(o); 1101 } 1102 1103 public void speedoDeletePersistent(Object o) { 1104 assertIsSpeedoProxy(o, "deletePersistent"); 1105 SpeedoProxy sp = (SpeedoProxy) o; 1106 assertPersistenceManager(sp); 1108 if (!tx.isActive()) { 1110 throw new JDOUserException("DeletePersistent " + 1111 "must be called in an active transaction"); 1112 } 1113 SpeedoAccessor sa = null; 1114 try { 1115 if (!sp.jdoIsPersistent()) { 1116 throw new JDOUserException( 1117 "DeletePersistent on an instance non persistent."); 1118 } 1119 if (sp.jdoIsDeleted()) { 1120 return; 1121 } 1122 sp.getSpeedoHome().sendEvent(InstanceLifecycleEvent.DELETE, sp, null, true); 1123 sa = (SpeedoAccessor) tpm.unexport(tx, sp); 1124 sp.getSpeedoHome().sendEvent(InstanceLifecycleEvent.DELETE, sp, null, false); 1125 } catch (RolledBackPersistenceException e) { 1126 throw tx.rollBackOnInternalError(e); 1127 } catch (PersistenceException e) { 1128 throw new JDOException("", ExceptionHelper.getNested(e)); 1129 } 1130 sa.deletePersistent(this); 1132 if (logger.isLoggable(BasicLevel.DEBUG)) { 1133 logger.log(BasicLevel.DEBUG, 1134 "Delete a persistent instance, identifier=" + sp.getPName()); 1135 } 1136 } 1137 1138 1142 public void deletePersistentAll(Object [] pcs) { 1143 if (pcs == null) 1144 return; 1145 assertIsOpen(); 1146 bindPMThread(); 1147 Throwable [] th = new Throwable [pcs.length]; 1148 int lg = 0; 1149 for (int i = 0; i < pcs.length; i++) { 1150 try { 1151 speedoDeletePersistent(pcs[i]); 1152 } catch (Throwable e) { 1153 th[lg] = e; 1154 lg++; 1155 } 1156 } 1157 if (lg > 0) { 1158 Throwable [] tfin = new Throwable [lg]; 1159 System.arraycopy(th, 0, tfin, 0, lg); 1160 throw new JDOUserException 1161 ("Impossible to delete persistent : ", tfin); 1162 } 1163 } 1164 1165 1169 public void deletePersistentAll(Collection pcs) { 1170 if (pcs == null) 1171 return; 1172 deletePersistentAll(pcs.toArray()); 1173 } 1174 1175 1182 public void makeTransient(Object o) { 1183 assertIsOpen(); 1184 bindPMThread(); 1185 if (o == null || !(o instanceof SpeedoProxy) 1186 || !((SpeedoProxy) o).jdoIsPersistent()) { 1187 return; 1188 } 1189 SpeedoProxy sp = (SpeedoProxy) o; 1190 synchronized(sp) { 1191 if (sp.jdoIsDirty()) { 1192 throw new JDOUserException("Try to make transient a dirty instance."); 1193 } 1194 try { 1195 tpm.unbind(tx, sp); 1196 } catch (PersistenceException e) { 1197 throw new JDOUserException("Impossible to make transient the persistent instance: ", 1198 ExceptionHelper.getNested(e)); 1199 } 1200 } 1201 } 1202 1203 1208 public void makeTransientAll(Object [] pcs) { 1209 if (pcs == null) 1210 return; 1211 Throwable [] th = new Throwable [pcs.length]; 1212 int lg = 0; 1213 for (int i = 0; i < pcs.length; i++) { 1214 try { 1215 makeTransient(pcs[i]); 1216 } catch (Throwable e) { 1217 th[lg] = e; 1218 lg++; 1219 } 1220 } 1221 if (lg > 0) { 1222 Throwable [] tfin = new Throwable [lg]; 1223 System.arraycopy(th, 0, tfin, 0, lg); 1224 throw new JDOUserException("Impossible to make transient: ", tfin); 1225 } 1226 } 1227 1228 1235 public void makeTransientAll(Collection pcs) { 1236 if (pcs == null) 1237 return; 1238 makeTransientAll(pcs.toArray()); 1239 } 1240 1241 1245 public void makeTransactional(Object o) { 1246 throw new JDOUnsupportedOptionException("not yet implemented"); 1248 } 1249 1250 1254 public void makeTransactionalAll(Object [] pcs) { 1255 if (pcs == null || pcs.length == 0) 1256 return; 1257 Throwable [] th = new Throwable [pcs.length]; 1258 int lg = 0; 1259 for (int i = 0; i < pcs.length; i++) { 1260 try { 1261 makeTransactional(pcs[i]); 1262 } catch (Throwable e) { 1263 th[lg] = e; 1264 lg++; 1265 } 1266 } 1267 if (lg > 0) { 1268 Throwable [] tfin = new Throwable [lg]; 1269 System.arraycopy(th, 0, tfin, 0, lg); 1270 throw new JDOUserException 1271 ("Impossible to make transactional : ", tfin); 1272 } 1273 } 1274 1275 1279 public void makeTransactionalAll(Collection pcs) { 1280 if (pcs == null || pcs.size() == 0) 1281 return; 1282 makeTransactionalAll(pcs.toArray()); 1283 } 1284 1285 public void makeNontransactional(Object o) { 1286 SpeedoProxy sp = (SpeedoProxy) o; 1287 assertIsOpen(); 1289 bindPMThread(); 1290 assertIsSpeedoProxy(sp, ""); 1291 assertPersistenceManager(sp); 1292 if (sp.jdoIsDirty()) 1293 throw new JDOUserException("Try to make non-transactional a dirty instance."); 1294 sp.getSpeedoAccessor().jdoChangeStatus(LifeCycle.ACTION_MAKENONTRANSACTIONAL); 1295 } 1296 1297 public void makeNontransactionalAll(Object [] pcs) { 1298 if (pcs == null || pcs.length == 0) 1299 return; 1300 ArrayList th = new ArrayList (pcs.length); 1301 for (int i = 0; i < pcs.length; i++) { 1302 try { 1303 makeNontransactional(pcs[i]); 1304 } catch (Throwable e) { 1305 th.add(e); 1306 } 1307 } 1308 if (th.size() > 0) { 1309 throw new JDOUserException("Impossible to make non transactional : ", 1310 (Throwable []) th.toArray(new Throwable [0])); 1311 } 1312 } 1313 1314 public void makeNontransactionalAll(Collection pcs) { 1315 if (pcs == null || pcs.size() == 0) 1316 return; 1317 makeNontransactionalAll(pcs.toArray()); 1318 } 1319 1320 public void setUserObject(Object o) { 1321 bindPMThread(); 1322 userObject = o; 1323 } 1324 1325 1331 public Object getUserObject() { 1332 bindPMThread(); 1333 return userObject; 1334 } 1335 1336 public PersistenceManagerFactory getPersistenceManagerFactory() { 1337 return pmf; 1338 } 1339 1340 1341 1349 public void setMultithreaded(boolean flag) { 1350 semaphore.init(flag); 1351 } 1352 1353 1358 public boolean getMultithreaded() { 1359 return semaphore.on; 1360 } 1361 1362 1365 public void setIgnoreCache(boolean flag) { 1366 ignoreCache = flag; 1367 } 1368 1369 1373 public boolean getIgnoreCache() { 1374 return ignoreCache; 1375 } 1376 1377 public Object newObjectIdInstance(Class aClass, Object s) { 1378 assertIsOpen(); 1379 bindPMThread(); 1380 try { 1381 return pnc.decodeAbstract(s, aClass); 1382 } catch (PException e) { 1383 throw new JDOUserException("Invalid persistent object identifier " 1384 + s + " for the class " + aClass, new Exception []{e}); 1385 } 1386 } 1387 1388 public void retrieve(Object o) { 1389 assertIsOpen(); 1390 bindPMThread(); 1391 assertIsSpeedoProxy(o, "retrieve(Object)"); 1392 speedoRetrieve((SpeedoProxy) o, new HashMap (), new ArrayList ()); 1393 } 1394 1395 1396 public void speedoRetrieve(SpeedoProxy sp, Map map, Collection fgHints){ 1397 try { 1398 if (map != null && !map.containsKey(sp.getPName())) { 1399 map.put(sp.getPName(), sp); 1400 tpm.refresh(tx, sp); 1401 SpeedoAccessor sa = (SpeedoAccessor) tpm.readIntention(tx, sp, null); 1402 sa.retrieve(this, map, fgHints); 1403 } 1404 } catch (PersistenceException e) { 1405 throw new JDOException("Impossible to retrieve a persistent instance", e); 1406 } 1407 } 1408 1409 public void retrieveAll(Collection pcs) { 1410 assertIsOpen(); 1411 bindPMThread(); 1412 if (pcs == null) { 1413 return; 1414 } 1415 for(Iterator it = pcs.iterator(); it.hasNext();) { 1416 Object o = it.next(); 1417 assertIsSpeedoProxy(o, "retrieve(Collection)"); 1418 speedoRetrieve((SpeedoProxy) o, new HashMap (), new ArrayList ()); 1419 } 1420 } 1421 1422 public void retrieveAll(Object [] pcs) { 1423 assertIsOpen(); 1424 bindPMThread(); 1425 if (pcs == null) { 1426 return; 1427 } 1428 for(int i = 0; i<pcs.length; i++) { 1429 assertIsSpeedoProxy(pcs[i], "retrieve(Collection)"); 1430 if(((SpeedoProxy) pcs[i]).getReferenceAccessor() != null) 1431 speedoRetrieve((SpeedoProxy) pcs[i], new HashMap (), new ArrayList ()); 1432 } 1433 } 1434 1435 public void retrieveAll(Collection collection, boolean b) { 1436 retrieveAll(collection); 1437 } 1438 1439 public void retrieveAll(Object [] objects, boolean b) { 1440 retrieveAll(objects); 1441 } 1442 1443 1449 public Object detachCopy(Object o){ 1450 assertIsOpen(); 1451 assertIsSpeedoProxy(o, "detachCopy"); 1452 return speedoDetachCopy((SpeedoProxy)o, new HashMap (), new ArrayList ()); 1453 } 1454 1455 public Object speedoDetachCopy(SpeedoProxy sp, Map map, Collection fgHints){ 1456 if(sp.jdoIsPersistent()){ 1458 if(sp.jdoIsDeleted()){ 1459 if(!sp.jdoIsNew()) 1461 throw new JDOUserException("This object cannot be detached: it has been deleted from the datastore."); 1462 } 1463 } 1464 else{ 1465 speedoMakePersistent(sp, true); 1467 } 1468 if(!sp.getSpeedoHome().isDetachable()){ 1469 throw new JDOUserException("This class cannot be detached: it has not been defined as detachable in the jdo file."); 1470 } 1471 sp.getSpeedoHome().sendEvent(InstanceLifecycleEvent.DETACH, sp, null, true); 1472 if(sp.jdoIsTransactional() && sp.jdoIsDirty()){ 1474 try{ 1475 SpeedoAccessor sa = (SpeedoAccessor) tpm.writeIntention(tx, sp, null); 1476 if(!sa.hasBeenFlush()){ 1477 tpm.flush(tx, sa); 1479 } 1480 } catch (Exception e) { 1481 throw new JDODataStoreException( 1482 "Problem while flushing a persistent object in order to detach a copy.", 1483 new Exception []{ExceptionHelper.getNested(e)}); 1484 } 1485 } 1486 try{ 1489 synchronized(fgHints){ 1490 SpeedoProxy copy = sp.getSpeedoHome().detachCopy(sp, this, map, null, fgHints); 1491 if (sp.getSpeedoHome().getVersioningStrategy() == SpeedoVersion.VERSION_NUMBER) { 1492 copy.getReferenceAccessor().changeVersion(); 1493 } 1494 return copy; 1495 } 1496 } 1497 catch(Exception e){ 1498 throw new JDOUserException("Detach cannot be performed", new Exception []{ExceptionHelper.getNested(e)}); 1499 } finally { 1500 sp.getSpeedoHome().sendEvent(InstanceLifecycleEvent.DETACH, sp, null, false); 1501 } 1502 } 1503 1504 1510 public Collection detachCopyAll(Collection collection){ 1511 assertIsOpen(); 1512 if (collection == null) 1513 return null; 1514 makePersistentAll(collection); 1515 ArrayList copies = new ArrayList (); 1516 for (Iterator it = collection.iterator(); it.hasNext();){ 1517 copies.add(detachCopy(it.next())); 1518 } 1519 return copies; 1520 } 1521 1522 public Object [] detachCopyAll(Object [] objects){ 1523 assertIsOpen(); 1524 if(objects == null) 1525 return null; 1526 makePersistentAll(objects); 1527 Object [] copies = new Object [objects.length]; 1528 for (int i = 0; i < objects.length; i++){ 1529 copies[i] = detachCopy(objects[i]); 1530 } 1531 return copies; 1532 } 1533 1534 1540 public Object attachCopy(Object detached, boolean makeTransactional){ 1541 assertIsOpen(); 1542 assertIsSpeedoProxy(detached, "attachCopy"); 1543 return speedoAttachCopy(detached, makeTransactional, new HashMap ()); 1544 } 1545 1546 1553 public Object speedoAttachCopy(Object detached, boolean makeTransactional, Map map){ 1554 if (detached == null) 1555 return null; 1556 Object oid = ((SpeedoProxy)detached).getEncodedPName(); 1557 SpeedoProxy sp = null; 1558 try { 1559 if (oid == null) { 1560 makePersistent(detached); 1562 sp = (SpeedoProxy) detached; 1564 } else { 1565 sp = (SpeedoProxy) speedoGetObjectById(oid, false); 1566 } 1567 sp.getSpeedoHome().sendEvent(InstanceLifecycleEvent.ATTACH, sp, null, true); 1568 SpeedoAccessor sar = sp.getSpeedoHome().readIntention(sp, null); 1569 if (oid == null) { 1572 sar.forceDetachedDirty(); 1573 } 1574 sp.getSpeedoHome().attachCopy(sp, this, map, detached, sar, makeTransactional); 1576 if (oid == null) { 1579 sar.restoreDetachedNone(); 1580 } 1581 sar.changeVersion(); 1583 sp.getSpeedoHome().sendEvent(InstanceLifecycleEvent.ATTACH, sp, null, false); 1584 return sp; 1585 } catch (Exception e) { 1586 Exception ie = ExceptionHelper.getNested(e); 1587 String msg = "Impossible to attach a copy of the persistent object with the identifier: " + oid; 1588 logger.log(BasicLevel.INFO, msg, ie); 1589 throw (e instanceof JDOException 1590 ? (JDOException) e 1591 : new JDOException(msg, ie)); 1592 } 1593 } 1594 1595 public Collection attachCopyAll(Collection detached, boolean makeTransactional){ 1596 ArrayList attached = new ArrayList (); 1597 for (Iterator it = detached.iterator(); it.hasNext();){ 1598 attached.add(attachCopy(it.next(), makeTransactional)); 1599 } 1600 return attached; 1601 } 1602 1603 public Object [] attachCopyAll(Object [] detached, boolean makeTransactional){ 1604 Object [] attached = new Object [detached.length]; 1605 for (int i = 0; i < detached.length; i++){ 1606 attached[i] = attachCopy(detached[i], makeTransactional); 1607 } 1608 return attached; 1609 } 1610 1611 public Object getUserObject(Object arg0) { 1612 return userObjects.get(arg0); 1613 } 1614 public Object putUserObject(Object arg0, Object arg1) { 1615 return userObjects.put(arg0, arg1); 1616 } 1617 public Object removeUserObject(Object arg0) { 1618 return userObjects.remove(arg0); 1619 } 1620 1621 1622 public void checkConsistency() { 1623 flush(); 1624 } 1626 1627 public Sequence getSequence(String name) { 1628 Sequence s = pmf.getSequenceManager().getSequence(name); 1629 if (s == null) { 1630 throw new JDOUserException("The sequence " + name + " has not been found." 1631 + "Be sure that one class of the package the sequence belongs to has been loaded."); 1632 } 1633 return s; 1634 } 1635 1636 public Object newInstance(Class arg0) { 1637 if (arg0 == null) { 1638 return null; 1639 } 1640 if (arg0.isInterface()) { 1641 throw new JDOUserException( 1642 "Speedo does not support persistent interface currently: " 1643 + arg0.getName()); 1644 } else { 1645 try { 1646 return arg0.newInstance(); 1647 } catch (Exception e) { 1648 throw new JDOUserException( 1649 "Speedo does not support persistent abstract class currently: " 1650 + arg0.getName()); 1651 } 1652 } 1653 } 1654 1655 1656 1659 public TransactionalPersistenceManager getTransactionalPersistenceManager() { 1660 return tpm; 1661 } 1662 1663 public void open(Object connectionspec) { 1664 connectionSpec = connectionspec; 1665 nbUse = 0; 1666 tx.setOptimistic(pmf.getOptimistic()); 1667 setIgnoreCache(pmf.getIgnoreCache()); 1668 boolean multithreaded = pmf.getMultithreaded(); 1669 if (multithreaded != semaphore.on) 1670 semaphore.init(multithreaded); 1671 try { 1672 tx.active(); 1673 } catch (PersistenceException e) { 1674 throw new JDOFatalInternalException( 1675 "Impossible to open this persistence manager", e); 1676 } 1677 } 1678 1679 public Object getConnectionSpec() { 1680 return connectionSpec; 1681 } 1682 1683 public void addUse() { 1684 nbUse++; 1685 logger.log(BasicLevel.DEBUG, "ProxyManager used: " + nbUse); 1686 } 1687 1688 1689 1692 public void beforeCompletion() { 1693 byte stat = tx.getStatus(); 1694 if (stat == TransactionalWorkingSet.CTX_PREPARED_FAIL 1695 || stat == TransactionalWorkingSet.CTX_PREPARED_OK) { 1696 1701 return; 1702 } 1703 bindPMThread(); 1704 logger.log(BasicLevel.INFO, "beforeCompletion of the transaction: "); 1705 try { 1706 tpm.prepare(tx); 1707 } catch (PersistenceException e) { 1708 Exception ie = ExceptionHelper.getNested(e); 1709 logger.log(BasicLevel.ERROR, 1710 "Error during the preparation of the transaction:", ie); 1711 throw new JDOException("", ie); 1712 } 1713 } 1714 1715 public void afterCompletion(int i) { 1716 if (nbUse == 0) { 1717 1722 return; 1723 } 1724 bindPMThread(); 1725 boolean commit = (i == Status.STATUS_COMMITTED); 1726 try { 1727 if (commit) { 1728 logger.log(BasicLevel.DEBUG, "afterCompletion(STATUS_COMMITTED) of the transaction: "); 1729 tpm.commit(tx); 1730 } else { 1731 logger.log(BasicLevel.DEBUG, "afterCompletion(STATUS_ROLLEDBACK) of the transaction: "); 1732 tpm.rollback(tx); 1733 } 1734 } catch (PersistenceException e) { 1735 Exception ie = ExceptionHelper.getNested(e); 1736 logger.log(BasicLevel.ERROR, "Error during the " 1737 + (commit ? "commit" : "rollback") 1738 + " of the transaction:", ie); 1739 throw new JDOException("", ie); 1740 } finally { 1741 close(); 1742 } 1743 } 1744 1745 1746 1749 1750 1751 public Semaphore getSemaphore() { 1752 return semaphore; 1753 } 1754 1755 private void bindPMThread() { 1756 if (currentThread != Thread.currentThread()) { 1757 currentThread = Thread.currentThread(); 1758 pmf.bindPM2Thread(thisPM); 1759 currentThread = null; 1760 } 1761 } 1762 1763 1768 private void assertIsOpen() { 1769 if (nbUse == 0) 1770 throw new JDOFatalUserException("The persistent manager is closed."); 1771 } 1772 1773 1778 private void assertIsSpeedoProxy(Object pc, String cmd) { 1779 if (!(pc instanceof SpeedoProxy)) { 1780 if (pc == null) { 1781 throw new JDOUserException("Null persistent object instance specified"); 1782 } else if (pc.getClass().isArray() 1783 || pc instanceof Collection ) { 1784 throw new JDOUserException("You must use the " + cmd 1785 + "All method with a multivalued parameter: " + pc); 1786 } else { 1787 throw new JDOUserException("The object is not a Speedoproxy, beware to : " + pc); 1788 } 1789 } 1790 } 1791 1792 1798 private void assertPersistenceManager(SpeedoProxy sp) { 1799 ProxyManager pm = (ProxyManager) sp.jdoGetPersistenceManager(); 1800 if (!thisPM.equals(pm)) { 1801 if (pm == null) { 1802 try { 1803 tpm.readIntention(tx, sp, null); 1804 } catch (RolledBackPersistenceException e) { 1805 throw tx.rollBackOnInternalError(e); 1806 } catch (PersistenceException e) { 1807 throw new JDOUserException("Impossible to add the " + 1808 "persistent object into the working set", e); 1809 } 1810 } else { 1811 throw new JDOUserException( 1812 "Object not managed by this persistence manager, object: " 1813 + sp); 1814 } 1815 } 1816 } 1817} 1818 | Popular Tags |