Package org.olat.core.commons.persistence

Source Code of org.olat.core.commons.persistence.DBImpl$ThreadLocalData

/**
* 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;
    }
  }
}
TOP

Related Classes of org.olat.core.commons.persistence.DBImpl$ThreadLocalData

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.