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.Ob