package edu.harvard.i2b2.crc.ejb;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import javax.xml.bind.JAXBElement;
import org.apache.catalina.tribes.tipis.AbstractReplicatedMap.MapMessage;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.harvard.i2b2.common.exception.I2B2DAOException;
import edu.harvard.i2b2.common.exception.I2B2Exception;
import edu.harvard.i2b2.common.util.ServiceLocator;
import edu.harvard.i2b2.common.util.ServiceLocatorException;
import edu.harvard.i2b2.common.util.jaxb.JAXBUnWrapHelper;
import edu.harvard.i2b2.common.util.jaxb.JAXBUtil;
import edu.harvard.i2b2.common.util.jaxb.JAXBUtilException;
import edu.harvard.i2b2.crc.dao.DAOFactoryHelper;
import edu.harvard.i2b2.crc.dao.IDAOFactory;
import edu.harvard.i2b2.crc.dao.SetFinderDAOFactory;
import edu.harvard.i2b2.crc.dao.setfinder.CRCTimeOutException;
import edu.harvard.i2b2.crc.dao.setfinder.CheckSkipTempTable;
import edu.harvard.i2b2.crc.dao.setfinder.IQueryInstanceDao;
import edu.harvard.i2b2.crc.dao.setfinder.LockedoutException;
import edu.harvard.i2b2.crc.dao.setfinder.QueryExecutorDao;
import edu.harvard.i2b2.crc.datavo.CRCJAXBUtil;
import edu.harvard.i2b2.crc.datavo.db.DataSourceLookup;
import edu.harvard.i2b2.crc.datavo.db.QtQueryInstance;
import edu.harvard.i2b2.crc.datavo.db.QtQueryStatusType;
import edu.harvard.i2b2.crc.datavo.i2b2message.BodyType;
import edu.harvard.i2b2.crc.datavo.i2b2message.RequestMessageType;
import edu.harvard.i2b2.crc.datavo.setfinder.query.PsmQryHeaderType;
import edu.harvard.i2b2.crc.datavo.setfinder.query.QueryDefinitionRequestType;
import edu.harvard.i2b2.crc.datavo.setfinder.query.QueryDefinitionType;
import edu.harvard.i2b2.crc.datavo.setfinder.query.QueryModeType;
import edu.harvard.i2b2.crc.datavo.setfinder.query.ResultOutputOptionListType;
import edu.harvard.i2b2.crc.role.AuthrizationHelper;
import edu.harvard.i2b2.crc.util.QueryProcessorUtil;
public class ExecRunnable implements Runnable{
private static Log log = LogFactory.getLog(ExecRunnable.class);
String sqlString = "";
String queryInstanceId = "";
String patientSetId = "";
String xmlRequest = "";
String dsLookupDomainId= "";
String dsLookupProjectId ="";
String dsLookupOwnerId = "";
String pmXml = null;
Map returnMap = new HashMap();
public ExecRunnable() {
}
private Exception ex = null;
private String callingMDBName = QueryManagerBeanUtil.SMALL_QUEUE, sessionId = "";
// default timeout three minutes
int transactionTimeout = 0;
MapMessage message = null;
private boolean jobCompleteFlag = false;
public Exception getJobException() {
return ex;
}
public boolean isJobCompleteFlag() {
return jobCompleteFlag;
}
public void setJobCompleteFlag(boolean jobCompleteFlag) {
this.jobCompleteFlag = jobCompleteFlag;
}
public void setJobException(Exception ex) {
this.ex = ex;
}
public Map getResult() {
return returnMap;
}
public void run() {
QueryProcessorUtil qpUtil = QueryProcessorUtil.getInstance();
boolean allowLargeTextValueConstrainFlag = true;
int queryResultInstanceId = 0;
try {
// if (message != null) {
/*
replyToQueue = (Queue) message.getJMSReplyTo();
String sqlString = message
.getString(QueryManagerBeanUtil.QUERY_MASTER_GENERATED_SQL_PARAM);
String queryInstanceId = message
.getString(QueryManagerBeanUtil.QUERY_INSTANCE_ID_PARAM);
String patientSetId = message
.getString(QueryManagerBeanUtil.QUERY_PATIENT_SET_ID_PARAM);
String xmlRequest = message
.getString(QueryManagerBeanUtil.XML_REQUEST_PARAM);
String dsLookupDomainId = message
.getString(QueryManagerBeanUtil.DS_LOOKUP_DOMAIN_ID);
String dsLookupProjectId = message
.getString(QueryManagerBeanUtil.DS_LOOKUP_PROJECT_ID);
String dsLookupOwnerId = message
.getString(QueryManagerBeanUtil.DS_LOOKUP_OWNER_ID);
*/
log.debug("domain id" + dsLookupDomainId + " "
+ dsLookupProjectId + " " + dsLookupOwnerId
+ " *********************");
DAOFactoryHelper daoFactoryHelper = new DAOFactoryHelper(
dsLookupDomainId, dsLookupProjectId, dsLookupOwnerId);
/*
* DataSourceLookupHelper dataSourceHelper = new
* DataSourceLookupHelper(); DataSourceLookup dsLookup =
* dataSourceHelper.matchDataSource( dsLookupDomainId,
* dsLookupProjectId, dsLookupOwnerId);
*/
IDAOFactory daoFactory = daoFactoryHelper.getDAOFactory();
SetFinderDAOFactory sfDAOFactory = daoFactory
.getSetFinderDAOFactory();
DataSourceLookup dsLookup = sfDAOFactory.getDataSourceLookup();
log.debug("ORIG domain id"
+ sfDAOFactory.getOriginalDataSourceLookup()
.getDomainId()
+ " ORIG "
+ sfDAOFactory.getOriginalDataSourceLookup()
.getProjectPath()
+ " ORIG "
+ sfDAOFactory.getOriginalDataSourceLookup()
.getOwnerId());
try {
AuthrizationHelper authHelper = new AuthrizationHelper(dsLookupDomainId, dsLookupProjectId, dsLookupOwnerId, daoFactory);
authHelper.checkRoleForProtectionLabel("SETFINDER_QRY_WITH_LGTEXT");
} catch(I2B2Exception i2b2Ex) {
allowLargeTextValueConstrainFlag = false;
}
//try {
// check if the status is cancelled
IQueryInstanceDao queryInstanceDao = sfDAOFactory
.getQueryInstanceDAO();
QtQueryInstance queryInstance = queryInstanceDao
.getQueryInstanceByInstanceId(queryInstanceId);
int queryStatusId = queryInstance.getQtQueryStatusType()
.getStatusTypeId();
if (queryStatusId == 9) {
log
.info("Ignoring this query, query status was 'Cancelled'");
//check end date, if not set set now
if (queryInstance.getEndDate() == null)
{
queryInstance.setEndDate(new Date(System
.currentTimeMillis()));
queryInstanceDao.update(queryInstance, false);
}
} else {
// set the query instance batch mode to queue name
queryInstance.setBatchMode(this.callingMDBName);
//queryInstance.setEndDate(new Date(System
// .currentTimeMillis()));
queryInstanceDao.update(queryInstance, false);
log.debug("ExecRunnable my pmXml is" + pmXml);
// process the query request
patientSetId = processQueryRequest(
transactionTimeout, dsLookup, sfDAOFactory,
xmlRequest, sqlString, sessionId,
queryInstanceId, patientSetId,allowLargeTextValueConstrainFlag, pmXml);
log
.debug("QueryExecutorMDB completed processing query instance ["
+ queryInstanceId + "]");
// finally send reply to queue
// sendReply(sessionId, patientSetId, "", replyToQueue);
}
// } catch (CRCTimeOutException daoEx) {
// catch this error and ignore. send general reply message.
// log.error(daoEx.getMessage(), daoEx);
// if (callingMDBName.equalsIgnoreCase(LARGE_QUEUE)) {
// transaction.begin();
// set status to error
// setQueryInstanceStatus(sfDAOFactory, queryInstanceId,
// 10,
// "Could not complete the query in the large queue with transaction timeout "
// + transactionTimeout);
// transaction.commit();
// } else {
// send message to next queue and if the there is no
// next queue then update query instance to error
// tryNextQueue(sfDAOFactory, sessionId, message,
// queryInstanceId);
// }
/*
} catch (I2B2DAOException daoEx) {
log.debug("got an error in ExecRunnable throwing: 1" + daoEx.getMessage() );
if (daoEx instanceof LockedoutException) {
log.debug("Lockedout happend"
+ daoEx.getMessage());
// message.
log.error(daoEx.getMessage(), daoEx);
// finally send reply to queue
// sendReply(sessionId, patientSetId, daoEx.getMessage(),
// replyToQueue);
throw(daoEx);
} else {
// catch this error and ignore. send general reply
// message.
log.debug("got an error in ExecRunnable throwing: 2");
log.error(daoEx.getMessage(), daoEx);
// finally send reply to queue
// sendReply(sessionId, patientSetId, "", replyToQueue);
//MM Dont throw? throw(daoEx);
}
}
*/
//}
// setFinishedFlag(true);
// outputString = reqHandler.execute();
setJobCompleteFlag(true);
log.debug("Finished Running Query, my queryResultId is : " + queryResultInstanceId);
returnMap.put(QueryManagerBeanUtil.QUERY_STATUS_PARAM, "DONE");
returnMap.put(QueryManagerBeanUtil.QT_QUERY_RESULT_INSTANCE_ID_PARAM, queryResultInstanceId);
}
catch (CRCTimeOutException daoEx) {
// catch this error and ignore. send general reply message.
log.error(daoEx.getMessage(), daoEx);
returnMap.put(QueryManagerBeanUtil.QUERY_STATUS_PARAM, "ERROR");
returnMap.put(QueryManagerBeanUtil.QT_QUERY_RESULT_INSTANCE_ID_PARAM, queryResultInstanceId);
setJobCompleteFlag(false);
// if (callingMDBName.equalsIgnoreCase(LARGE_QUEUE)) {
// transaction.begin();
// set status to error
// setQueryInstanceStatus(sfDAOFactory, queryInstanceId,
// 10,
// "Could not complete the query in the large queue with transaction timeout "
// + transactionTimeout);
// transaction.commit();
// } else {
// send message to next queue and if the there is no
// next queue then update query instance to error
// tryNextQueue(sfDAOFactory, sessionId, message,
// queryInstanceId);
// }
} catch (Exception e) {
returnMap.put(QueryManagerBeanUtil.QUERY_STATUS_PARAM, "ERROR");
returnMap.put(QueryManagerBeanUtil.QT_QUERY_RESULT_INSTANCE_ID_PARAM, queryResultInstanceId);
setJobCompleteFlag(true);
//setJobException(e);
log.error("Got an excpetion in ExecRunnable (RUN): " + e.getMessage());
e.printStackTrace();
//throw(e);
}
//notify();
}
/**/
public ExecRunnable(int transactionTimeout,
String callingMDBName, MapMessage message, String sessionId) {
this.transactionTimeout = transactionTimeout;
this.callingMDBName = callingMDBName;
this.message = message;
this.sessionId = sessionId;
}
public ExecRunnable(String sqlString, String queryInstanceId, String patientSetId ,
String xmlRequest, String dsLookupDomainId, String dsLookupProjectId ,
String dsLookupOwnerId, String pmXml ) throws Exception {
this.sqlString = sqlString;
this.queryInstanceId = queryInstanceId;
this.patientSetId = patientSetId;
this.xmlRequest = xmlRequest;
this.dsLookupDomainId = dsLookupDomainId;
this.dsLookupProjectId = dsLookupProjectId;
this.dsLookupOwnerId = dsLookupOwnerId;
this.pmXml = pmXml;
}
public void execute(String sqlString, String queryInstanceId, String patientSetId ,
String xmlRequest, String dsLookupDomainId, String dsLookupProjectId ,
String dsLookupOwnerId ) throws Exception {
this.sqlString = sqlString;
this.queryInstanceId = queryInstanceId;
this.patientSetId = patientSetId;
this.xmlRequest = xmlRequest;
this.dsLookupDomainId = dsLookupDomainId;
this.dsLookupProjectId = dsLookupProjectId;
this.dsLookupOwnerId = dsLookupOwnerId;
}
/*
private void sendReply(String sessionId, String patientSetId,
String message, Queue replyToQueue) throws JMSException,
ServiceLocatorException {
QueueConnection conn = null;
QueueSession session = null;
QueueSender sender = null;
try {
QueryProcessorUtil qpUtil = QueryProcessorUtil.getInstance();
ServiceLocator serviceLocator = ServiceLocator.getInstance();
conn = serviceLocator.getQueueConnectionFactory(
QueryManagerBeanUtil.QUEUE_CONN_FACTORY_NAME)
.createQueueConnection();
session = conn.createQueueSession(false,
javax.jms.Session.AUTO_ACKNOWLEDGE);
MapMessage mapMessage = session.createMapMessage();
// mapMessage.setString("para1", responseXML);
log.debug("message session id " + sessionId);
mapMessage.setJMSCorrelationID(sessionId);
mapMessage.setString(
QueryManagerBeanUtil.QT_QUERY_RESULT_INSTANCE_ID_PARAM,
patientSetId);
mapMessage.setString(QueryManagerBeanUtil.QUERY_STATUS_PARAM,
message);
sender = session.createSender(replyToQueue);
sender.send(mapMessage);
} catch (JMSException jmse) {
throw jmse;
} finally {
QueryManagerBeanUtil qmBeanUtil = new QueryManagerBeanUtil();
// qmBeanUtil.closeAll(sender, null, conn, session);
}
}
private void tryNextQueue(SetFinderDAOFactory sfDAOFactory,
String sessionId, MapMessage msg, String queryInstanceId)
throws JMSException, ServiceLocatorException {
String jmsQueueName = null;
// check which queue is this
if (callingMDBName.equalsIgnoreCase(SMALL_QUEUE)) {
// set status to running
jmsQueueName = QueryManagerBeanUtil.MEDIUM_QUEUE_NAME;
// this.setQueryInstanceStatus(sfDAOFactory, queryInstanceId, 7,
// "Queued in MEDIUM queue");
} else if (callingMDBName.equalsIgnoreCase(MEDIUM_QUEUE)) {
// set status to running
jmsQueueName = QueryManagerBeanUtil.LARGE_QUEUE_NAME;
// this.setQueryInstanceStatus(sfDAOFactory, queryInstanceId, 8,
// "Queued in LARGE queue");
}
if (jmsQueueName != null) {
QueryProcessorUtil qpUtil = QueryProcessorUtil.getInstance();
ServiceLocator serviceLocator = ServiceLocator.getInstance();
QueueConnection conn = serviceLocator.getQueueConnectionFactory(
QueryManagerBeanUtil.QUEUE_CONN_FACTORY_NAME)
.createQueueConnection();
Queue responseQueue = serviceLocator
.getQueue(QueryManagerBeanUtil.RESPONSE_QUEUE_NAME);
Queue sendQueue = serviceLocator.getQueue(jmsQueueName);
QueueSession session = conn.createQueueSession(false,
javax.jms.Session.AUTO_ACKNOWLEDGE);
String id = sessionId;
String selector = "JMSCorrelationID='" + id + "'";
QueueSender sender = session.createSender(sendQueue);
MapMessage mapMsg = session.createMapMessage();
mapMsg.setJMSCorrelationID(id);
mapMsg.setJMSReplyTo(responseQueue);
mapMsg.setString(QueryManagerBeanUtil.XML_REQUEST_PARAM, msg
.getString(QueryManagerBeanUtil.XML_REQUEST_PARAM));
mapMsg
.setString(
QueryManagerBeanUtil.QUERY_MASTER_GENERATED_SQL_PARAM,
msg
.getString(QueryManagerBeanUtil.QUERY_MASTER_GENERATED_SQL_PARAM));
mapMsg.setString(QueryManagerBeanUtil.QUERY_INSTANCE_ID_PARAM, msg
.getString(QueryManagerBeanUtil.QUERY_INSTANCE_ID_PARAM));
mapMsg
.setString(
QueryManagerBeanUtil.QUERY_PATIENT_SET_ID_PARAM,
msg
.getString(QueryManagerBeanUtil.QUERY_PATIENT_SET_ID_PARAM));
mapMsg.setString(QueryManagerBeanUtil.DS_LOOKUP_DOMAIN_ID, msg
.getString(QueryManagerBeanUtil.DS_LOOKUP_DOMAIN_ID));
mapMsg.setString(QueryManagerBeanUtil.DS_LOOKUP_PROJECT_ID, msg
.getString(QueryManagerBeanUtil.DS_LOOKUP_PROJECT_ID));
mapMsg.setString(QueryManagerBeanUtil.DS_LOOKUP_OWNER_ID, msg
.getString(QueryManagerBeanUtil.DS_LOOKUP_OWNER_ID));
sender.send(mapMsg);
}
}
*/
private String processQueryRequest(
int transactionTimeout, DataSourceLookup dsLookup,
SetFinderDAOFactory sfDAOFactory, String xmlRequest,
String sqlString, String sessionId, String queryInstanceId,
String patientSetId, boolean allowLargeTextValueConstrainFlag, String pmXml) throws I2B2DAOException, I2B2Exception, JAXBUtilException {
// QueryRequestDao queryRequestDao = new QueryRequestDao();
// returnedPatientSetId =
// queryRequestDao.getPatientCount(queryRequestXml,
// queryInstanceId,patientSetId);
QueryDefinitionRequestType qdRequestType = getQueryDefinitionRequestType(xmlRequest);
ResultOutputOptionListType resultOutputList = qdRequestType
.getResultOutputList();
DataSource dataSource = ServiceLocator.getInstance()
.getAppServerDataSource(dsLookup.getDataSource());
QueryExecutorDao queryExDao = new QueryExecutorDao(dataSource,
dsLookup, sfDAOFactory.getOriginalDataSourceLookup());
//see if the query will be direct query(no temp table)
boolean queryWithoutTempTableFlag = false;
PsmQryHeaderType psmQryHeaderType = getSetfinderRequestHeaderType(xmlRequest);
if (psmQryHeaderType != null && psmQryHeaderType.getQueryMode() != null) {
String queryMode = psmQryHeaderType.getQueryMode().value();
if (queryMode.equals(QueryModeType.OPTIMIZE_WITHOUT_TEMP_TABLE.value())) {
log.debug("Setfinder query header has [<query_mode>optimize_without_temp_table</query_mode>]");
CheckSkipTempTable checkSkipTempTable = new CheckSkipTempTable();
queryWithoutTempTableFlag = checkSkipTempTable.getSkipTempTable(qdRequestType, resultOutputList);
log.debug("Sefinder query without temp table flag [" + queryWithoutTempTableFlag +"]");
} else {
log.debug("Setfinder query header doesnt have [<query_mode>optimize_without_temp_table</query_mode>]");
}
} else {
log.debug("Setfinder query request header <psmheader> is null");
}
queryExDao.setQueryWithoutTempTableFlag(queryWithoutTempTableFlag);
queryExDao.executeSQL( transactionTimeout, dsLookup,
sfDAOFactory, xmlRequest, sqlString, queryInstanceId,
patientSetId, resultOutputList,allowLargeTextValueConstrainFlag, pmXml);
return patientSetId;
}
private QueryDefinitionRequestType getQueryDefinitionRequestType(
String xmlRequest) throws I2B2Exception {
String queryName = null;
QueryDefinitionType queryDef = null;
JAXBUtil jaxbUtil = CRCJAXBUtil.getJAXBUtil();
JAXBElement jaxbElement = null;
QueryDefinitionRequestType queryDefReqType = null;
try {
jaxbElement = jaxbUtil.unMashallFromString(xmlRequest);
if (jaxbElement == null) {
throw new I2B2Exception(
"null value in after unmarshalling request string ");
}
RequestMessageType requestMessageType = (RequestMessageType) jaxbElement
.getValue();
requestMessageType.getMessageHeader().getSecurity();
requestMessageType.getMessageHeader().getProjectId();
BodyType bodyType = requestMessageType.getMessageBody();
JAXBUnWrapHelper unWrapHelper = new JAXBUnWrapHelper();
queryDefReqType = (QueryDefinitionRequestType) unWrapHelper
.getObjectByClass(bodyType.getAny(),
QueryDefinitionRequestType.class);
} catch (JAXBUtilException e) {
log.error(e.getMessage(), e);
throw new I2B2Exception(e.getMessage(), e);
}
return queryDefReqType;
}
private PsmQryHeaderType getSetfinderRequestHeaderType(
String xmlRequest) throws I2B2Exception {
String queryName = null;
QueryDefinitionType queryDef = null;
JAXBUtil jaxbUtil = CRCJAXBUtil.getJAXBUtil();
JAXBElement jaxbElement = null;
PsmQryHeaderType psmHeaderType = null;
try {
jaxbElement = jaxbUtil.unMashallFromString(xmlRequest);
if (jaxbElement == null) {
throw new I2B2Exception(
"null value in after unmarshalling request string ");
}
RequestMessageType requestMessageType = (RequestMessageType) jaxbElement
.getValue();
BodyType bodyType = requestMessageType.getMessageBody();
JAXBUnWrapHelper unWrapHelper = new JAXBUnWrapHelper();
psmHeaderType = (PsmQryHeaderType) unWrapHelper
.getObjectByClass(bodyType.getAny(),
PsmQryHeaderType.class);
} catch (JAXBUtilException e) {
log.error(e.getMessage(), e);
throw new I2B2Exception(e.getMessage(), e);
}
return psmHeaderType;
}
private void setQueryInstanceStatus(SetFinderDAOFactory sfDAOFactory,
String queryInstanceId, int statusTypeId, String message) throws I2B2DAOException {
IQueryInstanceDao queryInstanceDao = sfDAOFactory.getQueryInstanceDAO();
QtQueryInstance queryInstance = queryInstanceDao
.getQueryInstanceByInstanceId(queryInstanceId);
QtQueryStatusType queryStatusType = new QtQueryStatusType();
queryStatusType.setStatusTypeId(statusTypeId);
queryInstance.setQtQueryStatusType(queryStatusType);
queryInstance.setEndDate(new Date(System.currentTimeMillis()));
queryInstance.setMessage(message);
queryInstance.setBatchMode(callingMDBName);
queryInstanceDao.update(queryInstance, true);
}
/*
private int readTimeoutPropertyValue(String queueType) {
QueryProcessorUtil qpUtil = QueryProcessorUtil.getInstance();
String timeoutStr = "";
int timeoutVal = 0;
try {
if (queueType.equals(SMALL_QUEUE)) {
timeoutStr = qpUtil
.getCRCPropertyValue("edu.harvard.i2b2.crc.jms.small.timeoutsec");
} else if (queueType.equals(MEDIUM_QUEUE)) {
timeoutStr = qpUtil
.getCRCPropertyValue("edu.harvard.i2b2.crc.jms.medium.timeoutsec");
} else if (queueType.equals(LARGE_QUEUE)) {
timeoutStr = qpUtil
.getCRCPropertyValue("edu.harvard.i2b2.crc.jms.large.timeoutsec");
}
timeoutVal = Integer.parseInt(timeoutStr);
} catch (I2B2Exception ex) {
ex.printStackTrace();
}
return timeoutVal;
}
*/
}