KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > speedo > pm > lib > SpeedoProxyManager


1 /**
2  * Speedo: an implementation of JDO compliant personality on top of JORM generic
3  * I/O sub-system.
4  * Copyright (C) 2001-2004 France Telecom R&D
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  *
21  *
22  * Contact: speedo@objectweb.org
23  *
24  * Authors: S.Chassande-Barrioz.
25  *
26  */

27
28 package org.objectweb.speedo.pm.lib;
29
30 import java.util.ArrayList JavaDoc;
31 import java.util.Collection JavaDoc;
32 import java.util.Collections JavaDoc;
33 import java.util.HashMap JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.Map JavaDoc;
36 import java.util.Set JavaDoc;
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 JavaDoc;
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 /**
100  * Is a fractal component exporting the ProxyManager interface. This
101  * implementation delegates most of the JDO methods (javax.jdo.PersistenceManager)
102  * to the underlying TransactionPersistenceManager, the perseus component
103  * managing the concurrency, the caching and the loading aspect.
104  * In order to represents a working set (transtional or not) this PM is linked
105  * forever to an org.objectweb.speedo.workingset.api.Transaction instance. The
106  * status of this Transaction instance changes when this PM is allocated
107  * or closed, or when transaction demarcations are done through the
108  * javax.jdo.Transaction interface.
109  * This implementation uses a QueryManager for allocating CompiledQuery
110  * instance. Concerning the javax.jdo.Query implementation, this PM uses
111  * org.objectweb.speedo.query.lib.SpeedoQuery which are created each time
112  * (No pooling mechanism).
113  * The last dependencies is the JormFactory and a P
114  *
115  *
116  * @see javax.jdo.PersistenceManager
117  * @see org.objectweb.perseus.persistence.api.TransactionalPersistenceManager
118  * @see org.objectweb.speedo.mapper.api.JormFactory
119  * @see org.objectweb.speedo.pm.api.ProxyManagerFactory
120  * @see org.objectweb.speedo.query.api.QueryManager
121  * @see org.objectweb.speedo.query.api.CompiledQuery
122  * @see org.objectweb.speedo.workingset.api.Transaction
123  *
124  * @author S.Chassande-Barrioz
125  */

