001: package org.apache.ojb.odmg;
002:
003: /* Copyright 2002-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 org.apache.commons.lang.SerializationUtils;
019: import org.apache.commons.lang.builder.ToStringBuilder;
020: import org.apache.commons.lang.builder.ToStringStyle;
021: import org.apache.ojb.broker.Identity;
022: import org.apache.ojb.broker.PBKey;
023: import org.apache.ojb.broker.PersistenceBroker;
024: import org.apache.ojb.broker.PersistenceBrokerFactory;
025: import org.apache.ojb.broker.util.collections.ManageableArrayList;
026: import org.apache.ojb.broker.util.configuration.Configuration;
027: import org.apache.ojb.broker.util.configuration.ConfigurationException;
028: import org.apache.ojb.broker.util.configuration.Configurator;
029: import org.apache.ojb.broker.util.factory.ConfigurableFactory;
030: import org.apache.ojb.broker.util.logging.Logger;
031: import org.apache.ojb.broker.util.logging.LoggerFactory;
032: import org.apache.ojb.odmg.locking.LockManager;
033: import org.apache.ojb.odmg.locking.LockManagerFactory;
034: import org.apache.ojb.odmg.oql.EnhancedOQLQuery;
035: import org.apache.ojb.odmg.oql.OQLQueryImpl;
036: import org.odmg.DArray;
037: import org.odmg.DBag;
038: import org.odmg.DList;
039: import org.odmg.DMap;
040: import org.odmg.DSet;
041: import org.odmg.Database;
042: import org.odmg.DatabaseClosedException;
043: import org.odmg.Implementation;
044: import org.odmg.ODMGRuntimeException;
045: import org.odmg.Transaction;
046:
047: /**
048: * Default implementation of the {@link Implementation} interface.
049: *
050: * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
051: * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird</a>
052: * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
053: *
054: * @version $Id: ImplementationImpl.java,v 1.1.2.12 2005/12/21 22:29:21 tomdz Exp $
055: */
056: public class ImplementationImpl implements ImplementationExt {
057: private Logger log = LoggerFactory
058: .getLogger(ImplementationImpl.class);
059:
060: // private List usedDatabases = new ArrayList();
061: private DatabaseImpl currentDatabase;
062: private Configurator configurator;
063: private OJBTxManager ojbTxManager;
064: private LockManager lockManager;
065:
066: private Class oqlCollectionClass;
067: private boolean impliciteWriteLocks;
068: private boolean implicitLocking;
069: private boolean implicitLockingBackward;
070: private boolean ordering;
071:
072: // private boolean noteUserOrder;
073:
074: /**
075: * private Constructor: use static factory method
076: * getInstance() to obtain an instance
077: */
078: protected ImplementationImpl() {
079: ojbTxManager = TxManagerFactory.instance();
080: lockManager = LockManagerFactory.getLockManager();
081: setConfigurator(PersistenceBrokerFactory.getConfigurator());
082: Configuration conf = getConfigurator()
083: .getConfigurationFor(null);
084: oqlCollectionClass = conf.getClass("OqlCollectionClass",
085: ManageableArrayList.class);
086: impliciteWriteLocks = (conf.getString("LockAssociations",
087: "WRITE").equalsIgnoreCase("WRITE"));
088: implicitLocking = conf.getBoolean("ImplicitLocking", true);
089: ordering = conf.getBoolean("Ordering", true);
090: // noteUserOrder = conf.getBoolean("NoteUserOrder", true);
091: implicitLockingBackward = conf.getBoolean(
092: "ImplicitLockingBackward", false);
093: if (log.isEnabledFor(Logger.INFO)) {
094: log.info("Settings: " + this .toString());
095: }
096: }
097:
098: public OJBTxManager getTxManager() {
099: return ojbTxManager;
100: }
101:
102: protected LockManager getLockManager() {
103: return lockManager;
104: }
105:
106: protected synchronized void setCurrentDatabase(DatabaseImpl curDB) {
107: currentDatabase = curDB;
108: }
109:
110: protected synchronized DatabaseImpl getCurrentDatabase() {
111: return currentDatabase;
112: }
113:
114: public PBKey getCurrentPBKey() {
115: return currentDatabase.getPBKey();
116: }
117:
118: /**
119: * Gets the configurator.
120: * @return Returns a Configurator
121: */
122: public Configurator getConfigurator() {
123: return configurator;
124: }
125:
126: /**
127: * Sets the configurator.
128: * @param configurator The configurator to set
129: */
130: public void setConfigurator(Configurator configurator) {
131: this .configurator = configurator;
132: }
133:
134: /**
135: * Create a <code>Transaction</code> object and associate it with the current thread.
136: * @return The newly created <code>Transaction</code> instance.
137: * @see Transaction
138: */
139: public Transaction newTransaction() {
140: if ((getCurrentDatabase() == null)) {
141: throw new DatabaseClosedException(
142: "Database is NULL, must have a DB in order to create a transaction");
143: }
144: TransactionImpl tx = new TransactionImpl(this );
145: try {
146: getConfigurator().configure(tx);
147: } catch (ConfigurationException e) {
148: throw new ODMGRuntimeException(
149: "Error in configuration of TransactionImpl instance: "
150: + e.getMessage());
151: }
152: return tx;
153: }
154:
155: /**
156: * Get the current <code>Transaction</code> for the thread.
157: * @return The current <code>Transaction</code> object or null if there is none.
158: * @see Transaction
159: */
160: public Transaction currentTransaction() {
161: if ((getCurrentDatabase() == null)) {
162: throw new DatabaseClosedException(
163: "Database is NULL, must have a DB in order to create a transaction");
164: }
165: return ojbTxManager.getTransaction();
166: }
167:
168: public boolean hasOpenTransaction() {
169: TransactionImpl tx = ojbTxManager.getTransaction();
170: return tx != null && tx.isOpen();
171: }
172:
173: /**
174: * Create a new <code>Database</code> object.
175: * @return The new <code>Database</code> object.
176: * @see Database
177: */
178: public Database newDatabase() {
179: return new DatabaseImpl(this );
180: }
181:
182: /**
183: * Create a new <code>OQLQuery</code> object.
184: * @return The new <code>OQLQuery</code> object.
185: * @see org.odmg.OQLQuery
186: */
187: public EnhancedOQLQuery newOQLQuery() {
188: if ((getCurrentDatabase() == null)
189: || !getCurrentDatabase().isOpen()) {
190: throw new DatabaseClosedException("Database is not open");
191: }
192: return new OQLQueryImpl(this );
193: }
194:
195: /**
196: * Create a new <code>DList</code> object.
197: * @return The new <code>DList</code> object.
198: * @see DList
199: */
200: public DList newDList() {
201: if ((getCurrentDatabase() == null)) {
202: throw new DatabaseClosedException(
203: "Database is NULL, cannot create a DList with a null database.");
204: }
205: return (DList) DListFactory.singleton
206: .createCollectionOrMap(getCurrentPBKey());
207: }
208:
209: /**
210: * Create a new <code>DBag</code> object.
211: * @return The new <code>DBag</code> object.
212: * @see DBag
213: */
214: public DBag newDBag() {
215: if ((getCurrentDatabase() == null)) {
216: throw new DatabaseClosedException(
217: "Database is NULL, cannot create a DBag with a null database.");
218: }
219: return (DBag) DBagFactory.singleton
220: .createCollectionOrMap(getCurrentPBKey());
221: }
222:
223: /**
224: * Create a new <code>DSet</code> object.
225: * @return The new <code>DSet</code> object.
226: * @see DSet
227: */
228: public DSet newDSet() {
229: if ((getCurrentDatabase() == null)) {
230: throw new DatabaseClosedException(
231: "Database is NULL, cannot create a DSet with a null database.");
232: }
233: return (DSet) DSetFactory.singleton
234: .createCollectionOrMap(getCurrentPBKey());
235: }
236:
237: /**
238: * Create a new <code>DArray</code> object.
239: * @return The new <code>DArray</code> object.
240: * @see DArray
241: */
242: public DArray newDArray() {
243: if ((getCurrentDatabase() == null)) {
244: throw new DatabaseClosedException(
245: "Database is NULL, cannot create a DArray with a null database.");
246: }
247: return (DArray) DArrayFactory.singleton
248: .createCollectionOrMap(getCurrentPBKey());
249: }
250:
251: /**
252: * Create a new <code>DMap</code> object.
253: * @return The new <code>DMap</code> object.
254: * @see DMap
255: */
256: public DMap newDMap() {
257: if ((getCurrentDatabase() == null)) {
258: throw new DatabaseClosedException(
259: "Database is NULL, cannot create a DMap with a null database.");
260: }
261: return (DMap) DMapFactory.singleton
262: .createCollectionOrMap(getCurrentPBKey());
263: }
264:
265: /**
266: * Get a <code>String</code> representation of the object's identifier.
267: * OJB returns the serialized Identity of the object.
268: * @param obj The object whose identifier is being accessed.
269: * @return The object's identifier in the form of a String
270: */
271: public String getObjectId(Object obj) {
272: Identity oid = null;
273: PersistenceBroker broker = null;
274:
275: try {
276: if (getCurrentDatabase() != null) {
277: /**
278: * is there an open database we are calling getObjectId against? if yes, use it
279: */
280: broker = PersistenceBrokerFactory
281: .createPersistenceBroker(getCurrentDatabase()
282: .getPBKey());
283: } else {
284: log
285: .warn("Can't find open database, try to use the default configuration");
286: /**
287: * otherwise, use default.
288: */
289: broker = PersistenceBrokerFactory
290: .defaultPersistenceBroker();
291: }
292:
293: oid = broker.serviceIdentity().buildIdentity(obj);
294: } finally {
295: if (broker != null) {
296: broker.close();
297: }
298: }
299: return new String(SerializationUtils.serialize(oid));
300: }
301:
302: /**
303: * Returns the current used database or null.
304: */
305: public Database getDatabase(Object obj) {
306: /* @todo enhance functionality */
307: return getCurrentDatabase();
308: }
309:
310: /**
311: * Register opened database via the PBKey.
312: */
313: protected synchronized void registerOpenDatabase(DatabaseImpl newDB) {
314: DatabaseImpl old_db = getCurrentDatabase();
315: if (old_db != null) {
316: try {
317: if (old_db.isOpen()) {
318: log
319: .warn("## There is still an opened database, close old one ##");
320: old_db.close();
321: }
322: } catch (Throwable t) {
323: //ignore
324: }
325: }
326: if (log.isDebugEnabled())
327: log.debug("Set current database " + newDB + " PBKey was "
328: + newDB.getPBKey());
329: setCurrentDatabase(newDB);
330: // usedDatabases.add(newDB.getPBKey());
331: }
332:
333: /**
334: * <strong>Note:</strong> Method behavior changed between version 1.0.3 and
335: * 1.0.4. Now this method is used to set the global property <em>implicit locking</em>,
336: * use method {@link TransactionExt#setImplicitLocking(boolean)} to set the property
337: * for a running transaction.
338: *
339: * @see ImplementationExt#setImplicitLocking(boolean)
340: */
341: public void setImplicitLocking(boolean value) {
342: if (implicitLockingBackward) {
343: ((TransactionExt) currentTransaction())
344: .setImplicitLocking(value);
345: } else {
346: this .implicitLocking = value;
347: }
348: }
349:
350: /**
351: * @see ImplementationExt#isImplicitLocking()
352: */
353: public boolean isImplicitLocking() {
354: return implicitLocking;
355: }
356:
357: /**
358: * @see ImplementationExt#getOqlCollectionClass()
359: */
360: public Class getOqlCollectionClass() {
361: return oqlCollectionClass;
362: }
363:
364: /**
365: * @see ImplementationExt#setOqlCollectionClass(Class)
366: */
367: public void setOqlCollectionClass(Class oqlCollectionClass) {
368: this .oqlCollectionClass = oqlCollectionClass;
369: }
370:
371: /**
372: * @see ImplementationExt#setImpliciteWriteLocks(boolean)
373: */
374: public void setImpliciteWriteLocks(boolean impliciteWriteLocks) {
375: this .impliciteWriteLocks = impliciteWriteLocks;
376: }
377:
378: /**
379: * @see ImplementationExt#isImpliciteWriteLocks()
380: */
381: public boolean isImpliciteWriteLocks() {
382: return impliciteWriteLocks;
383: }
384:
385: public boolean isOrdering() {
386: return ordering;
387: }
388:
389: public void setOrdering(boolean ordering) {
390: this .ordering = ordering;
391: }
392:
393: // public boolean isNoteUserOrder()
394: // {
395: // return noteUserOrder;
396: // }
397: //
398: // public void setNoteUserOrder(boolean noteUserOrder)
399: // {
400: // this.noteUserOrder = noteUserOrder;
401: // }
402:
403: /**
404: * Allow to use method {@link #setImplicitLocking(boolean)} in the same way
405: * as before version 1.0.4 - if set 'true', recommended setting is 'false'.
406: *
407: * @deprecated is only for backward compatibility with older versions (before 1.0.4)
408: * and will be removed in future versions.
409: */
410: public void setImplicitLockingBackward(
411: boolean implicitLockingBackward) {
412: this .implicitLockingBackward = implicitLockingBackward;
413: }
414:
415: public String toString() {
416: return new ToStringBuilder(this , ToStringStyle.MULTI_LINE_STYLE)
417: .append("implicitLocking", isImplicitLocking()).append(
418: "implicitWriteLocks", isImpliciteWriteLocks())
419: .append("ordering", isOrdering()).append(
420: "oqlCollectionClass", getOqlCollectionClass())
421: .append("txManager", getTxManager()).append(
422: "lockManager", getLockManager()).toString();
423: }
424:
425: //*****************************************************
426: // inner classes
427: //*****************************************************
428:
429: abstract static class BaseFactory extends ConfigurableFactory {
430: Object createCollectionOrMap() {
431: return this .createNewInstance();
432: }
433:
434: Object createCollectionOrMap(PBKey key) {
435: return createNewInstance(PBKey.class, key);
436: }
437: }
438:
439: static final class DListFactory extends BaseFactory {
440: static final BaseFactory singleton = new DListFactory();
441:
442: protected String getConfigurationKey() {
443: return "DListClass";
444: }
445: }
446:
447: static final class DArrayFactory extends BaseFactory {
448: static final BaseFactory singleton = new DArrayFactory();
449:
450: protected String getConfigurationKey() {
451: return "DArrayClass";
452: }
453: }
454:
455: static final class DBagFactory extends BaseFactory {
456: static final BaseFactory singleton = new DBagFactory();
457:
458: protected String getConfigurationKey() {
459: return "DBagClass";
460: }
461: }
462:
463: static final class DSetFactory extends BaseFactory {
464: static final BaseFactory singleton = new DSetFactory();
465:
466: protected String getConfigurationKey() {
467: return "DSetClass";
468: }
469: }
470:
471: static final class DMapFactory extends BaseFactory {
472: static final BaseFactory singleton = new DMapFactory();
473:
474: protected String getConfigurationKey() {
475: return "DMapClass";
476: }
477: }
478: }
|