/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS,
* <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) 1999-2006 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/
package org.olat.core.commons.persistence;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.jmx.StatisticsService;
import org.hibernate.stat.Statistics;
import org.hibernate.type.Type;
import org.olat.core.CoreSpringFactory;
import org.olat.core.extensions.ExtManager;
import org.olat.core.extensions.Extension;
import org.olat.core.extensions.hibernate.HibernateConfigurator;
import org.olat.core.helpers.Settings;
import org.olat.core.id.Persistable;
import org.olat.core.logging.AssertException;
import org.olat.core.logging.DBRuntimeException;
import org.olat.core.logging.LogDelegator;
import org.olat.core.logging.OLATRuntimeException;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.testutils.codepoints.server.Codepoint;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.jmx.support.MBeanServerFactoryBean;
/**
* A <b>DB </b> is a central place to get a Hibernate Session. It acts as a
* facade to the database, transactions and Queries. The hibernateSession is
* lazy loaded per thread.
*
* @author Andreas Ch. Kapp
* @author Christian Guretzki
*/
public class DBImpl extends LogDelegator implements DB {
private static final int MAX_DB_ACCESS_COUNT = 500;
private static DBImpl instance = new DBImpl();
private static SessionFactory sessionFactory = null;
private final ThreadLocal<ThreadLocalData> data = new ThreadLocal<ThreadLocalData>();
private Properties connectionProperties;
private OLog forcedLogger;
// true if this module has been loaded
private static boolean inactiv;
// Max value for commit-counter, values over this limit will be logged.
private static int maxCommitCounter = 10;
protected DBImpl() {
// private since singleton
inactiv = !DBModule.isActivated();
}
/**
* A <b>ThreadLocalData</b> is used as a central place to store data on a per
* thread basis.
*
* @author Andreas CH. Kapp
* @author Christian Guretzki
*/
private class ThreadLocalData {
private DBManager manager;
private boolean initialized = false;
// count number of db access in beginTransaction, used to log warn 'to many db access in one transaction'
private int accessCounter = 0;
// count number of commit in db-session, used to log warn 'Call more than one commit in a db-session'
private int commitCounter = 0;
// transaction listeners
private Set<ITransactionListener> transactionListeners_ = null;
private ThreadLocalData() {
// don't let any other class instantiate ThreadLocalData.
}
/**
* @return true if initialized.
*/
protected boolean isInitialized() {
return initialized;
}
protected DBManager getManager() {
return manager;
}
protected void setInitialized(boolean b) {
initialized = b;
}
protected void setManager(DBManager manager) {
this.manager = manager;
}
protected void incrementAccessCounter() {
this.accessCounter++;
}
protected int getAccessCounter() {
return this.accessCounter;
}
protected void resetAccessCounter() {
this.accessCounter = 0;
}
protected void incrementCommitCounter() {
this.commitCounter++;
}
protected int getCommitCounter() {
return this.commitCounter;
}
protected void resetCommitCounter() {
this.commitCounter = 0;
}
protected void addTransactionListener(ITransactionListener txListener) {
if (transactionListeners_==null) {
transactionListeners_ = new HashSet<ITransactionListener>();
}
transactionListeners_.add(txListener);
}
protected void removeTransactionListener(ITransactionListener txListener) {
if (transactionListeners_==null) {
// can't remove then - never mind
return;
}
transactionListeners_.remove(txListener);
}
protected void handleCommit(DB db) {
if (transactionListeners_==null) {
// nobody to be notified
return;
}
for (Iterator<ITransactionListener> it = transactionListeners_.iterator(); it.hasNext();) {
ITransactionListener listener = it.next();
try{
listener.handleCommit(db);
} catch(Exception e) {
logWarn("ITransactionListener threw exception in handleCommit:", e);
}
}
}
protected void handleRollback(DB db) {
if (transactionListeners_==null) {
// nobody to be notified
return;
}
for (Iterator<ITransactionListener> it = transactionListeners_.iterator(); it.hasNext();) {
ITransactionListener listener = it.next();
try{
listener.handleRollback(db);
} catch(Exception e) {
logWarn("ITransactionListener threw exception in hanldeRollback:", e);
}
}
}
}
private void setData(ThreadLocalData data) {
this.data.set(data);
}
private ThreadLocalData getData() {
ThreadLocalData tld = (ThreadLocalData) data.get();
if (tld == null) {
tld = new ThreadLocalData();
setData(tld);
}
return tld;
}
protected DBSession getDBSession() {
DBManager dbm = getData().getManager();
if (isLogDebugEnabled() && dbm == null) logDebug("DB manager ist null.", null);
return (dbm == null) ? null : dbm.getDbSession();
}
protected void setManager(DBManager manager) {
getData().setManager(manager);
}
DBManager getDBManager() {
return getData().getManager();
}
boolean isConnectionOpen() {
if ( (getData().getManager() == null)
|| (getData().getManager().getDbSession() == null) ) {
return false;
}
return getData().getManager().getDbSession().isOpen();
}
DBTransaction getTransaction() {
if ( (getData().getManager() == null)
|| (getData().getManager().getDbSession() == null) ) {
return null;
}
return getData().getManager().getDbSession().getTransaction();
}
private void createSession() {
if (isLogDebugEnabled()) logDebug("createSession start...", null);
Session session = null;
try {
DBSession dbs = getDBSession();
if (dbs == null) {
synchronized (this) { //o_clusterOK by:fj
/*
* to make sure, even though right now, db access is used in the
* single thread when starting up olat, and therefore the sync would
* not be necessary
*/
if (sessionFactory == null) {
Configuration cfg = DatabaseSetup.datastoreConfiguration();
// let all extensions add hibernate configuration, if needed
ExtManager extm = null;
try {
extm = ExtManager.getInstance();
} catch (Exception e) {
throw new OLATRuntimeException(this.getClass(), "Can not load extensions. Check xml files.", e);
}
Class extensionPoint = this.getClass();
int cnt = extm.getExtensionCnt();
for (int i = 0; i < cnt; i++) {
Extension anExt = extm.getExtension(i);
HibernateConfigurator hibconfigure = (HibernateConfigurator) anExt.getExtensionFor(extensionPoint.getName());
if (hibconfigure != null) {
hibconfigure.extend(cfg);
extm.inform(extensionPoint, anExt, "added hibernate configuration");
}
}
// set audit interceptor that traces lastChanged
cfg.setInterceptor(new AuditInterceptor());
cfg.setProperties(getConnectionProperties());
sessionFactory = cfg.buildSessionFactory();
registerStatisticsServiceAsMBean(sessionFactory);
try {
String lev = "n/a";
session = sessionFactory.openSession();
int iso = session.connection().getTransactionIsolation();
switch (iso) {
case Connection.TRANSACTION_READ_COMMITTED:
lev = "TRANSACTION_READ_COMMITTED";
break;
case Connection.TRANSACTION_READ_UNCOMMITTED:
lev = "TRANSACTION_READ_UNCOMMITTED";
break;
case Connection.TRANSACTION_REPEATABLE_READ:
lev = "TRANSACTION_REPEATABLE_READ";
break;
case Connection.TRANSACTION_SERIALIZABLE:
lev = "TRANSACTION_SERIALIZABLE";
break;
}
session.close();
logInfo("Transaction Level::::" + lev, null);
} catch (SQLException e) {
throw new DBRuntimeException("could not get TransactionIsolationLevel from db", e);
}
}
}
initializeSession();
// else we have an DBSession in the current thread, but check if
// session was closed
} else if (!dbs.isOpen()) {
initializeSession();
}
setInitialized(true);
} catch (HibernateException he) {
throw new OLATRuntimeException(DBImpl.class, "current session could not be obtained", he);
} finally {
if (isLogDebugEnabled()) logDebug("createSession finally...", null);
}
if (isLogDebugEnabled()) logDebug("createSession end...", null);
}
private void initializeSession() {
Codepoint.codepoint(DBImpl.class, "initializeSession");
if (isLogDebugEnabled()) logDebug("initializeSession", null);
Session session = sessionFactory.openSession();
setManager(new DBManager(session));
getData().resetAccessCounter();
getData().resetCommitCounter();
}
protected Properties getConnectionProperties() {
if (!threadLocalsInitialized()) {
if (Settings.isJUnitTest()) {
connectionProperties = DBModule.getDbProperties(DBModule.HIBERNATE_CONFIG_TESTDB);
} else {
connectionProperties = DBModule.getDbProperties(DBModule.HIBERNATE_CONFIG_PRODUCTIONDB);
}
}
return connectionProperties;
}
/**
* Close the database session.
*/
public void closeSession() {
getData().resetAccessCounter();
if (inactiv) return;
// Note: closeSession() now also checks if the connection is open at all
// in OLAT-4318 a situation is described where commit() fails and closeSession()
// is not called at all. that was due to a call to commit() with a session
// that was closed underneath by hibernate (not noticed by DBImpl).
// in order to be robust for any similar situation, we check if the
// connection is open, otherwise we shouldn't worry about doing any commit/rollback anyway
if (isConnectionOpen() && hasTransaction() && getTransaction().isInTransaction() && !getTransaction().isRolledBack()) {
if (Settings.isJUnitTest()) {
if (isLogDebugEnabled()) logDebug("Call commit", null);
getTransaction().commit();
getData().handleCommit(this);
} else {
if (isLogDebugEnabled()) logDebug("Call commit", null);
throw new AssertException("Close db-session with un-committed transaction");
}
}
DBSession s = getDBSession();
if (s != null) {
Codepoint.codepoint(DBImpl.class, "closeSession");
s.close();
// OLAT-3652 related: on closeSession also set the transaction to null
s.clearTransaction();
}
}
protected static DBImpl getInstance() {
return getInstance(true);
}
/**
* Get the DB instance. Initialisation is performed if flag is true.
*
* @param initialize
* @return the DB instance.
*/
protected static DBImpl getInstance(boolean initialize) {
// if module is not active we return a non-initialized instance and take
// care that
// the only cleanup-calls to db.closeSession do nothing
if (inactiv) return instance;
if (initialize) {
instance.createSession();
}
//OLAT-3621: paranoia check for error state: we need to catch errors at the earliest point possible. OLAT-3621 has a suspected situation
// where an earlier transaction failed and didn't clean up nicely. To check this, we introduce error checking in getInstance here
DBTransaction transaction = instance.getTransaction();
if (transaction!=null) {
// Filter Exception form async TaskExecutorThread, there are exception allowed
if (transaction.isError() && !Thread.currentThread().getName().equals("TaskExecutorThread")) {
instance.logWarn("Transaction (still?) in Error state: "+transaction.getError(), new Exception("DBImpl.getInstance("+initialize+")", transaction.getError()));
}
}
return instance;
}
/**
* Get db instance without checking transaction state
* @return
*/
protected static DBImpl getInstanceForClosing() {
return instance;
}
/**
* @return true if tread is initialized.
*/
boolean threadLocalsInitialized() {
return getData().isInitialized();
}
private void setInitialized(boolean initialized) {
getData().setInitialized(initialized);
}
boolean isInitialized() {
return getData().isInitialized();
}
/**
* Call this to begin a transaction .
* @param logObject TODO
*/
private void beginTransaction(Object logObject) {
// TODO: 07.01.2009/cg ONLY FOR DEBUGGING 'too many db access in one transaction'
// increment only non-cachable query
if (logObject instanceof String ) {
String query = (String) logObject;
query = query.trim();
if ( !query.startsWith("select count(poi) from org.olat.basesecurity.SecurityGroupMembershipImpl as sgmsi, org.olat.basesecurity.PolicyImpl as poi,")
&& !query.startsWith("select count(grp) from org.olat.group.BusinessGroupImpl as grp")
&& !query.startsWith("select count(sgmsi) from org.olat.basesecurity.SecurityGroupMembershipImpl as sgmsi") ) {
// it is no of cached queries
getData().incrementAccessCounter();
}
} else {
getData().incrementAccessCounter();
}
if (getData().getAccessCounter() > MAX_DB_ACCESS_COUNT) {
logWarn("beginTransaction bulk-change, too many db access for one transaction, could be a performance problem (add closeSession/createSession in loop) logObject=" + logObject, null);
getData().resetAccessCounter();
}
if(isLogDebugEnabled()) {
logDebug("beginTransaction TEST getDBSession()=" + getDBSession(), null);
}
if (!hasTransaction() ) {
// if no transaction exists, start a new one.
getDBSession().beginDbTransaction();
if(isLogDebugEnabled()) {
logDebug("No transaction exists, start a new one.", null);
}
} else if (getTransaction() != null && getTransaction().isRolledBack() ) {
logError("Call beginTransaction but transaction is already rollbacked",null);
}
if(isLogDebugEnabled()) {
logDebug("beginTransaction TEST hasTransaction()=" + hasTransaction(), null);
}
}
private boolean contains(Object object) {
return getDBManager().contains(object);
}
/**
* Create a DBQuery
*
* @param query
* @return DBQuery
*/
public DBQuery createQuery(String query) {
beginTransaction(query);
return getDBManager().createQuery(query);
}
/**
* Delete an object.
*
* @param object
*/
public void deleteObject(Object object) {
beginTransaction(object);
getDBManager().deleteObject(getTransaction(), object);
}
/**
* Deletion query.
*
* @param query
* @param value
* @param type
* @return nr of deleted rows
*/
public int delete(String query, Object value, Type type) {
beginTransaction(query);
return getDBManager().delete(getTransaction(), query, value, type);
}
/**
* Deletion query.
*
* @param query
* @param values
* @param types
* @return nr of deleted rows
*/
public int delete(String query, Object[] values, Type[] types) {
beginTransaction(query);
return getDBManager().delete(getTransaction(), query, values, types);
}
/**
* Find objects based on query
*
* @param query
* @param value
* @param type
* @return List of results.
*/
public List find(String query, Object value, Type type) {
beginTransaction(query);
return getDBManager().find(getTransaction(), query, value, type);
}
/**
* Find objects based on query
*
* @param query
* @param values
* @param types
* @return List of results.
*/
public List find(String query, Object[] values, Type[] types) {
beginTransaction(query);
return getDBManager().find(getTransaction(), query, values, types);
}
/**
* Find objects based on query
*
* @param query
* @return List of results.
*/
public List find(String query) {
beginTransaction(query);
return getDBManager().find(getTransaction(), query);
}
/**
* Find an object.
*
* @param theClass
* @param key
* @return Object, if any found. Null, if non exist.
*/
public Object findObject(Class theClass, Long key) {
beginTransaction(key);
return getDBManager().findObject(theClass, key);
}
/**
* Load an object.
*
* @param theClass
* @param key
* @return Object.
*/
public Object loadObject(Class theClass, Long key) {
beginTransaction(key);
return getDBManager().loadObject(getTransaction(), theClass, key);
}
/**
* Save an object.
*
* @param object
*/
public void saveObject(Object object) {
beginTransaction(object);
getDBManager().saveObject(getTransaction(), object);
}
/**
* Update an object.
*
* @param object
*/
public void updateObject(Object object) {
beginTransaction(object);
getDBManager().updateObject(getTransaction(), object);
}
/**
* Get any errors from a previous DB call.
*
* @return Exception, if any.
*/
public Exception getError() {
if (hasTransaction()) {
return getTransaction().getError();
} else {
return getDBManager().getLastError();
}
}
/**
* @return True if any errors occured in the previous DB call.
*/
public boolean isError() {
if (hasTransaction()) {
return getTransaction().isError();
} else {
return getDBManager()==null ? false : getDBManager().isError();
}
}
boolean hasTransaction() {
return null == getTransaction() ? false : getTransaction().isInTransaction();
}
/**
* @return a JDBC java.sql.Connection.
*/
protected Connection getConnection() {
return getData().getManager().getConnection();
}
/**
* see DB.loadObject(Persistable persistable, boolean forceReloadFromDB)
*
* @param persistable
* @return the loaded object
*/
public Persistable loadObject(Persistable persistable) {
return loadObject(persistable, false);
}
/**
* loads an object if needed. this makes sense if you have an object which had
* been generated in a previous hibernate session AND you need to access a Set
* or a attribute which was defined as a proxy.
*
* @param persistable the object which needs to be reloaded
* @param forceReloadFromDB if true, force a reload from the db (e.g. to catch
* up to an object commited by another thread which is still in this
* thread's session cache
* @return the loaded Object
*/
public Persistable loadObject(Persistable persistable, boolean forceReloadFromDB) {
if (persistable == null) throw new AssertException("persistable must not be null");
beginTransaction(persistable);
Persistable ret;
Class theClass = persistable.getClass();
if (forceReloadFromDB) {
// we want to reload it from the database.
// there are 3 scenarios possible:
// a) the object is not yet in the hibernate cache
// b) the object is in the hibernate cache
// c) the object is detached and there is an object with the same id in the hibernate cache
if (contains(persistable)) {
// case b - then we can use evict and load
getDBManager().evict(persistable);
return (Persistable) loadObject(theClass, persistable.getKey());
} else {
// case a or c - unfortunatelly we can't distinguish these two cases
// and session.refresh(Object) doesn't work.
// the only scenario that works is load/evict/load
Persistable attachedObj = (Persistable) loadObject(theClass, persistable.getKey());
getDBManager().evict(attachedObj);
return (Persistable) loadObject(theClass, persistable.getKey());
}
} else if (!contains(persistable)) {
// forceReloadFromDB is false - hence it is OK to take it from the cache if it would be there
// now this object directly is not in the cache, but it's possible that the object is detached
// and there is an object with the same id in the hibernate cache.
// therefore the following loadObject can either return it from the cache or load it from the DB
return (Persistable) loadObject(theClass, persistable.getKey());
} else {
// nothing to do, return the same object
return persistable;
}
}
@Override
public void commitAndCloseSession() {
try {
if (needsCommit()) {
commit();
}
} finally {
try{
// double check: is the transaction still open? if yes, is it not rolled-back? if yes, do a rollback now!
if (isConnectionOpen() && hasTransaction() && getTransaction().isInTransaction() && !getTransaction().isRolledBack()) {
getLogger().error("commitAndCloseSession: commit seems to have failed, transaction still open. Doing a rollback!", new Exception("commitAndCloseSession"));
rollback();
}
} finally {
closeSession();
}
}
}
@Override
public void rollbackAndCloseSession() {
try {
rollback();
} finally {
closeSession();
}
}
/**
* Call this to commit a transaction opened by beginTransaction().
*/
public void commit() {
// StackTraceElement[] elems = Thread.currentThread().getStackTrace();
// if (elems!=null && elems.length>1) {
// if (!elems[2].getClassName().equals("org.olat.commons.coordinate.cluster.ClusterSyncer") &&
// !elems[2].getClassName().equals("org.olat.core.util.mtx.ManagedTransaction")) {
// System.out.println("--> TRANSACTION RULES BROKEN");
// }
// }
if (isLogDebugEnabled()) logDebug("commit start...", null);
try {
if (isConnectionOpen() && hasTransaction() && getTransaction().isInTransaction()) {
if (isLogDebugEnabled()) logDebug("has Transaction and is in Transaction => commit", null);
getData().incrementCommitCounter();
if ( isLogDebugEnabled() ) {
if ((maxCommitCounter != 0) && (getData().getCommitCounter() > maxCommitCounter) ) {
logInfo("Call too many commit in a db-session, commitCounter=" + getData().getCommitCounter() +"; could be a performance problem" , null);
}
}
getTransaction().commit();
getData().handleCommit(this);
if (isLogDebugEnabled()) logDebug("Commit DONE hasTransaction()=" + hasTransaction(), null);
} else {
if (isLogDebugEnabled()) logDebug("Call commit without starting transaction", null );
}
} catch (Error er) {
logError("Uncaught Error in DBImpl.commit.", er);
throw er;
} catch (Exception e) {
// Filter Exception form async TaskExecutorThread, there are exception allowed
if (!Thread.currentThread().getName().equals("TaskExecutorThread")) {
logWarn("Caught Exception in DBImpl.commit.", e);
}
// Error when trying to commit
try {
if (hasTransaction() && !getTransaction().isRolledBack()) {
getTransaction().rollback();
getData().handleRollback(this);
}
} catch (Error er) {
logError("Uncaught Error in DBImpl.commit.catch(Exception).", er);
throw er;
} catch (Exception ex) {
logWarn("Could not rollback transaction after commit!", ex);
throw new DBRuntimeException("rollback after commit failed", e);
}
throw new DBRuntimeException("commit failed, rollback transaction", e);
}
}
/**
* Call this to rollback current changes.
*/
public void rollback() {
if (isLogDebugEnabled()) logDebug("rollback start...", null);
try {
// see closeSession() and OLAT-4318: more robustness with commit/rollback/close, therefore
// we check if the connection is open at this stage at all
if (isConnectionOpen() && hasTransaction() && getTransaction().isInTransaction() ) {
if (isLogDebugEnabled()) logDebug("Call rollback", null);
getTransaction().rollback();
getData().handleRollback(this);
}
} catch (Exception ex) {
logWarn("Could not rollback transaction!",ex);
throw new DBRuntimeException("rollback failed", ex);
}
}
/**
* Statistics must be enabled first, when you want to use it.
* @return Return Hibernates statistics object.
*/
public Statistics getStatistics() {
return sessionFactory.getStatistics();
}
/**
* Register StatisticsService as MBean for JMX support.
* @param mySessionFactory
*/
private void registerStatisticsServiceAsMBean(SessionFactory mySessionFactory) {
if (mySessionFactory == null) {
throw new AssertException("Can not register StatisticsService as MBean, SessionFactory is null");
}
try {
Hashtable<String, String> tb = new Hashtable<String, String>();
tb.put("type", "statistics");
tb.put("sessionFactory", "HibernateStatistics");
ObjectName on = new ObjectName("org.olat.core.persistance", tb);
MBeanServer server = (MBeanServer) CoreSpringFactory.getBean(MBeanServerFactoryBean.class);
StatisticsService stats = new StatisticsService();
stats.setSessionFactory(mySessionFactory);
server.registerMBean(stats, on);
} catch (MalformedObjectNameException e) {
logWarn("JMX-Error : Can not register as MBean, MalformedObjectNameException=", e);
} catch (InstanceAlreadyExistsException e) {
logWarn("JMX-Error : Can not register as MBean, InstanceAlreadyExistsException=", e);
} catch (MBeanRegistrationException e) {
logWarn("JMX-Error : Can not register as MBean, MBeanRegistrationException=", e);
} catch (NotCompliantMBeanException e) {
logWarn("JMX-Error : Can not register as MBean, NotCompliantMBeanException=", e);
} catch (NoSuchBeanDefinitionException e) {
logWarn("JMX-Error : Can not register as MBean, NoSuchBeanDefinitionException=", e);
}
}
/**
* @see org.olat.core.commons.persistence.DB#intermediateCommit()
*/
public void intermediateCommit() {
this.commit();
getData().handleCommit(this);
this.closeSession();
}
public void addTransactionListener(ITransactionListener listener) {
getData().addTransactionListener(listener);
}
public void removeTransactionListener(ITransactionListener listener) {
getData().removeTransactionListener(listener);
}
private boolean needsCommit() {
// see closeSession() and OLAT-4318: more robustness with commit/rollback/close, therefore
// we check if the connection is open at this stage at all
return isConnectionOpen() && hasTransaction() && !getTransaction().isRolledBack() && getTransaction().isInTransaction();
}
/** temp debug only **/
public void forceSetDebugLogLevel(boolean enabled) {
if (!enabled) {
forcedLogger = null;
return;
}
forcedLogger = new OLog() {
public void audit(String logMsg) {
Tracing.logAudit(logMsg, DBImpl.class);
}
public void audit(String logMsg, String userObj) {
Tracing.logAudit(logMsg, userObj, DBImpl.class);
}
public void debug(String logMsg, String userObj) {
Tracing.logInfo(logMsg, userObj, DBImpl.class);
}
public void debug(String logMsg) {
Tracing.logInfo(logMsg, DBImpl.class);
}
public void error(String logMsg, Throwable cause) {
Tracing.logError(logMsg, cause, DBImpl.class);
}
public void error(String logMsg) {
Tracing.logError(logMsg, DBImpl.class);
}
public void info(String logMsg, String userObject) {
Tracing.logInfo(logMsg, userObject, DBImpl.class);
}
public void info(String logMsg) {
Tracing.logInfo(logMsg, DBImpl.class);
}
public boolean isDebug() {
return true;
}
public void warn(String logMsg, Throwable cause) {
Tracing.logWarn(logMsg, cause, DBImpl.class);
}
public void warn(String logMsg) {
Tracing.logWarn(logMsg, DBImpl.class);
}
};
}
protected OLog getLogger() {
if (forcedLogger==null) {
return super.getLogger();
} else {
return forcedLogger;
}
}
}