126 public class SpeedoProxyManager
127         implements PersistenceManager,
128         ProxyManager,
129         BindingController{
130
131     public final static String JavaDoc PROXY_MANAGER_FACTORY_BINDING = "proxy-manager-factory";
132     public final static String JavaDoc TRANSACTIONAL_PERSISTENCE_MANAGER_BINDING = "transactional-persistence-manager";
133     public final static String JavaDoc QUERY_MANAGER_BINDING = "query-manager";
134     public final static String JavaDoc TRANSACTION_BINDING = "transaction";
135     public final static String JavaDoc JORM_FACTORY_BINDING = "jorm-factory";
136     public final static String JavaDoc PNAME_CODER_BINDING = "pname-coder";
137     public final static String JavaDoc COMPONENT_BINDING = "component";
138     public final static String JavaDoc LOGGER_NAME
139             = SpeedoProperties.LOGGER_NAME + ".rt.SpeedoProxyManager";
140
141     private Logger logger;
142     private LoggerFactory loggerFactory;
143
144     /**
145      * The ProxyManagedFactory managing this ProxyManager
146      */

147     private ProxyManagerFactory pmf = null;
148
149     /**
150      * The manager of SpeedoQuery. It contains the optimized queries already
151      * used.
152      */

153     private QueryManager queryManager = null;
154
155     /**
156      * The transaction associated to this proxy manager.
157      */

158     private Transaction tx;
159
160     /**
161      * The TransactionalPersistenceManager (Perseus)
162      */

163     private TransactionalPersistenceManager tpm = null;
164
165     /**
166      * The JormFactory able to initialize the Persistent of classes
167      */

168     private JormFactory jf = null;
169
170     /**
171      * The PNameCoder able to encode/decode all PName
172      */

173     private PNameCoder pnc = null;
174
175     /**
176      * is the information permiting the access to the data store
177      */

178     private Object JavaDoc connectionSpec = null;
179
180     /**
181      * Indicates if number of proxy manager user. O means the ProxyManager
182      * is closed.
183      */

184     private short nbUse = 0;
185
186     /**
187      * The user object
188      */

189     private Object JavaDoc userObject = null;
190
191     /**
192      * indicates if the cache must be ignore on queries
193      */

194     boolean ignoreCache = true;
195
196     /**
197      * The fractal reference to this
198      */

199     private ProxyManager thisPM = null;
200
201     /**
202      * The lastest thread associated to the current ProxyManager
203      */

204     private Thread JavaDoc currentThread = null;
205
206     /**
207      * A semaphore object used to support the multithread mode
208      */

209     private Semaphore semaphore;
210
211     private boolean prefetchOnExtent = true;
212     private boolean prefetchOnQuery = true;
213
214     private FetchPlan fetchPlan;
215     
216     private HashMap JavaDoc userObjects = new HashMap JavaDoc();
217     
218     public SpeedoProxyManager() {
219         semaphore = new Semaphore(false);
220     }
221
222     public Query createQuery(Object JavaDoc o) {
223         SpeedoQuery sq = new SpeedoQuery();
224         sq.withPrefetch(prefetchOnQuery);
225         sq.setProxyManager(this);
226         //initialize the fetch plan of the speedo query
227
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     // IMPLEMENTATION OF THE UserBindingController INTERFACE //
239
//-------------------------------------------------------//
240

241     public String JavaDoc[] listFc() {
242         return new String JavaDoc[] {
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 JavaDoc lookupFc(String JavaDoc 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 JavaDoc s, Object JavaDoc 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 JavaDoc 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 JavaDoc 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     // IMPLEMENTATION OF THE JDOConnection INTERFACE //
324
//-----------------------------------------------//
325

326     public Object JavaDoc 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     // IMPLEMENTATION OF THE PersistentManager INTERFACE //
343
//---------------------------------------------------//
344
public void addInstanceLifecycleListener(InstanceLifecycleListener l, Class JavaDoc[] classes) {
345         // TODO: support lifeCycle listener (add)
346
}
347     public void removeInstanceLifecycleListener(InstanceLifecycleListener classes) {
348         // TODO: support lifeCycle listener (remove)
349
}
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     /**
370      * Fetches the Null PName associated to the PBinder of the persistent class
371      */

372     public java.lang.Class JavaDoc getObjectIdClass(Class JavaDoc 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 JavaDoc 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     /**
389      * A PersistenceManager instance can be used until it is closed.
390      * @return true if this PersistenceManager has been closed
391      * @see #close()
392      */

393     public boolean isClosed() {
394         bindPMThread();
395         return nbUse == 0;
396     }
397
398     /**
399      * This method closes the PersistenceManager.
400      * @exception javax.jdo.JDOUserException if the transaction associated to
401      * the persistence manager is active.
402      * @exception javax.jdo.JDOFatalDataStoreException if there is a problem while
403      * releasing the persistence manager.
404      */

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             //Forget the information to access to the data store.
428
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     /**
443      * Return the Transaction instance associated with a PersistenceManager.
444      * @return the Transaction associated with this
445      * PersistenceManager.
446      */

447     public javax.jdo.Transaction currentTransaction() {
448         bindPMThread();
449         return tx;
450     }
451
452     /**
453      * Mark an instance as no longer needed in the cache.
454      * @param o the instance to evict from the cache.
455      */

456     public void evict(Object JavaDoc 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     /** Mark an array of instances as no longer needed in the cache.
474      * @see #evict(java.lang.Object pc)
475      * @param pcs the array of instances to evict from the cache.
476      * @exception javax.jdo.JDOUserException if some instances cannot be removed.
477      */

478     public void evictAll(Object JavaDoc[] pcs) {
479         Throwable JavaDoc[] th = new Throwable JavaDoc[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 JavaDoc e) {
487                 th[lg] = e;
488                 lg++;
489             }
490         }
491         if (lg > 0) {
492             Throwable JavaDoc[] tfin = new Throwable JavaDoc[lg];
493             System.arraycopy(th, 0, tfin, 0, lg);
494             throw new JDOUserException("Impossible to evict", tfin);
495         }
496     }
497
498     /** Mark a Set of instances as no longer needed in the cache.
499      * @see #evict(java.lang.Object pc)
500      * @param pcs the Set of instance to evict from the cache.
501      */

502     public void evictAll(Collection JavaDoc pcs) {
503         evictAll(pcs.toArray());
504     }
505
506     /** Mark all persistent-nontransactional instances as no longer needed
507      * in the cache. It transitions all persistent-nontransactional instances to
508      * hollow. Transactional instances are subject to eviction based on the
509      * RetainValues setting.
510      * @see #evict(java.lang.Object pc)
511      */

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     /** Refresh the state of the instance from the data store.
523      * <P>In an optimistic transaction, the state of instances in the cache
524      * might not match the state in the data store. This method is used to
525      * reload the state of the instance from the data store so that a subsequent
526      * commit is more likely to succeed.
527      * <P>Outside a transaction, this method will refresh nontransactional
528      * state.
529      * @param o the instance to refresh.
530      */

531     public void refresh(Object JavaDoc 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 JavaDoc(), new ArrayList JavaDoc());
542     }
543
544     public void speedoRefresh(SpeedoProxy sp, Map JavaDoc map, Collection JavaDoc 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     /** Refresh the state of an array of instances from the data store.
558      * @see #refresh(java.lang.Object pc)
559      * @param pcs the array of instances to refresh.
560      * object.
561      */

562     public void refreshAll(Object JavaDoc[] pcs) {
563         Throwable JavaDoc[] th = new Throwable JavaDoc[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 JavaDoc e) {
571                 th[lg] = e;
572                 lg++;
573             }
574         }
575         if (lg > 0) {
576             Throwable JavaDoc[] tfin = new Throwable JavaDoc[lg];
577             System.arraycopy(th, 0, tfin, 0, lg);
578             throw new JDOUserException("Impossible to refresh", tfin);
579         }
580     }
581
582     /** Refresh the state of a Set of instances from the data store.
583      * @see #refresh(java.lang.Object pc)
584      * @param pcs the Set of instances to refresh.
585      */

586     public void refreshAll(Collection JavaDoc pcs) {
587         refreshAll(pcs.toArray());
588     }
589
590     /** Refresh the state of all applicable instances from the data store.
591      * <P>If called with an active transaction, all transactional instances
592      * will be refreshed. If called outside an active transaction, all
593      * nontransactional instances will be refreshed.
594      * @see #refresh(java.lang.Object pc)
595      */

596     public void refreshAll() {
597         assertIsOpen();
598         if (!tx.isActive()) {
599             return;
600         }
601         Set JavaDoc entries = tx.entries();
602         int size = entries.size();
603         if (size == 0) {
604             return;
605         }
606         Object JavaDoc[] sps = new Object JavaDoc[size];
607         Iterator JavaDoc 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         //TODO: review the refreshAll(JDOException) behavior
619
refreshAll();
620     }
621
622
623     /**
624      * Create a new Query with no elements.
625      * @return the new Query.
626      */

627     public Query newQuery() {
628         assertIsOpen();
629         bindPMThread();
630         return createQuery(null);
631     }
632
633     public Query newQuery(String JavaDoc query) {
634         assertIsOpen();
635         bindPMThread();
636         //TODO: Implements newQuery(String)
637
return createQuery(null);
638     }
639     
640     public Query newNamedQuery(Class JavaDoc klass, String JavaDoc name) {
641         try {
642             QueryDefinition qd = ((SpeedoHome) jf.getPClassMapping(klass)).getNamedQuery(name);
643             return createQuery(qd);
644         } catch (PException e) {
645             Exception JavaDoc 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     /**
654      * Create a new Query using elements from another Query.
655      * The other Query must have been created by the same JDO implementation.
656      * It might be active in a different PersistenceManager or might have been
657      * serialized and restored.
658      * <P>All of the settings of the other Query are copied to this Query,
659      * except for the candidate Set or Extent.
660      * @return the new Query
661      * @param compiled another Query from the same JDO implementation
662      */

663     public Query newQuery(Object JavaDoc compiled) {
664         assertIsOpen();
665         bindPMThread();
666         return createQuery(compiled);
667     }
668
669     /**
670      * Create a new Query using the specified language.
671      * @param language the language of the query parameter
672      * @param query the query, which is of a form determined by the language
673      * @return the new Query
674      */

675     public Query newQuery(String JavaDoc language, Object JavaDoc 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     /**
686      * Create a new Query specifying the Class of the candidate instances.
687      * @param cls the Class of the candidate instances
688      * @return the new Query
689      */

690     public Query newQuery(Class JavaDoc 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 JavaDoc 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 JavaDoc filter) {
714         assertIsOpen();
715         bindPMThread();
716         Query q = newQuery(extent);
717         q.setFilter(filter);
718         return q;
719     }
720
721     /**
722      * Create a new Query with the Class of the candidate instances and
723      * candidate Set.
724      * @param cls the Class of results
725      * @param cln the Set of candidate instances
726      * @return the new Query
727      */

728     public Query newQuery(Class JavaDoc cls, Collection JavaDoc cln) {
729         assertIsOpen();
730         bindPMThread();
731         Query q = createQuery(null);
732         q.setClass(cls);
733         q.setCandidates(cln);
734         return q;
735     }
736
737     /**
738      * Create a new Query with the Class of the candidate instances and filter.
739      * @param cls the Class of results
740      * @param filter the filter for candidate instances
741      * @return the new Query
742      */

743     public Query newQuery(Class JavaDoc cls, String JavaDoc filter) {
744         assertIsOpen();
745         bindPMThread();
746         Query q = createQuery(null);
747         q.setClass(cls);
748         q.setFilter(filter);
749         return q;
750     }
751
752     /**
753      * Create a new Query with the Class of the candidate instances,
754      * candidate Set, and filter.
755      * @param cls the Class of candidate instances
756      * @param cln the Set of candidate instances
757      * @param filter the filter for candidate instances
758      * @return the new Query
759      */

760     public Query newQuery(Class JavaDoc cls, Collection JavaDoc cln, String JavaDoc 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     /** Not implemented. The PersistenceManager manages a collection of
771      * instances in the data store based on the class of the instances. This
772      * method returns a Extent of instances in the data store that might be
773      * iterated or given to a Query. The Extent itself might not reference any
774      * instances, but only hold the class name and an
775      * indicator whether subclasses are included in the Extent.
776      * @param persistenceCapableClass Class of instances
777      * @param subclasses whether to include instances of subclasses
778      * @return an Extent of the specified Class
779      */

780     public Extent getExtent(Class JavaDoc 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 JavaDoc arg0) {
789         return getExtent(arg0, true);
790     }
791
792
793     /** This method locates a persistent instance in the cache of instances
794      * managed by this PersistenceManager. The getObjectById method attempts
795      * to find an instance in the cache with the specified JDO identity.
796      * The oid parameter object might have been returned by an earlier call
797      * to getObjectId or getTransactionalObjectId, or might have been
798      * constructed by the application.
799      * @see #getObjectId(java.lang.Object pc)
800      * @see #getTransactionalObjectId(java.lang.Object pc)
801      * @return the PersistenceCapable instance with the specified
802      * ObjectId
803      * @param oid an ObjectId
804      * @param validate if the existence of the instance is to be validated. The
805      * flag is ignored in this implementation.
806      */

807     public Object JavaDoc getObjectById(Object JavaDoc oid, boolean validate) {
808         assertIsOpen();
809         bindPMThread();
810         return speedoGetObjectById(oid, validate);
811     }
812
813     public Object JavaDoc getObjectById(Class JavaDoc arg0, Object JavaDoc oid) {
814         assertIsOpen();
815         bindPMThread();
816         return speedoGetObjectById(oid, false);
817     }
818     
819     public Object JavaDoc getObjectById(Object JavaDoc oid) {
820         assertIsOpen();
821         bindPMThread();
822         return speedoGetObjectById(oid, false);
823     }
824     
825     public Collection JavaDoc getObjectsById(Collection JavaDoc arg0, boolean validate) {
826         if (arg0 == null) {
827             return Collections.EMPTY_LIST;
828         }
829         assertIsOpen();
830         bindPMThread();
831         ArrayList JavaDoc al = new ArrayList JavaDoc(arg0.size());
832         for(Iterator JavaDoc it = arg0.iterator(); it.hasNext();) {
833             Object JavaDoc 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 JavaDoc e) {
841                 al.add(null);
842             }
843         }
844         return al;
845     }
846     
847     public Collection JavaDoc getObjectsById(Collection JavaDoc arg0) {
848         return getObjectsById(arg0, true);
849     }
850     
851     public Object JavaDoc[] getObjectsById(Object JavaDoc[] arg0, boolean arg1) {
852         if (arg0 == null) {
853             return new Object JavaDoc[0];
854         }
855         assertIsOpen();
856         bindPMThread();
857         Object JavaDoc[] objs = new Object JavaDoc[arg0.length];
858         for(int i=0; i<arg0.length; i++) {
859             Object JavaDoc 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 JavaDoc e) {
867                 objs[i] = null;
868             }
869         }
870         return objs;
871     }
872     
873     public Object JavaDoc[] getObjectsById(Object JavaDoc[] arg0) {
874         return getObjectsById(arg0, true);
875     }
876
877     public Object JavaDoc speedoGetObjectById(Object JavaDoc 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                         //Fetch an instance (new or from the cache)
891
CacheEntry ce = tpm.getObjectById(tx, pn);
892                         //clear the state
893
tpm.refresh(tx, ce);
894                         //if it exists then object loading else exception
895
tpm.readIntention(tx, ce, null);
896                         return ce;
897                     }
898                 } else {
899                     //do not load if present in the cache
900
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 JavaDoc e) {
910             Exception JavaDoc 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     /** The ObjectId returned by this method represents the JDO identity of
918      * the instance. The ObjectId is a copy (clone) of the internal state
919      * of the instance, and changing it does not affect the JDO identity of
920      * the instance.
921      * @see #getTransactionalObjectId(java.lang.Object pc)
922      * @see #getObjectById(java.lang.Object oid, boolean validate)
923      * @param pc the PersistenceCapable instance
924      * @return the ObjectId of the instance
925      */

926     public Object JavaDoc getObjectId(Object JavaDoc pc) {
927         assertIsOpen();
928         bindPMThread();
929         //the object must be persistence capable. otherwise, it doesn't have an
930
//objectid
931
try {
932             assertIsSpeedoProxy(pc, "");
933         } catch (Exception JavaDoc 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 JavaDoc[]{ExceptionHelper.getNested(e)});
946         }
947     }
948
949     /** Not implemented. The ObjectId returned by this method represents the JDO
950      * identity of the instance. The ObjectId is a copy (clone) of the internal
951      * state of the instance, and changing it does not affect the JDO identity
952      * of the instance.
953      * <P>If the object identity is being changed in the transaction, by the
954      * application modifying one or more of the application key fields,
955      * then this method returns the current identity in the transaction.
956      * <P>If there is no transaction in progress, or if none of the key fields
957      * is being modified, then this method will return the same value as
958      * getObjectId.
959      * @see #getObjectId(java.lang.Object pc)
960      * @see #getObjectById(java.lang.Object oid, boolean validate)
961      * @param o a PersistenceCapable instance
962      * @return the ObjectId of the instance
963      */

964     public Object JavaDoc getTransactionalObjectId(Object JavaDoc o) {
965         assertIsOpen();
966         bindPMThread();
967         throw new JDOUnsupportedOptionException("Not implemented.");
968     }
969
970     /** Make the transient instance persistent in this PersistenceManager.
971      * This method must be called in an active transaction.
972      * The PersistenceManager assigns an ObjectId to the instance and
973      * transitions it to persistent-new.
974      * The instance will be managed in the Extent associated with its Class.
975      * The instance will be put into the data store at commit.
976      * The closure of instances of PersistenceCapable classes
977      * reachable from persistent
978      * fields will be made persistent at commit. [This is known as
979      * persistence by reachability.]
980      * @param o a transient instance of a Class that implements
981      * PersistenceCapable
982      */

983     public void makePersistent(Object JavaDoc 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                //initialize the PBinding of the persistent object
1004
PClassMapping pcm;
1005                if (sp instanceof SpeedoGenClassProxy) {
1006                    pcm = jf.getGenClassMapping(
1007                        ((SpeedoGenClassProxy) sp).jdoGetGenClassId());
1008                    //Assign the PBinding
1009
((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 JavaDoc 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 JavaDoc 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 JavaDoc[]{ExceptionHelper.getNested(e)});
1039                }
1040            }
1041            //call the speedoProxy to make persistent the reference field
1042
sa.makePersistent(this);
1043            sp.getSpeedoHome().sendEvent(InstanceLifecycleEvent.CREATE, sp, null, false);
1044        }
1045    }
1046
1047    /** Make an array of instances persistent.
1048     * @param pcs an array of transient instances
1049     * @exception javax.jdo.JDOUserException if an object cannot be made persistent.
1050     * @see #makePersistent(java.lang.Object pc)
1051     */

1052    public void makePersistentAll(Object JavaDoc[] pcs) {
1053        if (pcs == null || pcs.length == 0)
1054            return;
1055        assertIsOpen();
1056        bindPMThread();
1057        Exception JavaDoc[] th = new Exception JavaDoc[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 JavaDoc e) {
1064                th[lg] = e;
1065                lg++;
1066            }
1067        }
1068        if (lg > 0) {
1069            Exception JavaDoc[] tfin = new Exception JavaDoc[lg];
1070            System.arraycopy(th, 0, tfin, 0, lg);
1071            throw new JDOUserException("Impossible to make persistent : ", tfin);
1072        }
1073    }
1074
1075    /** Make a Set of instances persistent.
1076     * @param pcs a Set of transient instances
1077     * @see #makePersistent(java.lang.Object pc)
1078     */

1079    public void makePersistentAll(Collection JavaDoc pcs) {
1080        if (pcs == null)
1081            return;
1082        makePersistentAll(pcs.toArray());
1083    }
1084
1085    /** Delete the persistent instance from the data store.
1086     * This method must be called in an active transaction.
1087     * The data store object will be removed at commit.
1088     * Unlike makePersistent, which makes the closure of the instance
1089     * persistent, the closure of the instance is not deleted from the data
1090     * store.
1091     * This method has no effect if the instance is already deleted in the
1092     * current transaction.
1093     * @exception javax.jdo.JDOUserException if the instance is transient or managed by
1094     * another PersistenceManager.
1095     * @param o a persistent instance
1096     */

1097    public void deletePersistent(Object JavaDoc o) {
1098        assertIsOpen();
1099        bindPMThread();
1100        speedoDeletePersistent(o);
1101    }
1102
1103    public void speedoDeletePersistent(Object JavaDoc o) {
1104        assertIsSpeedoProxy(o, "deletePersistent");
1105        SpeedoProxy sp = (SpeedoProxy) o;
1106        // Verify the instance is managed by this persistence manager
1107
assertPersistenceManager(sp);
1108        // Verify the transaction is active
1109
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        //remove the multivalued fields and cascade delete
1131
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    /** Delete an array of instances from the data store.
1139     * @param pcs a Set of persistent instances
1140     * @see #deletePersistent(java.lang.Object pc)
1141     */

1142    public void deletePersistentAll(Object JavaDoc[] pcs) {
1143        if (pcs == null)
1144            return;
1145        assertIsOpen();
1146        bindPMThread();
1147        Throwable JavaDoc[] th = new Throwable JavaDoc[pcs.length];
1148        int lg = 0;
1149        for (int i = 0; i < pcs.length; i++) {
1150            try {
1151                speedoDeletePersistent(pcs[i]);
1152            } catch (Throwable JavaDoc e) {
1153                th[lg] = e;
1154                lg++;
1155            }
1156        }
1157        if (lg > 0) {
1158            Throwable JavaDoc[] tfin = new Throwable JavaDoc[lg];
1159            System.arraycopy(th, 0, tfin, 0, lg);
1160            throw new JDOUserException
1161                    ("Impossible to delete persistent : ", tfin);
1162        }
1163    }
1164
1165    /** Delete a Set of instances from the data store.
1166     * @param pcs a Set of persistent instances
1167     * @see #deletePersistent(java.lang.Object pc)
1168     */

1169    public void deletePersistentAll(Collection JavaDoc pcs) {
1170        if (pcs == null)
1171            return;
1172        deletePersistentAll(pcs.toArray());
1173    }
1174
1175    /** Make an instance transient, removing it from management by this
1176     * PersistenceManager.
1177     * <P>The instance loses its JDO identity and it is no longer associated
1178     * with any PersistenceManager. The state of fields is preserved unchanged.
1179     * @param o the instance to make transient.
1180     * @exception javax.jdo.JDOUserException if the instance is dirty.
1181     */

1182    public void makeTransient(Object JavaDoc 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    /** Make an array of instances transient, removing them from management by
1204     * this PersistenceManager.
1205     * @see #makeTransient(java.lang.Object pc)
1206     * @param pcs the instances to make transient.
1207     */

1208    public void makeTransientAll(Object JavaDoc[] pcs) {
1209        if (pcs == null)
1210            return;
1211        Throwable JavaDoc[] th = new Throwable JavaDoc[pcs.length];
1212        int lg = 0;
1213        for (int i = 0; i < pcs.length; i++) {
1214            try {
1215                makeTransient(pcs[i]);
1216            } catch (Throwable JavaDoc e) {
1217                th[lg] = e;
1218                lg++;
1219            }
1220        }
1221        if (lg > 0) {
1222            Throwable JavaDoc[] tfin = new Throwable JavaDoc[lg];
1223            System.arraycopy(th, 0, tfin, 0, lg);
1224            throw new JDOUserException("Impossible to make transient: ", tfin);
1225        }
1226    }
1227
1228    /** Make a Set of instances transient, removing them from management
1229     * by this PersistenceManager.
1230     * <P>The instances lose their JDO identity and they are no longer
1231     * associated with any PersistenceManager. The state of fields is preserved
1232     * unchanged.
1233     * @param pcs the instances to make transient.
1234     */

1235    public void makeTransientAll(Collection JavaDoc pcs) {
1236        if (pcs == null)
1237            return;
1238        makeTransientAll(pcs.toArray());
1239    }
1240
1241    /** Make an instance subject to transactional boundaries.
1242     * @see javax.jdo.PersistenceManager#makeTransactional
1243     * @param o the instance to make transactional.
1244     */

1245    public void makeTransactional(Object JavaDoc o) {
1246//TODO: support the makeTransactional method
1247
throw new JDOUnsupportedOptionException("not yet implemented");
1248    }
1249
1250    /** Make an array of instances subject to transactional boundaries.
1251     * @param pcs the array of instances to make transactional.
1252     * @see #makeTransactional(java.lang.Object pc)
1253     */

1254    public void makeTransactionalAll(Object JavaDoc[] pcs) {
1255        if (pcs == null || pcs.length == 0)
1256            return;
1257        Throwable JavaDoc[] th = new Throwable JavaDoc[pcs.length];
1258        int lg = 0;
1259        for (int i = 0; i < pcs.length; i++) {
1260            try {
1261                makeTransactional(pcs[i]);
1262            } catch (Throwable JavaDoc e) {
1263                th[lg] = e;
1264                lg++;
1265            }
1266        }
1267        if (lg > 0) {
1268            Throwable JavaDoc[] tfin = new Throwable JavaDoc[lg];
1269            System.arraycopy(th, 0, tfin, 0, lg);
1270            throw new JDOUserException
1271                    ("Impossible to make transactional : ", tfin);
1272        }
1273    }
1274
1275    /** Make a Set of instances subject to transactional boundaries.
1276     * @param pcs the Set of instances to make transactional.
1277     * @see #makeTransactional(java.lang.Object pc)
1278     */

1279    public void makeTransactionalAll(Collection JavaDoc pcs) {
1280        if (pcs == null || pcs.size() == 0)
1281            return;
1282        makeTransactionalAll(pcs.toArray());
1283    }
1284
1285    public void makeNontransactional(Object JavaDoc o) {
1286        SpeedoProxy sp = (SpeedoProxy) o;
1287        //preconditions
1288
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 JavaDoc[] pcs) {
1298        if (pcs == null || pcs.length == 0)
1299            return;
1300        ArrayList JavaDoc th = new ArrayList JavaDoc(pcs.length);
1301        for (int i = 0; i < pcs.length; i++) {
1302            try {
1303                makeNontransactional(pcs[i]);
1304            } catch (Throwable JavaDoc e) {
1305                th.add(e);
1306            }
1307        }
1308        if (th.size() > 0) {
1309            throw new JDOUserException("Impossible to make non transactional : ",
1310                    (Throwable JavaDoc[]) th.toArray(new Throwable JavaDoc[0]));
1311        }
1312    }
1313
1314    public void makeNontransactionalAll(Collection JavaDoc pcs) {
1315        if (pcs == null || pcs.size() == 0)
1316            return;
1317        makeNontransactionalAll(pcs.toArray());
1318    }
1319
1320    public void setUserObject(Object JavaDoc o) {
1321        bindPMThread();
1322        userObject = o;
1323    }
1324
1325    /** The application can manage the PersistenceManager instances
1326     * more easily by having an application object associated with each
1327     * PersistenceManager instance.
1328     * @return the user object associated with this PersistenceManager
1329     * @see #setUserObject
1330     */

1331    public Object JavaDoc getUserObject() {
1332        bindPMThread();
1333        return userObject;
1334    }
1335
1336    public PersistenceManagerFactory getPersistenceManagerFactory() {
1337        return pmf;
1338    }
1339
1340
1341    /** Set the Multithreaded flag for this PersistenceManager. Applications
1342     * that use multiple threads to invoke methods or access fields from
1343     * instances managed by this PersistenceManager must set this flag to true.
1344     * Instances managed by this PersistenceManager include persistent or
1345     * transactional instances of PersistenceCapable classes, as well as
1346     * helper instances such as Query, Transaction, or Extent.
1347     * @param flag the Multithreaded setting.
1348     */

1349    public void setMultithreaded(boolean flag) {
1350        semaphore.init(flag);
1351    }
1352
1353    /** Get the current Multithreaded flag for this PersistenceManager.
1354     * This option is ignored by the implementation.
1355     * @see #setMultithreaded
1356     * @return the Multithreaded setting.
1357     */

1358    public boolean getMultithreaded() {
1359        return semaphore.on;
1360    }
1361
1362    /** Set the ignoreCache parameter for queries.
1363     * @param flag the ignoreCache setting.
1364     */

1365    public void setIgnoreCache(boolean flag) {
1366        ignoreCache = flag;
1367    }
1368
1369    /** Get the ignoreCache setting for queries.
1370     * @return the ignoreCache setting.
1371     * @see #setIgnoreCache
1372     */

1373    public boolean getIgnoreCache() {
1374        return ignoreCache;
1375    }
1376
1377    public Object JavaDoc newObjectIdInstance(Class JavaDoc aClass, Object JavaDoc 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 JavaDoc[]{e});
1385        }
1386    }
1387
1388    public void retrieve(Object JavaDoc o) {
1389        assertIsOpen();
1390        bindPMThread();
1391        assertIsSpeedoProxy(o, "retrieve(Object)");
1392        speedoRetrieve((SpeedoProxy) o, new HashMap JavaDoc(), new ArrayList JavaDoc());
1393    }
1394
1395    
1396    public void speedoRetrieve(SpeedoProxy sp, Map JavaDoc map, Collection JavaDoc 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 JavaDoc pcs) {
1410        assertIsOpen();
1411        bindPMThread();
1412        if (pcs == null) {
1413            return;
1414        }
1415        for(Iterator JavaDoc it = pcs.iterator(); it.hasNext();) {
1416            Object JavaDoc o = it.next();
1417            assertIsSpeedoProxy(o, "retrieve(Collection)");
1418            speedoRetrieve((SpeedoProxy) o, new HashMap JavaDoc(), new ArrayList JavaDoc());
1419        }
1420    }
1421
1422    public void retrieveAll(Object JavaDoc[] 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 JavaDoc(), new ArrayList JavaDoc());
1432        }
1433    }
1434
1435    public void retrieveAll(Collection JavaDoc collection, boolean b) {
1436        retrieveAll(collection);
1437    }
1438
1439    public void retrieveAll(Object JavaDoc[] objects, boolean b) {
1440        retrieveAll(objects);
1441    }
1442
1443    /**
1444     * Make a detached copy of the persitent object o and return it.
1445     * Only the fields belonging to the fetch group are reachable.
1446     * @param o
1447     * @return the detached copy of the persistent object
1448     */

1449    public Object JavaDoc detachCopy(Object JavaDoc o){
1450        assertIsOpen();
1451        assertIsSpeedoProxy(o, "detachCopy");
1452        return speedoDetachCopy((SpeedoProxy)o, new HashMap JavaDoc(), new ArrayList JavaDoc());
1453    }
1454    
1455    public Object JavaDoc speedoDetachCopy(SpeedoProxy sp, Map JavaDoc map, Collection JavaDoc fgHints){
1456        //check the meta info about the detachability of the class
1457
if(sp.jdoIsPersistent()){
1458            if(sp.jdoIsDeleted()){
1459                //persistent_deleted
1460
if(!sp.jdoIsNew())
1461                    throw new JDOUserException("This object cannot be detached: it has been deleted from the datastore.");
1462            }
1463        }
1464        else{
1465            //makePersistent
1466
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        //persistent_new or persistent_dirty: updated with object id and version
1473
if(sp.jdoIsTransactional() && sp.jdoIsDirty()){
1474            try{
1475                SpeedoAccessor sa = (SpeedoAccessor) tpm.writeIntention(tx, sp, null);
1476                if(!sa.hasBeenFlush()){
1477                    //flush
1478
tpm.flush(tx, sa);
1479                }
1480            } catch (Exception JavaDoc e) {
1481                throw new JDODataStoreException(
1482                "Problem while flushing a persistent object in order to detach a copy.",
1483                new Exception JavaDoc[]{ExceptionHelper.getNested(e)});
1484            }
1485        }
1486        //the core processing
1487
//avoid cycles using a map
1488
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 JavaDoc e){
1498            throw new JDOUserException("Detach cannot be performed", new Exception JavaDoc[]{ExceptionHelper.getNested(e)});
1499        } finally {
1500            sp.getSpeedoHome().sendEvent(InstanceLifecycleEvent.DETACH, sp, null, false);
1501        }
1502    }
1503    
1504    /**
1505     * Create a detached copy for each element of collection (assuming each element is persistent).
1506     * If there are duplicates in collection, the corresponding detached copy is used for each such duplicate.
1507     * @param collection
1508     * @return the collection of the detached copies in the same order than the parameter
1509     */

1510    public Collection JavaDoc detachCopyAll(Collection JavaDoc collection){
1511        assertIsOpen();
1512        if (collection == null)
1513            return null;
1514        makePersistentAll(collection);
1515        ArrayList JavaDoc copies = new ArrayList JavaDoc();
1516        for (Iterator JavaDoc it = collection.iterator(); it.hasNext();){
1517            copies.add(detachCopy(it.next()));
1518        }
1519        return copies;
1520    }
1521    
1522    public Object JavaDoc[] detachCopyAll(Object JavaDoc[] objects){
1523        assertIsOpen();
1524        if(objects == null)
1525            return null;
1526        makePersistentAll(objects);
1527        Object JavaDoc[] copies = new Object JavaDoc[objects.length];
1528        for (int i = 0; i < objects.length; i++){
1529            copies[i] = detachCopy(objects[i]);
1530        }
1531        return copies;
1532    }
1533    
1534    /**
1535     * Apply the changes contained in the detached object to the corresponding persistent instance in the cache.
1536     * @param detached
1537     * @param makeTransactional
1538     * @return the peristent object containg attached values
1539     */

1540    public Object JavaDoc attachCopy(Object JavaDoc detached, boolean makeTransactional){
1541       assertIsOpen();
1542        assertIsSpeedoProxy(detached, "attachCopy");
1543        return speedoAttachCopy(detached, makeTransactional, new HashMap JavaDoc());
1544    }
1545    
1546    /**
1547     * Apply the changes contained in the detached object to the corresponding persistent instance in the cache.
1548     * @param detached
1549     * @param makeTransactional
1550     * @param map is the attachement context
1551     * @return the peristent object containg attached values
1552     */

1553    public Object JavaDoc speedoAttachCopy(Object JavaDoc detached, boolean makeTransactional, Map JavaDoc map){
1554        if (detached == null)
1555            return null;
1556        Object JavaDoc oid = ((SpeedoProxy)detached).getEncodedPName();
1557        SpeedoProxy sp = null;
1558        try {
1559            if (oid == null) {
1560                //make the object persistent
1561
makePersistent(detached);
1562                //return detached;
1563
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 made persistent in this method
1570
// force the state to detached_dirty
1571
if (oid == null) {
1572                sar.forceDetachedDirty();
1573            }
1574            //call the attach method on the proxy
1575
sp.getSpeedoHome().attachCopy(sp, this, map, detached, sar, makeTransactional);
1576            // if made persistent in this method
1577
// restore the state to detached_none
1578
if (oid == null) {
1579                sar.restoreDetachedNone();
1580            }
1581            //change the version on attach
1582
sar.changeVersion();
1583            sp.getSpeedoHome().sendEvent(InstanceLifecycleEvent.ATTACH, sp, null, false);
1584            return sp;
1585        } catch (Exception JavaDoc e) {
1586            Exception JavaDoc ie = ExceptionHelper.getNested(e);
1587            String JavaDoc 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 JavaDoc attachCopyAll(Collection JavaDoc detached, boolean makeTransactional){
1596        ArrayList JavaDoc attached = new ArrayList JavaDoc();
1597        for (Iterator JavaDoc it = detached.iterator(); it.hasNext();){
1598            attached.add(attachCopy(it.next(), makeTransactional));
1599        }
1600        return attached;
1601    }
1602    
1603    public Object JavaDoc[] attachCopyAll(Object JavaDoc[] detached, boolean makeTransactional){
1604        Object JavaDoc[] attached = new Object JavaDoc[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 JavaDoc getUserObject(Object JavaDoc arg0) {
1612        return userObjects.get(arg0);
1613    }
1614    public Object JavaDoc putUserObject(Object JavaDoc arg0, Object JavaDoc arg1) {
1615        return userObjects.put(arg0, arg1);
1616    }
1617    public Object JavaDoc removeUserObject(Object JavaDoc arg0) {
1618        return userObjects.remove(arg0);
1619    }
1620    
1621    
1622    public void checkConsistency() {
1623        flush();
1624        // TODO: verify consistency of state in the WS
1625
}
1626    
1627    public Sequence getSequence(String JavaDoc 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 JavaDoc newInstance(Class JavaDoc 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 JavaDoc e) {
1648                throw new JDOUserException(
1649                    "Speedo does not support persistent abstract class currently: "
1650                        + arg0.getName());
1651            }
1652        }
1653    }
1654    
1655    
1656    // IMPLEMENTATION OF THE ProxyManager INTERFACE //
1657
//----------------------------------------------//
1658

1659    public TransactionalPersistenceManager getTransactionalPersistenceManager() {
1660        return tpm;
1661    }
1662
1663    public void open(Object JavaDoc 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 JavaDoc getConnectionSpec() {
1680        return connectionSpec;
1681    }
1682
1683    public void addUse() {
1684        nbUse++;
1685        logger.log(BasicLevel.DEBUG, "ProxyManager used: " + nbUse);
1686    }
1687
1688
1689    // IMPLEMENTATION OF THE Synchronization INTERFACE //
1690
//-------------------------------------------------//
1691

1692    public void beforeCompletion() {
1693        byte stat = tx.getStatus();
1694        if (stat == TransactionalWorkingSet.CTX_PREPARED_FAIL
1695            || stat == TransactionalWorkingSet.CTX_PREPARED_OK) {
1696            /**
1697             * The PersistenceManager has been registered several times as a
1698             * Synchronization and the beforeCompletion method is call several
1699             * times.
1700             */

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 JavaDoc 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            /**
1718             * The PersistenceManager has been registered several times as a
1719             * Synchronization and the afterCompletion method is call several
1720             * times.
1721             */

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 JavaDoc 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    // OTHER METHODS //
1747
//---------------//
1748

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    /**
1764     * Verify the persistence manager is open.
1765     * @exception javax.jdo.JDOFatalUserException if the persistence manager is
1766     * closed.
1767     */

1768    private void assertIsOpen() {
1769        if (nbUse == 0)
1770            throw new JDOFatalUserException("The persistent manager is closed.");
1771    }
1772
1773    /**
1774     * Verify that an instance is persistence capable.
1775     * @param pc the object to test.
1776     * @exception javax.jdo.JDOUserException if the object is not persistence capable.
1777     */

1778    private void assertIsSpeedoProxy(Object JavaDoc pc, String JavaDoc 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 JavaDoc) {
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    /**
1793     * Verify the instance is managed by this persistence manager.
1794     * @param sp a speedo proxy instance.
1795     * @exception javax.jdo.JDOUserException if the instance is managed by
1796     * another persistence manager.
1797     */

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