/*******************************************************************************
* ALMA - Atacama Large Millimeter Array
* Copyright (c) ESO - European Southern Observatory, 2011
* (in the framework of the ALMA collaboration).
* All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*******************************************************************************/
package alma.acs.tmcdb;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import junit.framework.TestCase;
import org.hibernate.jdbc.Work;
import alma.acs.logging.ClientLogManager;
import alma.acs.logging.level.AcsLogLevelDefinition;
import com.cosylab.cdb.jdal.hibernate.HibernateUtil;
import com.cosylab.cdb.jdal.hibernate.HibernateUtil.HibernateUtilException;
import com.cosylab.cdb.jdal.logging.AcsLoggerHelper;
public class TestPojosCascading extends TestCase {
private final String CREATE_TMCDB_SWCORE = System.getenv("ACSDATA") + "/config/DDL/hsqldb/TMCDB_swconfigcore/CreateHsqldbTables.sql";
private final String CREATE_TMCDB_SWEXT = System.getenv("ACSDATA") + "/config/DDL/hsqldb/TMCDB_swconfigext/CreateHsqldbTables.sql";
private final String DROP_TMCDB_SWCORE = System.getenv("ACSDATA") + "/config/DDL/hsqldb/TMCDB_swconfigcore/DropAllTables.sql";
private final String DROP_TMCDB_SWEXT = System.getenv("ACSDATA") + "/config/DDL/hsqldb/TMCDB_swconfigext/DropAllTables.sql";
private final static int DEFAULT_BUF_LEN = 64 * 1024;
private Logger logger;
private HibernateUtil hibernateUtil;
protected void setUp() throws Exception {
System.out.println("\n---------------- " + getName() + " ---------------\n");
String loggerName = getName(); // name of junit test method
AcsLoggerHelper acsLoggerHelper = AcsLoggerHelper.getInstance();
acsLoggerHelper.setLoggerName(loggerName);
acsLoggerHelper.setDefaultLogLevels(AcsLogLevelDefinition.INFO, AcsLogLevelDefinition.INFO);
logger = AcsLoggerHelper.getInstance().getSharedLogger();
acsLoggerHelper.setHibernateLogLevels(AcsLogLevelDefinition.INFO, AcsLogLevelDefinition.WARNING);
acsLoggerHelper.setHibernateSqlLogLevels(AcsLogLevelDefinition.TRACE, AcsLogLevelDefinition.TRACE);
hibernateUtil = HibernateUtil.getInstance(logger);
hibernateUtil.setConfiguration(new org.hibernate.cfg.Configuration().configure("test-hibernate.cfg.xml"));
hibernateUtil.getSessionFactory().openSession();
createDB();
}
protected void tearDown() throws Exception {
dropDB();
// null the various static logger references; otherwise junit will not create new loggers in subsequent setUp
HibernateUtil.clearInstance();
AcsLoggerHelper.getInstance().shutdown();
ClientLogManager.getAcsLogManager().shutdown(true);
}
public void testNoCascading() throws Exception {
try {
Configuration conf = new Configuration();
conf.setConfigurationName("rtobarConfig");
conf.setFullName("Super full name");
conf.setActive(true);
conf.setCreationTime(new Date());
conf.setDescription("Testing configuration");
EventChannel ec = new EventChannel();
ec.setName("NC1");
ec.setPath("");
ec.setConfiguration(conf);
try {
hibernateUtil.beginTransaction();
hibernateUtil.getSession().save(ec);
hibernateUtil.commitTransaction();
fail("Should fail since configuration is not cascaded by EC");
} catch(Throwable t) {
hibernateUtil.closeSession();
}
ec = new EventChannel();
ec.setName("NC1");
ec.setPath("path"); // path is part of a UNIQUE statement, so it must have a value (it seems)
ec.setConfiguration(conf);
hibernateUtil.beginTransaction();
hibernateUtil.getSession().save(conf);
hibernateUtil.getSession().save(ec);
hibernateUtil.commitTransaction();
} catch (Exception ex) {
logger.log(Level.WARNING, "Got a failure already before dropDB is called", ex);
throw ex;
}
}
public void testCascadingAggregation() throws Exception {
LoggingConfig lconf = new LoggingConfig();
NamedLoggerConfig nlconf = new NamedLoggerConfig();
nlconf.setName("rtobarNamedLoggingConfig");
nlconf.setMinLogLevel((byte)0x01);
nlconf.setMinLogLevelLocal((byte)0x01);
nlconf.setLoggingConfig(lconf);
Set<NamedLoggerConfig> nlconfs = new HashSet<NamedLoggerConfig>();
nlconfs.add(nlconf);
lconf.setNamedLoggerConfigs(nlconfs);
hibernateUtil.beginTransaction();
hibernateUtil.getSession().save(lconf); // Should cascade the NamedLoggerConfig
hibernateUtil.commitTransaction();
}
@SuppressWarnings("unchecked")
public void testCascadingInverseAggregation() throws Exception {
try {
Component comp = createTrasientFilledComponent();
hibernateUtil.beginTransaction();
hibernateUtil.getSession().save(comp.getConfiguration());
hibernateUtil.getSession().save(comp.getComponentType());
hibernateUtil.getSession().save(comp); // compType cascades
hibernateUtil.commitTransaction();
List res = hibernateUtil.getList(ComponentType.class);
assertEquals(1, res.size());
res = hibernateUtil.getList(Component.class);
assertEquals(1, res.size());
res = hibernateUtil.getList(Configuration.class);
assertEquals(1, res.size());
// Now try inverse cascading
Set<BACIProperty> props = new HashSet<BACIProperty>();
for(int i=0; i!= 10; i++) {
props.add( createTrasientFilledBACIProperty("Prop-" + i, comp) );
}
comp.setBACIProperties(props);
hibernateUtil.beginTransaction();
hibernateUtil.getSession().saveOrUpdate(comp); // props cascade as inverse
hibernateUtil.commitTransaction();
res = hibernateUtil.getList(ComponentType.class);
assertEquals(1, res.size());
res = hibernateUtil.getList(Component.class);
assertEquals(1, res.size());
res = hibernateUtil.getList(Configuration.class);
assertEquals(1, res.size());
res = hibernateUtil.getList(BACIProperty.class);
assertEquals(10, res.size());
} catch (Exception ex) {
logger.log(Level.WARNING, "Got a failure already before dropDB is called", ex);
throw ex;
}
}
@SuppressWarnings("unchecked")
public void testCascadingInverseComposition() throws Exception {
try {
Component comp = createTrasientFilledComponent();
hibernateUtil.beginTransaction();
hibernateUtil.getSession().save(comp.getConfiguration());
hibernateUtil.getSession().save(comp.getComponentType());
hibernateUtil.getSession().save(comp); // compType cascades
hibernateUtil.commitTransaction();
List res = hibernateUtil.getList(ComponentType.class);
assertEquals(1, res.size());
res = hibernateUtil.getList(Component.class);
assertEquals(1, res.size());
res = hibernateUtil.getList(Configuration.class);
assertEquals(1, res.size());
// Now try inverse cascading
Set<BACIProperty> props = new HashSet<BACIProperty>();
for(int i=0; i!= 10; i++) {
props.add( createTrasientFilledBACIProperty("Prop-" + i, comp) );
}
comp.setBACIProperties(props);
hibernateUtil.beginTransaction();
hibernateUtil.getSession().saveOrUpdate(comp); // props cascade as inverse
hibernateUtil.commitTransaction();
res = hibernateUtil.getList(ComponentType.class);
assertEquals(1, res.size());
res = hibernateUtil.getList(Component.class);
assertEquals(1, res.size());
res = hibernateUtil.getList(Configuration.class);
assertEquals(1, res.size());
res = hibernateUtil.getList(BACIProperty.class);
assertEquals(10, res.size());
// And now delete the component - Component and BACI properties should get deleted
hibernateUtil.beginTransaction();
hibernateUtil.getSession().delete(comp); // props cascade as inverse
hibernateUtil.commitTransaction();
res = hibernateUtil.getList(ComponentType.class);
assertEquals(1, res.size());
res = hibernateUtil.getList(Component.class);
assertEquals(0, res.size());
res = hibernateUtil.getList(Configuration.class);
assertEquals(1, res.size());
res = hibernateUtil.getList(BACIProperty.class);
assertEquals(0, res.size());
} catch (Exception ex) {
logger.log(Level.WARNING, "Got a failure already before dropDB is called", ex);
throw ex;
}
}
private Component createTrasientFilledComponent() {
ComponentType compType = new ComponentType();
compType.setIDL("IDL:alma/Some/IF.idl:1.0");
Configuration conf = new Configuration();
conf.setConfigurationName("rtobarConfig");
conf.setFullName("Super full name");
conf.setActive(true);
conf.setCreationTime(new Date());
conf.setDescription("Testing configuration");
Component comp = new Component();
comp.setComponentType(compType);
comp.setConfiguration(conf);
comp.setContainer(null); // Container can be null
comp.setComponentName("COMPONENT");
comp.setCode("Code");
comp.setImplLang(ImplLangEnum.JAVA);
comp.setRealTime(false);
comp.setPath(".");
comp.setIsAutostart(true);
comp.setIsDefault(true);
comp.setIsControl(false);
comp.setIsStandaloneDefined(true);
comp.setKeepAliveTime(0);
comp.setMinLogLevel((byte)0);
comp.setMinLogLevelLocal((byte)0);
comp.setXMLDoc("<doc/>");
return comp;
}
private BACIProperty createTrasientFilledBACIProperty(String name, Component comp) {
BACIProperty prop = new BACIProperty();
prop.setComponent(comp);
prop.setPropertyName(name);
prop.setDescription("desc");
prop.setFormat("%d");
prop.setUnits("[s]");
prop.setResolution("0.1");
prop.setArchive_priority(1);
prop.setArchive_min_int(1.0);
prop.setArchive_max_int(1.0);
prop.setArchive_suppress(false);
prop.setArchive_mechanism(BACIPropArchMech.MONITOR_COLLECTOR);
prop.setDefault_timer_trig(0.1);
prop.setMin_timer_trig(0.1);
prop.setInitialize_devio(true);
prop.setDefault_value("0.1");
prop.setArchive_delta(0.1);
return prop;
}
private void createDB() throws HibernateUtilException {
String url = hibernateUtil.getConfiguration().getProperty("hibernate.connection.url");
if( url.contains("oracle") ) {
return;
}
hibernateUtil.beginTransaction();
hibernateUtil.getSession().doWork( new Work() {
public void execute(Connection conn) throws SQLException {
conn.setAutoCommit(true);
runScriptFile(CREATE_TMCDB_SWCORE, conn);
runScriptFile(CREATE_TMCDB_SWEXT, conn);
}
});
hibernateUtil.commitTransaction();
}
private void dropDB() throws HibernateUtilException {
String url = hibernateUtil.getConfiguration().getProperty("hibernate.connection.url");
if( !url.contains("mem") ) {
hibernateUtil.beginTransaction();
hibernateUtil.getSession().doWork( new Work() {
public void execute(Connection conn) throws SQLException {
conn.setAutoCommit(true);
runScript("delete from event;" +
"delete from eventchannel;" +
"delete from baciproperty;" +
"delete from component;" +
"delete from componenttype;" +
"delete from namedloggerconfig;" +
"delete from loggingconfig;" +
"delete from eventchannel;" +
"delete from computer;" +
"delete from networkdevice;" +
"delete from configuration",
conn);
}
});
hibernateUtil.commitTransaction();
return;
}
hibernateUtil.beginTransaction();
hibernateUtil.getSession().doWork( new Work() {
public void execute(Connection conn) throws SQLException {
conn.setAutoCommit(true);
runScriptFile(DROP_TMCDB_SWEXT, conn);
runScriptFile(DROP_TMCDB_SWCORE, conn);
}
});
hibernateUtil.commitTransaction();
}
private void runScriptFile( String script, Connection conn ) throws SQLException {
String sql = "";
try {
// try to get hold of the script
InputStream is = getResourceStream(script);
sql = fileToString(new InputStreamReader(is));
} catch (IOException e) {
// convert to runtime, as this is only used for testing
throw new RuntimeException(e);
}
runScript(sql, conn);
}
private void runScript( String sql, Connection conn ) throws SQLException {
Statement stmt = conn.createStatement();
String[] statements = sql.split( ";", -1 );
for( int i = 0; i < statements.length; i++ ) {
String statement = statements[i].trim();
if( statement.length() == 0 ) {
// skip empty lines
continue;
}
stmt.execute( statement );
}
}
private InputStream getResourceStream(String pathname) throws IOException {
InputStream s = null; // this is the stream we return
// Look for the resource on the file system
// -----------------------------------------
File f = new File( pathname );
s = new FileInputStream( f );
return s;
}
private String fileToString( Reader reader ) throws IOException {
BufferedReader br = new BufferedReader( reader );
StringBuffer sb = new StringBuffer();
char[] buff = new char[DEFAULT_BUF_LEN];
while( br.ready() ) {
int nread = br.read( buff, 0, buff.length );
if( nread <= 0 ) {
break;
}
sb.append( buff, 0, nread );
}
br.close();
return sb.toString();
}
}