001: package org.apache.ojb.jdo;
002:
003: /* Copyright 2003-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: import java.util.Collection;
019: import java.util.Iterator;
020:
021: import javax.jdo.Extent;
022: import javax.jdo.InstanceCallbacks;
023: import javax.jdo.JDOFatalUserException;
024: import javax.jdo.PersistenceManager;
025: import javax.jdo.PersistenceManagerFactory;
026: import javax.jdo.Query;
027: import javax.jdo.Transaction;
028:
029: import org.apache.ojb.broker.Identity;
030: import org.apache.ojb.broker.PBKey;
031: import org.apache.ojb.broker.PersistenceBrokerFactory;
032: import org.apache.ojb.broker.core.proxy.CollectionProxyDefaultImpl;
033: import org.apache.ojb.broker.core.proxy.ProxyHelper;
034: import org.apache.ojb.otm.EditingContext;
035: import org.apache.ojb.otm.OTMConnection;
036: import org.apache.ojb.otm.OTMKit;
037: import org.apache.ojb.otm.kit.SimpleKit;
038: import org.apache.ojb.otm.lock.LockType;
039: import org.apache.ojb.otm.lock.LockingException;
040: import org.apache.ojb.otm.states.State;
041:
042: /**
043: * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird</a>
044: * @author <a href="mailto:brianm@apache.org">Brian McCallister</a>
045: */
046: public class PersistenceManagerImpl implements PersistenceManager {
047: private OTMConnection m_conn;
048: private OTMKit m_kit;
049: private boolean m_multiThreaded = false;
050: private boolean m_ignoreCache = false;
051: private PersistenceManagerFactory m_factory;
052: private String m_userID;
053: private String m_password;
054: private String m_alias;
055: private Object m_usersObject;
056: private TransactionImpl m_tx;
057:
058: public PersistenceManagerImpl(PersistenceManagerFactory factory,
059: String alias, String userid, String password) {
060: m_factory = factory;
061: m_userID = userid;
062: m_password = password;
063: m_alias = alias;
064: m_kit = SimpleKit.getInstance();
065: /**
066: * if the alias is null, use the default.
067: */
068: if (null == m_alias) {
069: m_conn = m_kit.acquireConnection(PersistenceBrokerFactory
070: .getDefaultKey());
071: } else {
072: PBKey key = new PBKey(m_alias, m_userID, m_password);
073: m_conn = m_kit.acquireConnection(key);
074: }
075: m_tx = new TransactionImpl(this , m_kit, m_conn);
076: }
077:
078: OTMConnection getConnection() {
079: return this .m_conn;
080: }
081:
082: OTMKit getKit() {
083: return this .m_kit;
084: }
085:
086: public boolean isClosed() {
087: return m_conn.isClosed();
088: }
089:
090: /**
091: * Close database resources and
092: * Rollback transaction if there is one in progress
093: */
094: public void close() {
095: if (isClosed()) {
096: throw new JDOFatalUserException(
097: generateIsClosedErrorMessage("close()"));
098: }
099: if (m_tx.isActive())
100: m_tx.rollback();
101: m_conn.close();
102: }
103:
104: public Transaction currentTransaction() {
105: return m_tx;
106: }
107:
108: /**
109: * evict all persistent-clean instances from the editing context cache
110: *
111: * @param o
112: */
113: public void evict(Object o) {
114: if (isClosed()) {
115: throw new JDOFatalUserException(
116: generateIsClosedErrorMessage("evict(Object)"));
117: }
118: if (null != o) {
119: try {
120: Identity oid = m_conn.getIdentity(o);
121: State state = m_conn.getEditingContext().lookupState(
122: oid);
123: /**
124: * if the object is PersistentClean or non transactional, evict it.
125: */
126: if (State.PERSISTENT_CLEAN == state) {
127: /**
128: * spec says call the jdoPreClear if it's InstanceCallbacks aware
129: */
130: if (o instanceof InstanceCallbacks) {
131: ((InstanceCallbacks) o).jdoPreClear();
132: }
133: m_conn.invalidate(m_conn.getIdentity(o));
134: /**
135: * set all fields to their default values
136: */
137:
138: /**
139: * set state to hollow
140: */
141: }
142: if (null == state) {
143: /**
144: * not in the editing context, evict it from the global cache
145: */
146: m_conn.serviceObjectCache().remove(
147: m_conn.getIdentity(o));
148: }
149: } catch (LockingException e) {
150: /**
151: * shouldn't happen, we're only dealing with persistentClean and non transactional (aka non-locked)
152: * objects.
153: */
154: }
155: }
156: }
157:
158: public void evictAll(Object[] objects) {
159: if (isClosed()) {
160: throw new JDOFatalUserException(
161: generateIsClosedErrorMessage("evictAll(Object[])"));
162: }
163: if (null == objects) {
164: throw new NullPointerException(
165: "evictAll(Object[]) was passed a null Array.");
166: }
167: int length = objects.length;
168: for (int i = 0; i < length; i++) {
169: evict(objects[i]);
170: }
171: }
172:
173: public void evictAll(Collection collection) {
174: if (isClosed()) {
175: throw new JDOFatalUserException(
176: generateIsClosedErrorMessage("evictAll(Collection)"));
177: }
178: if (null == collection) {
179: throw new NullPointerException(
180: "evictAll(Collection) was passed a null Collection.");
181: }
182: Iterator it = collection.iterator();
183: while (it.hasNext()) {
184: evict(it.next());
185: }
186: }
187:
188: public void evictAll() {
189: if (isClosed()) {
190: throw new JDOFatalUserException(
191: generateIsClosedErrorMessage("evictAll()"));
192: }
193: EditingContext ctx = m_conn.getEditingContext();
194: if (ctx != null) {
195: for (Iterator i = ctx.getAllObjectsInContext().iterator(); i
196: .hasNext();) {
197: evict(i.next());
198: }
199: }
200: /**
201: * clear the rest of the global cache
202: */
203: m_conn.serviceObjectCache().clear();
204: }
205:
206: public void refresh(Object o) {
207: if (isClosed()) {
208: throw new JDOFatalUserException(
209: generateIsClosedErrorMessage("refresh(Object)"));
210: }
211: m_conn.refresh(o);
212: if (o instanceof InstanceCallbacks) {
213: ((InstanceCallbacks) o).jdoPostLoad();
214: }
215: }
216:
217: public void refreshAll(Object[] objects) {
218: if (isClosed()) {
219: throw new JDOFatalUserException(
220: generateIsClosedErrorMessage("refreshAll(Object[])"));
221: }
222: if (null == objects) {
223: throw new NullPointerException(
224: "refreshAll(Object[]) was passed a null Array.");
225: }
226: int length = objects.length;
227: for (int i = 0; i < length; i++) {
228: refresh(objects[i]);
229: }
230: }
231:
232: public void refreshAll(Collection collection) {
233: if (isClosed()) {
234: throw new JDOFatalUserException(
235: generateIsClosedErrorMessage("refreshAll(Collection)"));
236: }
237: if (null == collection) {
238: throw new NullPointerException(
239: "refreshAll(Collection) was passed a null Collection.");
240: }
241: Iterator it = collection.iterator();
242: while (it.hasNext()) {
243: refresh(it.next());
244: }
245: }
246:
247: public void refreshAll() {
248: if (isClosed()) {
249: throw new JDOFatalUserException(
250: generateIsClosedErrorMessage("refreshAll()"));
251: }
252: if (currentTransaction().isActive()) {
253: Collection collection = m_conn.getEditingContext()
254: .getAllObjectsInContext();
255: Iterator it = collection.iterator();
256: while (it.hasNext()) {
257: refresh(it.next());
258: }
259: }
260: }
261:
262: public Query newQuery() {
263: if (isClosed()) {
264: throw new JDOFatalUserException(
265: generateIsClosedErrorMessage("newQuery()"));
266: }
267:
268: return new QueryImpl(this );
269: }
270:
271: public Query newQuery(Object o) {
272: if (isClosed()) {
273: throw new JDOFatalUserException(
274: generateIsClosedErrorMessage("newQuery(Object)"));
275: }
276: try {
277: return ((QueryImpl) o).ojbClone();
278: } catch (ClassCastException e) {
279: throw new IllegalArgumentException(
280: "newQuery(Object) must be passed a Query instance");
281: }
282: }
283:
284: public Query newQuery(String s, Object o) {
285: if (isClosed()) {
286: throw new JDOFatalUserException(
287: generateIsClosedErrorMessage("newQuery(String, Object)"));
288: }
289:
290: throw new UnsupportedOperationException("Not yet implemented!");
291: }
292:
293: public Query newQuery(Class aClass) {
294: if (isClosed()) {
295: throw new JDOFatalUserException(
296: generateIsClosedErrorMessage("newQuery(Class)"));
297: }
298: Query query = new QueryImpl(this );
299: query.setClass(aClass);
300: return query;
301: }
302:
303: public Query newQuery(Extent extent) {
304: if (isClosed()) {
305: throw new JDOFatalUserException(
306: generateIsClosedErrorMessage("newQuery(Extent)"));
307: }
308:
309: Query query = new QueryImpl(this );
310: query.setCandidates(extent);
311: return query;
312: }
313:
314: public Query newQuery(Class aClass, Collection collection) {
315: if (isClosed()) {
316: throw new JDOFatalUserException(
317: generateIsClosedErrorMessage("newQuery(Class, Collection)"));
318: }
319: Query query = new QueryImpl(this );
320: query.setCandidates(collection);
321: query.setClass(aClass);
322: return query;
323: }
324:
325: public Query newQuery(Class aClass, String s) {
326: if (isClosed()) {
327: throw new JDOFatalUserException(
328: generateIsClosedErrorMessage("newQuery(Class, String)"));
329: }
330: Query query = new QueryImpl(this );
331: query.setClass(aClass);
332: query.setFilter(s);
333: return query;
334: }
335:
336: public Query newQuery(Class aClass, Collection collection, String s) {
337: if (isClosed()) {
338: throw new JDOFatalUserException(
339: generateIsClosedErrorMessage("newQuery(Class, Collection, String)"));
340: }
341: Query query = new QueryImpl(this );
342: query.setCandidates(collection);
343: query.setClass(aClass);
344: query.setFilter(s);
345: return query;
346: }
347:
348: public Query newQuery(Extent extent, String s) {
349: if (isClosed()) {
350: throw new JDOFatalUserException(
351: generateIsClosedErrorMessage("newQuery(Extent, String)"));
352: }
353: Query query = new QueryImpl(this );
354: query.setCandidates(extent);
355: query.setFilter(s);
356: return query;
357: }
358:
359: /**
360: * @param aClass top level class
361: * @param include_extent include subclasses, presently ignored
362: * @return
363: * @todo figure out how to implement, may have to query all and filter objects
364: */
365: public Extent getExtent(Class aClass, boolean include_extent) {
366: if (!include_extent)
367: throw new UnsupportedOperationException(
368: "Not yet implemented!");
369: if (isClosed()) {
370: throw new JDOFatalUserException(
371: generateIsClosedErrorMessage("getExtent(Class, boolean)"));
372: }
373: return new ExtentImpl(aClass, m_conn, this , include_extent);
374: }
375:
376: public Object getObjectById(Object o, boolean validate) {
377: if (isClosed()) {
378: throw new JDOFatalUserException(
379: generateIsClosedErrorMessage("getObjectById(Object, boolean)"));
380: }
381: Object retval = null;
382: try {
383: retval = m_conn.getObjectByIdentity((Identity) o);
384: } catch (LockingException e) {
385: e.printStackTrace(); //To change body of catch statement use Options | File Templates.
386: } catch (ClassCastException e) {
387: throw new IllegalArgumentException(
388: "Object passed as id is not an id: " + o);
389: }
390: return retval;
391: }
392:
393: /**
394: * @todo verify that Identity meets the requirements of the JDO spec
395: */
396: public Object getObjectId(Object o) {
397: if (isClosed()) {
398: throw new JDOFatalUserException(
399: generateIsClosedErrorMessage("getObjectId(Object)"));
400: }
401: return m_conn.getIdentity(o);
402: }
403:
404: public Object getTransactionalObjectId(Object o) {
405: if (isClosed()) {
406: throw new JDOFatalUserException(
407: generateIsClosedErrorMessage("getTransactionalObjectId(Object)"));
408: }
409: return m_conn.getIdentity(o);
410: }
411:
412: public Object newObjectIdInstance(Class aClass, String s) {
413: if (isClosed()) {
414: throw new JDOFatalUserException(
415: generateIsClosedErrorMessage("newObjectIdInstance(Class, String)"));
416: }
417: return null;
418: }
419:
420: public void makePersistent(Object o) {
421: if (isClosed()) {
422: throw new JDOFatalUserException(
423: generateIsClosedErrorMessage("makePersistent(Object)"));
424: }
425: try {
426: m_conn.makePersistent(o);
427: } catch (LockingException e) {
428: // throw runtime exception
429: }
430: }
431:
432: public void makePersistentAll(Object[] objects) {
433: if (isClosed()) {
434: throw new JDOFatalUserException(
435: generateIsClosedErrorMessage("makePersistentAll(Object[])"));
436: }
437: if (null == objects) {
438: throw new NullPointerException(
439: "makePersistentAll(Object[]) was passed a null Array.");
440: }
441: int length = objects.length;
442: for (int i = 0; i < length; i++) {
443: makePersistent(objects[i]);
444: }
445: }
446:
447: public void makePersistentAll(Collection collection) {
448: if (isClosed()) {
449: throw new JDOFatalUserException(
450: generateIsClosedErrorMessage("makePersistentAll(Collection)"));
451: }
452: if (null == collection) {
453: throw new NullPointerException(
454: "makePersistentAll(Collection) was passed a null Collection.");
455: }
456: Iterator it = collection.iterator();
457: while (it.hasNext()) {
458: makePersistent(it.next());
459: }
460: }
461:
462: public void deletePersistent(Object o) {
463: if (isClosed()) {
464: throw new JDOFatalUserException(
465: generateIsClosedErrorMessage("deletePersistent(Object)"));
466: }
467: try {
468: m_conn.deletePersistent(o);
469: } catch (LockingException e) {
470: handleLockingException(e);
471: }
472: }
473:
474: public void deletePersistentAll(Object[] objects) {
475: if (isClosed()) {
476: throw new JDOFatalUserException(
477: generateIsClosedErrorMessage("deletePersistentAll(Object[])"));
478: }
479: if (null == objects) {
480: throw new NullPointerException(
481: "deletePersistentAll(Object[]) was passed a null Array.");
482: }
483: int length = objects.length;
484: for (int i = 0; i < length; i++) {
485: deletePersistent(objects[i]);
486: }
487: }
488:
489: public void deletePersistentAll(Collection collection) {
490: if (isClosed()) {
491: throw new JDOFatalUserException(
492: generateIsClosedErrorMessage("deletePersistentAll(Collection)"));
493: }
494: if (null == collection) {
495: throw new NullPointerException(
496: "deletePersistentAll(Collection) was passed a null Collection.");
497: }
498: Iterator it = collection.iterator();
499: while (it.hasNext()) {
500: deletePersistent(it.next());
501: }
502: }
503:
504: /**
505: * Right now this makes the object non-transactional.
506: *
507: * @todo figure out what this is supposed to really do
508: */
509: public void makeTransient(Object o) {
510: if (isClosed()) {
511: throw new JDOFatalUserException(
512: generateIsClosedErrorMessage("makeTransient(Object)"));
513: }
514: m_conn.getEditingContext().remove(m_conn.getIdentity(o));
515: m_conn.serviceObjectCache().remove(m_conn.getIdentity(o));
516: }
517:
518: public void makeTransientAll(Object[] objects) {
519: if (isClosed()) {
520: throw new JDOFatalUserException(
521: generateIsClosedErrorMessage("makeTransientAll(Object[])"));
522: }
523: if (null == objects) {
524: throw new NullPointerException(
525: "makeTransientAll(Object[]) was passed a null Array.");
526: }
527: for (int i = 0; i < objects.length; i++) {
528: this .makeTransient(objects[i]);
529: }
530: }
531:
532: public void makeTransientAll(Collection collection) {
533: if (isClosed()) {
534: throw new JDOFatalUserException(
535: generateIsClosedErrorMessage("makeTransientAll(Collection)"));
536: }
537: if (null == collection) {
538: throw new NullPointerException(
539: "makeTransientAll(Collection) was passed a null Collection.");
540: }
541: for (Iterator iterator = collection.iterator(); iterator
542: .hasNext();) {
543: this .makeTransient(iterator.next());
544: }
545: }
546:
547: public void makeTransactional(Object o) {
548: if (isClosed()) {
549: throw new JDOFatalUserException(
550: generateIsClosedErrorMessage("makeTransactional(Object)"));
551: }
552: try {
553: m_conn.getEditingContext().insert(m_conn.getIdentity(o), o,
554: LockType.READ_LOCK);
555: } catch (LockingException e) {
556: handleLockingException(e);
557: }
558: }
559:
560: public void makeTransactionalAll(Object[] objects) {
561: if (isClosed()) {
562: throw new JDOFatalUserException(
563: generateIsClosedErrorMessage("makeTransactionalAll(Object[])"));
564: }
565: if (null == objects) {
566: throw new NullPointerException(
567: "makeTransactionalAll(Object[]) was passed a null Array.");
568: }
569: for (int i = 0; i < objects.length; i++) {
570: this .makeTransactional(objects[i]);
571: }
572: }
573:
574: public void makeTransactionalAll(Collection collection) {
575: if (isClosed()) {
576: throw new JDOFatalUserException(
577: generateIsClosedErrorMessage("makeTransactionalAll(Collection)"));
578: }
579: if (null == collection) {
580: throw new NullPointerException(
581: "makeTransactionalAll(Collection) was passed a null Collection.");
582: }
583: for (Iterator iterator = collection.iterator(); iterator
584: .hasNext();) {
585: this .makeTransactional(iterator.next());
586: }
587: }
588:
589: /**
590: * @todo What is the difference between this and makeTransient?
591: */
592: public void makeNontransactional(Object o) {
593: if (isClosed()) {
594: throw new JDOFatalUserException(
595: generateIsClosedErrorMessage("makeNontransactional(Object)"));
596: }
597: this .makeTransient(o);
598: }
599:
600: public void makeNontransactionalAll(Object[] objects) {
601: if (isClosed()) {
602: throw new JDOFatalUserException(
603: generateIsClosedErrorMessage("makeNontransactionalAll(Object[])"));
604: }
605: if (null == objects) {
606: throw new NullPointerException(
607: "makeNontransactionalAll(Object[]) was passed a null Array.");
608: }
609: for (int i = 0; i < objects.length; i++) {
610: this .makeNontransactional(objects[i]);
611: }
612: }
613:
614: public void makeNontransactionalAll(Collection collection) {
615: if (isClosed()) {
616: throw new JDOFatalUserException(
617: generateIsClosedErrorMessage("makeNontransactionalAll(Collection)"));
618: }
619: if (null == collection) {
620: throw new NullPointerException(
621: "makeNontransactionalAll(Collection) was passed a null Collection.");
622: }
623: for (Iterator iterator = collection.iterator(); iterator
624: .hasNext();) {
625: this .makeNontransactional(iterator.next());
626: }
627: }
628:
629: /**
630: * Force materialization of real object
631: * @param o
632: */
633: public void retrieve(Object o) {
634: if (isClosed()) {
635: throw new JDOFatalUserException(
636: generateIsClosedErrorMessage("retrieve(Object)"));
637: }
638: ProxyHelper.getRealObject(o);
639: }
640:
641: /**
642: * Force materialization of all items in collection
643: * @param collection
644: */
645: public void retrieveAll(Collection collection) {
646: if (isClosed()) {
647: throw new JDOFatalUserException(
648: generateIsClosedErrorMessage("retrieveAll(Collection)"));
649: }
650: if (null == collection) {
651: throw new NullPointerException(
652: "retrieveAll(Collection) was passed a null Collection.");
653: }
654:
655: /* @todo I consider this a hack as CPDI is configurable now! */
656: if (collection instanceof CollectionProxyDefaultImpl) {
657: CollectionProxyDefaultImpl cp = (CollectionProxyDefaultImpl) collection;
658: cp.getData();
659: }
660: }
661:
662: public void retrieveAll(Object[] objects) {
663: if (isClosed()) {
664: throw new JDOFatalUserException(
665: generateIsClosedErrorMessage("retrieveAll(Object[])"));
666: }
667: if (null == objects) {
668: throw new NullPointerException(
669: "retrieveAll(Object[]) was passed a null Array.");
670: }
671: // We don't proxy arrays
672: }
673:
674: public void setUserObject(Object o) {
675: if (isClosed()) {
676: throw new JDOFatalUserException(
677: generateIsClosedErrorMessage("setUserObject(Object)"));
678: }
679: m_usersObject = o;
680: }
681:
682: public Object getUserObject() {
683: if (isClosed()) {
684: throw new JDOFatalUserException(
685: generateIsClosedErrorMessage("getUserObject()"));
686: }
687: return m_usersObject;
688: }
689:
690: public PersistenceManagerFactory getPersistenceManagerFactory() {
691: if (isClosed()) {
692: throw new JDOFatalUserException(
693: generateIsClosedErrorMessage("getPersistenceManagerFactory()"));
694: }
695: return this .m_factory;
696: }
697:
698: /**
699: * @todo This will need to change when we have a JDO compliant Identity implementation
700: */
701: public Class getObjectIdClass(Class aClass) {
702: if (isClosed()) {
703: throw new JDOFatalUserException(
704: generateIsClosedErrorMessage("getObjectIdClass(Class)"));
705: }
706: return Identity.class;
707: }
708:
709: public void setMultithreaded(boolean b) {
710: if (isClosed()) {
711: throw new JDOFatalUserException(
712: generateIsClosedErrorMessage("setMultithreaded(boolean)"));
713: }
714: m_multiThreaded = b;
715: }
716:
717: public boolean getMultithreaded() {
718: if (isClosed()) {
719: throw new JDOFatalUserException(
720: generateIsClosedErrorMessage("getMultithreaded()"));
721: }
722: return m_multiThreaded;
723: }
724:
725: public void setIgnoreCache(boolean b) {
726: if (isClosed()) {
727: throw new JDOFatalUserException(
728: generateIsClosedErrorMessage("setIgnoreCache(boolean)"));
729: }
730: m_ignoreCache = b;
731: }
732:
733: public boolean getIgnoreCache() {
734: if (isClosed()) {
735: throw new JDOFatalUserException(
736: generateIsClosedErrorMessage("getIgnoreCache()"));
737: }
738: return m_ignoreCache;
739: }
740:
741: /**
742: * TODO i18n these messages
743: *
744: * @param methodSignature
745: * @return
746: */
747: private static final String generateIsClosedErrorMessage(
748: String methodSignature) {
749: return "PersistenceManager already closed, cannot call '"
750: + methodSignature
751: + "'. Obtain a new PersistenceBroker and retry.";
752: }
753:
754: private void handleLockingException(LockingException e) {
755: throw new UnsupportedOperationException("Not yet implemented!");
756: }
757:
758: /**
759: * TODO i18n these messages
760: *
761: * @param methodSignature
762: * @param type
763: * @return
764: */
765: private static final String generateNullParameterErrorMessage(
766: String methodSignature, String type) {
767: return methodSignature + " was passed a null " + type + ".";
768: }
769:
770: /**
771: * @todo what does this do?
772: * @see javax.jdo.PersistenceManager#retrieveAll(java.util.Collection, boolean)
773: */
774: public void retrieveAll(Collection arg0, boolean arg1) {
775: // TODO Auto-generated method stub
776:
777: }
778:
779: /**
780: * @todo what does this do?
781: * @see javax.jdo.PersistenceManager#retrieveAll(java.lang.Object[], boolean)
782: */
783: public void retrieveAll(Object[] arg0, boolean arg1) {
784: // TODO Auto-generated method stub
785: }
786: }
|