/*
* Lokomo OneCMDB - An Open Source Software for Configuration
* Management of Datacenter Resources
*
* Copyright (C) 2006 Lokomo Systems AB
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* Lokomo Systems AB can be contacted via e-mail: info@lokomo.com or via
* paper mail: Lokomo Systems AB, Sv�rdv�gen 27, SE-182 33
* Danderyd, Sweden.
*
*/
package org.onecmdb.core.internal.storage.hibernate;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.onecmdb.core.IAttribute;
import org.onecmdb.core.ICi;
import org.onecmdb.core.ICmdbTransaction;
import org.onecmdb.core.IObjectScope;
import org.onecmdb.core.IPath;
import org.onecmdb.core.IRFC;
import org.onecmdb.core.ISession;
import org.onecmdb.core.internal.ccb.AttributeModifiable;
import org.onecmdb.core.internal.ccb.CiModifiable;
import org.onecmdb.core.internal.ccb.CmdbTransaction;
import org.onecmdb.core.internal.ccb.RfcQueryCriteria;
import org.onecmdb.core.internal.ccb.rfc.RFC;
import org.onecmdb.core.internal.model.BasicAttribute;
import org.onecmdb.core.internal.model.ConfigurationItem;
import org.onecmdb.core.internal.model.ItemId;
import org.onecmdb.core.internal.model.Path;
import org.onecmdb.core.internal.model.QueryCriteria;
import org.onecmdb.core.internal.model.QueryResult;
import org.onecmdb.core.internal.storage.IDaoReader;
import org.onecmdb.core.internal.storage.IDaoWriter;
import org.onecmdb.core.internal.storage.expression.OneCMDBExpression;
import org.onecmdb.core.tests.profiler.Profiler;
import org.springframework.dao.ConcurrencyFailureException;
public class HibernateDao2 {//implements IDaoReader2, IDaoWriter2 {
private SessionFactory sf;
private String namespace = "oneCMDB";
private volatile boolean sessionLocked;
private Log log = LogFactory.getLog(this.getClass());
private TestCache aliasCache = new TestCache();
private TestCache idCache = new TestCache();
public void setSessionFactory(SessionFactory sf) {
this.sf = sf;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
public String getNamespace() {
return (this.namespace);
}
public void destory() {
log.info("HIBERNATE DAO: Shutdown started");
sf.close();
log.info("HIBERNATE DAO: Shutdown completed");
}
/*
public void setInterceptor(DaoReaderInterceptor interceptor) {
if (interceptor instanceof DaoReaderInterceptor) {
((DaoReaderInterceptor) interceptor).setDaoReader(this);
}
}
*/
/**
* Retrive a session. There will only exists only ONE open session per
* application. This means that the closeSession() MUST be called once a
* getSession() has been called, else the system will be blocked!
*
* @return
*/
private Session getSession(ISession s) {
// Lock here
synchronized (sf) {
while (sessionLocked) {
try {
sf.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new ConcurrencyFailureException(
"Session wait got interrupted", e);
}
}
// Create Session interceptor...
DaoSessionReaderInterceptor inter = new DaoSessionReaderInterceptor();
//inter.setDaoReader(this);
inter.setSession(s);
Session session = sf.openSession(inter);
//sessionLocked = true;
return (session);
}
}
private void closeSession(Session session) {
synchronized (sf) {
try {
session.close();
} finally {
// Relese lock...
//sessionLocked = false;
sf.notifyAll();
}
}
}
private Map<ItemId, ICi> mapdb = new HashMap<ItemId, ICi>();
private Queue<ICmdbTransaction> txqueue = new LinkedList<ICmdbTransaction>();
/**
* Transaction handling....
*/
public void storeTransaction(ICmdbTransaction cmdbtx) {
/*
* Session session = getSession(); Transaction tx = null; try {
*
* tx = session.beginTransaction(); for (IRFC rfc : cmdbtx.getRfcs()) {
* session.save(rfc); } session.save(cmdbtx); tx.commit(); } catch
* (HibernateException he) { if (tx!=null) { tx.rollback(); } throw he; }
* finally { closeSession(session); }
*/
}
/*
public ICmdbTransaction getTransaction(ItemId id) {
Session session = getSession();
try {
Object o = session.get(CmdbTransaction.class, ((ItemId) id)
.asLong());
if (o instanceof ICmdbTransaction) {
return ((ICmdbTransaction) o);
}
return (null);
} finally {
closeSession(session);
}
}
*/
public void rejectTransaction(ICmdbTransaction cmdbTx) {
idCache.clear();
aliasCache.clear();
Session session = getSession(cmdbTx.getSession());
Transaction tx = null;
try {
tx = session.beginTransaction();
cmdbTx.setEndTs(new Date());
storeTx(session, cmdbTx);
tx.commit();
} catch (HibernateException he) {
if (tx != null) {
tx.rollback();
}
throw he;
} finally {
closeSession(session);
}
}
private void storeTx(Session session, ICmdbTransaction cmdbTx) {
storeRFCs(session, cmdbTx, cmdbTx.getRfcs());
session.save(cmdbTx);
}
private void storeRFCs(Session session, ICmdbTransaction tx, List<IRFC> rfcs) {
for (IRFC rfc : rfcs) {
// Update tx id.
rfc.setTxId(tx.getId().asLong());
// Don't save Attribute/Ci modifiable.
if (!(
rfc.getClass().equals(CiModifiable.class)
||
rfc.getClass().equals(AttributeModifiable.class)
)) {
session.save(rfc);
}
if (rfc.getRfcs().size() > 0) {
storeRFCs(session, tx, rfc.getRfcs());
}
}
}
public void commitTransaction(IObjectScope scope, ICmdbTransaction cmdbTx) {
idCache.clear();
aliasCache.clear();
Session session = null;
Transaction tx = null;
Profiler.start("commitTx()");
try {
session = getSession(cmdbTx.getSession());
tx = session.beginTransaction();
for (ICi item : scope.getDestroyedICis()) {
session.delete(item);
}
for (ICi item : scope.getNewICis()) {
session.save(item);
}
for (ICi item : scope.getModifiedICis()) {
session.update(item);
}
cmdbTx.setEndTs(new Date());
storeTx(session, cmdbTx);// session.update(cmdbTx);
tx.commit();
} catch (HibernateException he) {
if (tx != null) {
tx.rollback();
}
throw he;
} finally {
closeSession(session);
Profiler.stop("commitTx()");
}
}
public List queryCriteria(ISession s, DetachedCriteria detachedCrit, PageInfo info) {
Session session = getSession(s);
List result = Collections.EMPTY_LIST;
try {
Profiler.start("QueryCriteria():");
Criteria criteria = detachedCrit.getExecutableCriteria(session);
criteria.addOrder(Order.asc("alias"));
if (info != null) {
if (info.getFirstResult() != null) {
criteria.setFirstResult(info.getFirstResult());
}
if (info.getMaxResult() != null) {
criteria.setMaxResults(info.getMaxResult());
}
}
result = criteria.list();
} finally {
Profiler.stop();
closeSession(session);
}
return(result);
}
}