KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ojb > otm > core > BaseConnection


1 package org.apache.ojb.otm.core;
2
3 /* Copyright 2003-2005 The Apache Software Foundation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 import org.apache.ojb.broker.*;
19 import org.apache.ojb.broker.cache.ObjectCache;
20 import org.apache.ojb.broker.core.proxy.ProxyHelper;
21 import org.apache.ojb.broker.accesslayer.OJBIterator;
22 import org.apache.ojb.broker.metadata.ClassDescriptor;
23 import org.apache.ojb.broker.query.Query;
24 import org.apache.ojb.broker.query.ReportQuery;
25 import org.apache.ojb.broker.util.configuration.ConfigurationException;
26 import org.apache.ojb.broker.util.configuration.Configurator;
27 import org.apache.ojb.odmg.oql.EnhancedOQLQuery;
28 import org.apache.ojb.odmg.oql.OQLQueryImpl;
29 import org.apache.ojb.otm.EditingContext;
30 import org.apache.ojb.otm.OTMConnection;
31 import org.apache.ojb.otm.copy.ObjectCopyStrategy;
32 import org.apache.ojb.otm.lock.LockType;
33 import org.apache.ojb.otm.lock.LockingException;
34 import org.odmg.ODMGRuntimeException;
35 import org.odmg.OQLQuery;
36
37 import java.util.Collection JavaDoc;
38 import java.util.Iterator JavaDoc;
39 import java.util.ListIterator JavaDoc;
40 import java.util.ArrayList JavaDoc;
41
42 /**
43  *
44  * <javadoc>
45  *
46  * @author <a HREF="mailto:mattbaird@yahoo.com">Matthew Baird </a>
47  * @author <a HREF="mailto:rraghuram@hotmail.com">Raghu Rajah </a>
48  * @version $Id: BaseConnection.java,v 1.37.2.2 2005/12/21 22:30:18 tomdz Exp $
49  *
50  */

