package gr.ntua.ivml.mint.db;
import gr.ntua.ivml.mint.persistent.BlobWrap;
import gr.ntua.ivml.mint.persistent.Crosswalk;
import gr.ntua.ivml.mint.persistent.DataUpload;
import gr.ntua.ivml.mint.persistent.Lock;
import gr.ntua.ivml.mint.persistent.Mapping;
import gr.ntua.ivml.mint.persistent.Organization;
import gr.ntua.ivml.mint.persistent.Publication;
import gr.ntua.ivml.mint.persistent.SchemaPublication;
import gr.ntua.ivml.mint.persistent.Thesaurus;
import gr.ntua.ivml.mint.persistent.ThesaurusAssignment;
import gr.ntua.ivml.mint.persistent.Transformation;
import gr.ntua.ivml.mint.persistent.User;
import gr.ntua.ivml.mint.persistent.XMLNode;
import gr.ntua.ivml.mint.persistent.XmlSchema;
import gr.ntua.ivml.mint.util.Config;
import java.io.BufferedReader;
import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.StatelessSession;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.impl.SessionFactoryImpl;
public class DB {
private static SessionFactory sessionFactory;
private static TestSetup testSetup;
private static boolean schemaSetup;
static final Logger log = Logger.getLogger( DB.class );
//threadlocal, but I rig it myself ..
private static Hashtable<Long, Session> sessions = new Hashtable<Long,Session>();
private static ThreadLocal<StatelessSession> statelessSessions = new ThreadLocal<StatelessSession>();
static {
initSession();
}
private static void initSession() {
try {
// Create the SessionFactory from hibernate.cfg.xml
// or, like here, from hibernate.properties
Class<?>[] classes = { User.class, Organization.class,
DataUpload.class, BlobWrap.class,
XMLNode.class, Lock.class,
Mapping.class, Transformation.class,
Publication.class, XmlSchema.class,
Crosswalk.class, Thesaurus.class,
ThesaurusAssignment.class };
Set<Class<?>> classSet = new HashSet<Class<?>>();
classSet.addAll( Arrays.asList( classes ));
if(Config.has("publish") && Config.get("publish").equalsIgnoreCase("newschema")){
classSet.remove( Publication.class );
classSet.add( SchemaPublication.class );
log.debug( "Replaced Pulication with SchemaPublication!");}
AnnotationConfiguration ac = new AnnotationConfiguration();
// is there custom db stuff ?
try {
Class<?> customDB = Class.forName("gr.ntua.ivml.mint.db.CustomDB");
Method m = customDB.getMethod("init", AnnotationConfiguration.class, Set.class );
m.invoke(null, ac, classSet );
} catch( Exception e ) {
log.debug( "No CustomDB found" );
}
for( Class<?> c: classSet ) {
ac.addClass(c);
}
sessionFactory = ac.buildSessionFactory( );
} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
log.error("Initial SessionFactory creation failed." , ex);
throw new ExceptionInInitializerError(ex);
}
log.info( "SessionFactory instatiated" );
// load the classes, they do some cleanup
getLockManager();
getDataUploadDAO();
getTransformationDAO();
new GlobalPrefixStore();
}
/*
* Should try and open session when request comes in
public static Session getSession() {
return sessionFactory.openSession();
}
*/
public static void setSession( Session s ) {
long threadId = Thread.currentThread().getId();
sessions.put( threadId, s );
}
public static void removeSession() {
long threadId = Thread.currentThread().getId();
sessions.remove( threadId );
}
public static Session getSession() {
long threadId = Thread.currentThread().getId();
Session s;
s = sessions.get( threadId );
if((s == null ) || ( !s.isOpen())) {
s = sessionFactory.openSession();
log.debug( "Session created!");
sessions.put( threadId, s );
}
return s;
}
public static StatelessSession getStatelessSession() {
StatelessSession ss = statelessSessions.get();
if( ss == null ) {
try {
Connection c = ((SessionFactoryImpl)sessionFactory).getConnectionProvider().getConnection();
ss = sessionFactory.openStatelessSession(c);
log.debug( "StatelessSession created!");
statelessSessions.set( ss );
} catch( SQLException se ) {
log.error( "No stateless Session", se );
}
}
return ss;
}
public static void closeStatelessSession() {
StatelessSession ss = statelessSessions.get();
if( ss != null ) {
try {
ss.connection().close();
} catch( SQLException e ) {
log.error( e );
}
ss.close();
statelessSessions.set( null );
}
}
public static Session newSession() {
closeSession();
return getSession();
}
public static void closeSession() {
long threadId = Thread.currentThread().getId();
Session s = sessions.get( threadId );
if( s != null ) {
s.close();
sessions.remove(threadId );
}
}
public static void logPid() {
Session s = getSession();
Connection c = s.connection();
logPid(c );
}
public static void logPid( Connection c ) {
try {
Statement st = c.createStatement();
st.execute("select pg_backend_pid()");
ResultSet rs = st.getResultSet();
rs.next();
log.debug( "Thread: " + Thread.currentThread().getName() + " pid = " + rs.getInt(1));
} catch( Exception e ) {
log.debug( "Cant log transaction id " + e.getMessage());
}
}
// test to write out current transaction (and create new one)
public static void commit() {
getSession().flush();
getSession().getTransaction().commit();
getSession().beginTransaction();
}
public static LockManager getLockManager() {
return new LockManager();
}
public static CrosswalkDAO getCrosswalkDAO() {
return (CrosswalkDAO) instantiateDAO( CrosswalkDAO.class );
}
public static XmlSchemaDAO getXmlSchemaDAO() {
return (XmlSchemaDAO) instantiateDAO( XmlSchemaDAO.class );
}
public static UserDAO getUserDAO() {
return (UserDAO) instantiateDAO( UserDAO.class );
}
public static TransformationDAO getTransformationDAO() {
return (TransformationDAO) instantiateDAO( TransformationDAO.class );
}
public static XMLNodeDAO getXMLNodeDAO() {
return (XMLNodeDAO) instantiateDAO( XMLNodeDAO.class );
}
public static XpathHolderDAO getXpathHolderDAO() {
return (XpathHolderDAO) instantiateDAO( XpathHolderDAO.class );
}
public static OrganizationDAO getOrganizationDAO() {
return (OrganizationDAO) instantiateDAO( OrganizationDAO.class );
}
public static XmlObjectDAO getXmlObjectDAO() {
return (XmlObjectDAO) instantiateDAO( XmlObjectDAO.class );
}
public static DataUploadDAO getDataUploadDAO() {
return (DataUploadDAO) instantiateDAO( DataUploadDAO.class );
}
public static MappingDAO getMappingDAO() {
return (MappingDAO) instantiateDAO( MappingDAO.class );
}
public static PublicationDAO getPublicationDAO() {
return (PublicationDAO) instantiateDAO( PublicationDAO.class );
}
public static ThesaurusDAO getThesaurusDAO() {
return (ThesaurusDAO) instantiateDAO( ThesaurusDAO.class );
}
public static ThesaurusAssignmentDAO getThesaurusAssignmentDAO() {
return (ThesaurusAssignmentDAO) instantiateDAO( ThesaurusAssignmentDAO.class );
}
private static DAO instantiateDAO(Class<? extends DAO> daoClass) {
try {
DAO dao = (DAO)daoClass.newInstance();
return dao;
} catch (Exception ex) {
throw new RuntimeException("Can not instantiate DAO: " + daoClass, ex);
}
}
public static void testSetup() {
if( testSetup != null ) return;
testSetup = new TestSetup();
}
private static StringBuffer readFile( String file ) throws IOException {
StringBuffer sb = new StringBuffer();
InputStream is = DB.class.getClassLoader().getResourceAsStream(file);
BufferedReader br = new BufferedReader( new InputStreamReader( is, Charset.forName( "UTF-8" )));
String buffer;
while((buffer = br.readLine()) != null) {
sb.append( buffer );
sb.append( "\n" );
}
return sb;
}
public static void doSQL( String filename ) {
try {
StringBuffer sb = readFile( filename );
Transaction t = DB.getSession().beginTransaction();
DB.getSession().createSQLQuery(sb.toString()).executeUpdate();
t.commit();
} catch( Exception e ) {
throw new IOError( e );
}
}
public static void flush() {
getSession().flush();
}
public static void initSchema() {
doSQL( "createSchema.sql" );
}
}