51 public abstract class BaseConnection implements OTMConnection
52 {
53
54     private PersistenceBroker _pb;
55     private Transaction _tx;
56     private ConcreteEditingContext _editingContext;
57     private Configurator m_configurator;
58
59     /**
60      * Constructor for BaseConnection.
61      *
62      */

63     public BaseConnection(PBKey pbKey)
64     {
65         _pb = PersistenceBrokerFactory.createPersistenceBroker(pbKey);
66         m_configurator = PersistenceBrokerFactory.getConfigurator();
67     }
68
69     public void close()
70     {
71         _pb.close();
72         _pb = null;
73     }
74
75     public boolean isClosed()
76     {
77         if (_pb == null)
78             return true;
79         else
80             return _pb.isClosed();
81     }
82
83     public PersistenceBroker getKernelBroker()
84     {
85         return _pb;
86     }
87
88     public void setTransaction(Transaction transaction)
89     {
90         if (transaction == null)
91         {
92             _editingContext = null;
93         }
94         else if (_tx != null)
95         {
96             throw new IllegalStateException JavaDoc("OTMConnection is already bound to the transacaction "
97                     + _tx);
98         }
99         else
100         {
101             _editingContext = new ConcreteEditingContext(transaction, _pb);
102         }
103         _tx = transaction;
104     }
105
106     public Transaction getTransaction()
107     {
108         return _tx;
109     }
110
111     //////////////////////////////////////
112
// OTMConnection protocol
113
//////////////////////////////////////
114

115     /**
116      * @see org.apache.ojb.otm.OTMConnection#getObjectByIdentity(Identity, int)
117      */

118     public Object JavaDoc getObjectByIdentity(Identity oid, int lock) throws LockingException
119     {
120         checkTransaction("getObjectByIdentity");
121         Object JavaDoc userObject;
122         Object JavaDoc cacheObject;
123
124         cacheObject = _pb.getObjectByIdentity(oid);
125         if (cacheObject == null)
126         {
127             // Possibly the object was inserted in this transaction
128
// and was not stored to database yet
129
userObject = _editingContext.lookup(oid);
130         }
131         else
132         {
133             userObject = getUserObject(oid, cacheObject);
134             // userObject from editing context may be proxy
135
userObject = ProxyHelper.getRealObject(userObject);
136             _editingContext.insert(oid, userObject, lock);
137         }
138         return userObject;
139     }
140
141     private void checkTransaction(String JavaDoc methodBeingCalled)
142     {
143         if (null == _tx)
144         {
145             throw new TransactionNotInProgressException(
146                     methodBeingCalled
147                             + " requires a valid transaction. Please make sure you have created a new transaction, and called begin() on it.");
148         }
149         if (!_tx.isInProgress())
150         {
151             throw new TransactionNotInProgressException(methodBeingCalled
152                     + " cannot be called before transaction begin() is called");
153         }
154     }
155
156     /**
157      * @see org.apache.ojb.otm.OTMConnection#getObjectByIdentity(Identity)
158      */

159     public Object JavaDoc getObjectByIdentity(Identity oid) throws LockingException
160     {
161         return getObjectByIdentity(oid, LockType.READ_LOCK);
162     }
163
164     /**
165      * @param query The query to execute
166      * @return an Iterator that iterates Objects. The returned objects are locked for read.
167      */

168     public Iterator getIteratorByQuery(Query query)
169     {
170         return getIteratorByQuery(query, LockType.READ_LOCK);
171     }
172
173     /**
174      * @param query The query to execute
175      * @param lock the lock that need to be acquired on the object Possible values are:
176      * LockType.NO_LOCK (aka read only) - changes to the object will not be written to
177      * database; LockType.READ_LOCK (aka optimistic lock) - changes to the object will
178      * be written to the database, in this case the lock will be automatically upgraded
179      * to the write lock on transaction commit; LockType.WRITE_LOCK (aka pessimistic
180      * lock) - changes to the object will be written to the database.
181      * @return an Iterator that iterates Objects of class c if calling the .next() method. The
182      * returned objects are locked with the given lock value.
183      */

184     public Iterator getIteratorByQuery(Query query, int lock)
185     {
186         checkTransaction("getIteratorByQuery");
187         return new OTMIterator((OJBIterator) _pb.getIteratorByQuery(query), lock, null);
188     }
189
190     /**
191      * @param query The OQL query to execute. Use this method if you don't want to load all the
192      * collection at once as OQLQuery.execute() does.
193      * @return an Iterator that iterates Objects. The returned objects are locked for read.
194      */

195     public Iterator getIteratorByOQLQuery(OQLQuery query)
196     {
197         return getIteratorByOQLQuery(query, LockType.READ_LOCK);
198     }
199
200     /**
201      * @param query The OQL query to execute. Use this method if you don't want to load all the
202      * collection at once as OQLQuery.execute() does.
203      * @return an Iterator that iterates Objects. The returned objects are locked for read.
204      */

205     public Iterator getIteratorByOQLQuery(OQLQuery query, int lock)
206     {
207         checkTransaction("getIteratorByOQLQuery");
208         if (query instanceof OTMOQLQueryImpl)
209         {
210             OTMOQLQueryImpl q = (OTMOQLQueryImpl) query;
211             return new OTMIterator((OJBIterator) _pb.getIteratorByQuery(q.getQuery()), lock, q);
212         }
213         else
214         {
215             throw new IllegalArgumentException JavaDoc("The OQLQuery where created not via OTM API");
216         }
217     }
218
219     /**
220      * @param query The query to execute
221      * @param lock the lock that need to be acquired on the object Possible values are:
222      * LockType.NO_LOCK (aka read only) - changes to the object will not be written to
223      * database; LockType.READ_LOCK (aka optimistic lock) - changes to the object will
224      * be written to the database, in this case the lock will be automatically upgraded
225      * to the write lock on transaction commit; LockType.WRITE_LOCK (aka pessimistic
226      * lock) - changes to the object will be written to the database.
227      * @return an Iterator that iterates Objects of class c if calling the .next() method. The
228      * returned objects are locked with the given lock value.
229      */

230     public Collection JavaDoc getCollectionByQuery(Query query, int lock)
231     {
232         checkTransaction("getCollectionByQuery");
233         Collection JavaDoc col = _pb.getCollectionByQuery(query);
234         Collection JavaDoc result = createCollectionOfTheSameClass(col);
235         for (Iterator it = col.iterator(); it.hasNext();)
236         {
237             result.add(insertObject(it.next(), lock));
238         }
239         return result;
240     }
241
242     /**
243      * @param query The query to execute
244      * @return an Iterator that iterates Objects of class c if calling the .next() method. The
245      * returned objects are locked for read.
246      */

247     public Collection JavaDoc getCollectionByQuery(Query query)
248     {
249         return getCollectionByQuery(query, LockType.READ_LOCK);
250     }
251
252     /**
253      * Get the identity of the object
254      *
255      * @param object The object
256      * @return the identity of the object
257      */

258     public Identity getIdentity(Object JavaDoc object)
259     {
260         return new Identity(object, _pb);
261     }
262
263     /**
264      * Get the class descriptor
265      *
266      * @param clazz The class
267      * @return the descriptor of the class
268      */

269     public ClassDescriptor getDescriptorFor(Class JavaDoc clazz)
270     {
271         return _pb.getClassDescriptor(clazz);
272     }
273
274     /**
275      * @see org.apache.ojb.otm.OTMConnection#invalidate(Identity)
276      */

277     public void invalidate(Identity oid) throws LockingException
278     {
279         if (null == _tx)
280         {
281             throw new TransactionNotInProgressException(
282                     "invalidate requires a valid transaction. Please make sure you have created a new transaction, and called begin() on it.");
283         }
284         // mark as invalidated in the editing context, if it's found there
285
_editingContext.insert(oid, null, LockType.READ_LOCK);
286
287         // remove from the cache
288
_pb.serviceObjectCache().remove(oid);
289
290     }
291
292     /**
293      * @see org.apache.ojb.otm.OTMConnection#serviceObjectCache()
294      */

295     public ObjectCache serviceObjectCache()
296     {
297         return _pb.serviceObjectCache();
298     }
299
300     /**
301      * TODO remove all from editing context.
302      *
303      * @throws LockingException
304      */

305     public void invalidateAll() throws LockingException
306     {
307         _pb.serviceObjectCache().clear();
308     }
309
310     /**
311      * @see org.apache.ojb.otm.OTMConnection#lockForWrite(Object)
312      */

313     public void lockForWrite(Object JavaDoc object) throws LockingException
314     {
315         checkTransaction("lockForWrite");
316         makePersistent(object);
317     }
318
319     /**
320      * @see org.apache.ojb.otm.OTMConnection#makePersistent(Object)
321      */

322     public void makePersistent(Object JavaDoc userObject) throws LockingException
323     {
324         checkTransaction("makePersistent");
325         Identity oid = new Identity(userObject, _pb);
326         Object JavaDoc cacheObject = _pb.getObjectByIdentity(oid);
327
328         if ((cacheObject != null) && (_editingContext.lookup(oid) == null))
329         {
330             // The object exists in the database, but is not yet in the editing
331
// context, so we need to put it to the editing context in its
332
// old state, then we will put the modified userObject.
333
// This will allow the editing context to find changes
334
ObjectCopyStrategy copyStrategy = _tx.getKit().getCopyStrategy(oid);
335             Object JavaDoc origUserObject = copyStrategy.copy(cacheObject, _pb);
336             _editingContext.insert(oid, origUserObject, LockType.WRITE_LOCK);
337         }
338         _editingContext.insert(oid, userObject, LockType.WRITE_LOCK);
339     }
340
341     /**
342      * @see org.apache.ojb.otm.OTMConnection#deletePersistent(Object)
343      */

344     public void deletePersistent(Object JavaDoc userObject) throws LockingException
345     {
346         checkTransaction("deletePersistent");
347         Identity oid = new Identity(userObject, _pb);
348         Object JavaDoc cacheObject = _pb.getObjectByIdentity(oid);
349         if (cacheObject == null)
350         {
351             // Possibly the object was inserted in this transaction
352
// and was not stored to database yet, so we simply remove it
353
// from editing context.
354
_editingContext.remove(oid);
355         }
356         else
357         {
358             if (_editingContext.lookup(oid) == null)
359             {
360                 // The object exists in the database, but is not yet in the editing
361
// context, so we need to put it to the editing context
362
ObjectCopyStrategy copyStrategy = _tx.getKit().getCopyStrategy(oid);
363                 Object JavaDoc origUserObject = copyStrategy.copy(cacheObject, _pb);
364                 _editingContext.insert(oid, origUserObject, LockType.WRITE_LOCK);
365             }
366             _editingContext.deletePersistent(oid, userObject);
367         }
368     }
369
370     /**
371      * @see org.apache.ojb.otm.OTMConnection#refresh(Object)
372      */

373     public void refresh(Object JavaDoc userObject)
374     {
375         checkTransaction("refresh");
376         Identity oid = new Identity(userObject, _pb);
377         _editingContext.refresh(oid, userObject);
378     }
379
380     public EditingContext getEditingContext()
381     {
382         return _editingContext;
383     }
384
385     public EnhancedOQLQuery newOQLQuery()
386     {
387         return newOQLQuery(LockType.READ_LOCK);
388     }
389
390     public EnhancedOQLQuery newOQLQuery(int lock)
391     {
392         checkTransaction("newOQLQuery");
393         OQLQueryImpl query = new OTMOQLQueryImpl(_pb.getPBKey(), lock);
394         try
395         {
396             m_configurator.configure(query);
397         }
398         catch (ConfigurationException e)
399         {
400             throw new ODMGRuntimeException("Error in configuration of OQLQueryImpl instance: "
401                     + e.getMessage());
402         }
403         return query;
404     }
405
406     public int getCount(Query query)
407     {
408         checkTransaction("getCount");
409         return _pb.getCount(query);
410     }
411
412     private Object JavaDoc insertObject(Object JavaDoc cacheObject, int lock)
413     {
414         Object JavaDoc ctxObject;
415         Identity oid;
416         Object JavaDoc userObject;
417
418
419         oid = getIdentity(cacheObject);
420         userObject = getUserObject(oid, cacheObject);
421         try
422         {
423             _editingContext.insert(oid, userObject, lock);
424         }
425         catch (LockingException ex)
426         {
427             throw new LockingPassthruException(ex);
428         }
429
430         return userObject;
431     }
432
433     /**
434      * Get user object (from the editing context) with the given oid.
435      * If not found, then create it as a copy of cacheObject.
436      * User object and cache object must be separate.
437      * @param oid The identity
438      * @param cacheObject the object for user
439      */

440     private Object JavaDoc getUserObject(Identity oid, Object JavaDoc cacheObject)
441     {
442         Object JavaDoc userObject = _editingContext.lookup(oid);
443
444         if (userObject == null)
445         {
446             ObjectCopyStrategy copyStrategy = _tx.getKit().getCopyStrategy(oid);
447             userObject = copyStrategy.copy(cacheObject, _pb);
448         }
449         return userObject;
450     }
451
452     private Collection JavaDoc createCollectionOfTheSameClass(Collection JavaDoc col)
453     {
454         try
455         {
456             return (Collection JavaDoc) col.getClass().newInstance();
457         }
458         catch (Throwable JavaDoc ex)
459         {
460             return new ArrayList JavaDoc();
461         }
462     }
463
464     ///////////////////////////////////////
465
// Transaction Notifications
466
///////////////////////////////////////
467

468     /**
469      *
470      * Notification issued by the driving transaction to begin this transaction
471      *
472      */

473     public abstract void transactionBegin() throws TransactionException;
474
475     /**
476      *
477      * Prepare for a commit. As part of a two phase commit protocol of the transaction.
478      *
479      */

480     public abstract void transactionPrepare() throws TransactionException;
481
482     /**
483      *
484      * Notification issued by the driving transaction to commit resources held by this connection.
485      *
486      */

487     public abstract void transactionCommit() throws TransactionException;
488
489     /**
490      *
491      * Notification issued by the driving transaction to rollback resources held by this
492      * connection.
493      *
494      */

495     public abstract void transactionRollback() throws TransactionException;
496
497     ///////////////////////////////////////
498
// Inner classes
499
///////////////////////////////////////
500

501     private class OTMIterator implements OJBIterator
502     {
503         private final OJBIterator _it;
504         private final int _lock;
505         private final OTMOQLQueryImpl _oqlQuery;
506
507         OTMIterator(OJBIterator it, int lock, OTMOQLQueryImpl oqlQuery)
508         {
509             _it = it;
510             _lock = lock;
511             _oqlQuery = oqlQuery;
512         }
513
514         public boolean hasNext()
515         {
516             boolean res = _it.hasNext();
517
518             // once the result set is finished, close it
519
if (!res)
520             {
521                 done();
522             }
523
524             return res;
525         }
526
527         public Object JavaDoc next()
528         {
529             Object JavaDoc object = _it.next();
530             object = insertObject(object, _lock);
531             return object;
532         }
533
534         public void remove()
535         {
536             throw new UnsupportedOperationException JavaDoc();
537         }
538
539         public void done()
540         {
541             releaseDbResources();
542             if (_oqlQuery != null)
543             {
544                 _oqlQuery.resetBindIterator();
545             }
546         }
547
548         protected void finalize()
549         {
550             done();
551         }
552
553         /*
554          * (non-Javadoc)
555          *
556          * @see org.apache.ojb.broker.accesslayer.OJBIterator#absolute(int)
557          */

558         public boolean absolute(int row) throws PersistenceBrokerException
559         {
560             return _it.absolute(row);
561         }
562
563         /*
564          * (non-Javadoc)
565          *
566          * @see org.apache.ojb.broker.accesslayer.OJBIterator#fullSize()
567          */

568         public int fullSize() throws PersistenceBrokerException
569         {
570             return _it.fullSize();
571         }
572
573         /*
574          * (non-Javadoc)
575          *
576          * @see org.apache.ojb.broker.accesslayer.OJBIterator#relative(int)
577          */

578         public boolean relative(int row) throws PersistenceBrokerException
579         {
580             return _it.relative(row);
581         }
582
583         /*
584          * (non-Javadoc)
585          *
586          * @see org.apache.ojb.broker.accesslayer.OJBIterator#releaseDbResources()
587          */

588         public void releaseDbResources()
589         {
590             _it.releaseDbResources();
591         }
592
593         /*
594          * (non-Javadoc)
595          *
596          * @see org.apache.ojb.broker.accesslayer.OJBIterator#size()
597          */

598         public int size() throws PersistenceBrokerException
599         {
600             return _it.size();
601         }
602
603         /**
604          * @see org.apache.ojb.broker.accesslayer.OJBIterator#disableLifeCycleEvents()
605          */

606         public void disableLifeCycleEvents()
607         {
608             _it.disableLifeCycleEvents();
609         }
610     }
611
612     private class OTMOQLQueryImpl extends OQLQueryImpl
613     {
614         int _lock;
615
616         public OTMOQLQueryImpl(PBKey key, int lock)
617         {
618             super(key);
619             _lock = lock;
620         }
621
622         /**
623          * Execute the query. After executing a query, the parameter list is reset.
624          *
625          * @return The object that represents the result of the query. The returned data, whatever
626          * its OQL type, is encapsulated into an object. For instance, when OQL returns an
627          * integer, the result is put into an <code>Integer</code> object. When OQL
628          * returns a collection (literal or object), the result is always a Java collection
629          * object of the same kind (for instance, a <code>DList</code>).
630          * @exception org.odmg.QueryException An exception has occurred while executing the query.
631          */

632         public Object JavaDoc execute() throws org.odmg.QueryException
633         {
634             Collection JavaDoc result;
635             Iterator iter = null;
636             Query query = getQuery();
637
638             try
639             {
640                 if (!(query instanceof ReportQuery))
641                 {
642                     Collection JavaDoc res0 = _pb.getCollectionByQuery(query);
643                     result = createCollectionOfTheSameClass(res0);
644                     for (iter = res0.iterator(); iter.hasNext();)
645                     {
646                         result.add(insertObject(iter.next(), _lock));
647                     }
648                 }
649                 else
650                 {
651                     result = new ArrayList JavaDoc();
652                     iter = _pb.getReportQueryIteratorByQuery(query);
653                     while (iter.hasNext())
654                     {
655                         Object JavaDoc[] res = (Object JavaDoc[]) iter.next();
656
657                         if (res.length == 1)
658                         {
659                             if (res[0] != null) // skip null values
660
{
661                                 result.add(res[0]);
662                             }
663                         }
664                         else
665                         {
666                             // skip null tuples
667
for (int i = 0; i < res.length; i++)
668                             {
669                                 if (res[i] != null)
670                                 {
671                                     result.add(res);
672                                     break;
673                                 }
674                             }
675                         }
676                     }
677                 }
678                 resetBindIterator();
679             }
680             finally
681             {
682                 if ((iter != null) && (iter instanceof OJBIterator))
683                 {
684                     ((OJBIterator) iter).releaseDbResources();
685                 }
686             }
687             return result;
688         }
689
690         void resetBindIterator()
691         {
692             // reset iterator to start of list so we can reuse this query
693
ListIterator JavaDoc it = getBindIterator();
694             while (it.hasPrevious())
695             {
696                 it.previous();
697             }
698         }
699     }
700
701 }
702
Popular Tags