Java tutorial
/* * Copyright (c) Mirth Corporation. All rights reserved. * * http://www.mirthcorp.com * * The software in this package is published under the terms of the MPL license a copy of which has * been included with this distribution in the LICENSE.txt file. */ package com.mirth.connect.server.controllers.tests; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Calendar; import java.util.LinkedHashSet; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.concurrent.Executors; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.commons.dbutils.DbUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.math3.util.Precision; import org.apache.ibatis.session.SqlSession; import org.apache.log4j.Logger; import com.mirth.connect.connectors.tests.TestAutoResponder; import com.mirth.connect.connectors.tests.TestDestinationConnector; import com.mirth.connect.connectors.tests.TestResponseTransformer; import com.mirth.connect.connectors.tests.TestSerializer; import com.mirth.connect.connectors.tests.TestSourceConnector; import com.mirth.connect.connectors.vm.VmDispatcherProperties; import com.mirth.connect.connectors.vm.VmReceiverProperties; import com.mirth.connect.donkey.model.channel.DestinationConnectorProperties; import com.mirth.connect.donkey.model.channel.DestinationConnectorPropertiesInterface; import com.mirth.connect.donkey.model.message.ConnectorMessage; import com.mirth.connect.donkey.model.message.ContentType; import com.mirth.connect.donkey.model.message.Message; import com.mirth.connect.donkey.model.message.MessageContent; import com.mirth.connect.donkey.model.message.RawMessage; import com.mirth.connect.donkey.model.message.Status; import com.mirth.connect.donkey.server.Donkey; import com.mirth.connect.donkey.server.channel.Channel; import com.mirth.connect.donkey.server.channel.DestinationChainProvider; import com.mirth.connect.donkey.server.channel.DestinationConnector; import com.mirth.connect.donkey.server.channel.DispatchResult; import com.mirth.connect.donkey.server.channel.FilterTransformerExecutor; import com.mirth.connect.donkey.server.channel.MetaDataReplacer; import com.mirth.connect.donkey.server.channel.ResponseSelector; import com.mirth.connect.donkey.server.channel.ResponseTransformerExecutor; import com.mirth.connect.donkey.server.channel.SourceConnector; import com.mirth.connect.donkey.server.controllers.ChannelController; import com.mirth.connect.donkey.server.data.DonkeyDao; import com.mirth.connect.donkey.server.data.buffered.BufferedDaoFactory; import com.mirth.connect.donkey.server.message.DataType; import com.mirth.connect.donkey.server.queue.ConnectorMessageQueueDataSource; import com.mirth.connect.donkey.server.queue.DestinationQueue; import com.mirth.connect.donkey.util.Serializer; import com.mirth.connect.donkey.util.SerializerProvider; import com.mirth.connect.donkey.util.xstream.XStreamSerializer; import com.mirth.connect.model.Connector; import com.mirth.connect.model.Connector.Mode; import com.mirth.connect.model.Filter; import com.mirth.connect.model.Rule; import com.mirth.connect.model.ServerEventContext; import com.mirth.connect.model.Transformer; import com.mirth.connect.plugins.datatypes.hl7v2.HL7v2DataTypeProperties; import com.mirth.connect.plugins.datatypes.hl7v2.HL7v2ResponseValidationProperties; import com.mirth.connect.plugins.datatypes.hl7v2.HL7v2ResponseValidator; import com.mirth.connect.plugins.datatypes.hl7v2.HL7v2SerializationProperties; import com.mirth.connect.server.Mirth; import com.mirth.connect.server.controllers.ConfigurationController; import com.mirth.connect.server.controllers.ControllerFactory; import com.mirth.connect.server.util.ResourceUtil; public class TestUtils { final public static String TEST_HL7_MESSAGE = "MSH|^~\\&|LABNET|Acme Labs|||20090601105700||ORU^R01|HMCDOOGAL-0088|D|2.2\nPID|1|8890088|8890088^^^72777||McDoogal^Hattie^||19350118|F||2106-3|100 Beach Drive^Apt. 5^Mission Viejo^CA^92691^US^H||(949) 555-0025|||||8890088^^^72|604422825\nPV1|1|R|C3E^C315^B||||2^HIBBARD^JULIUS^|5^ZIMMERMAN^JOE^|9^ZOIDBERG^JOHN^|CAR||||4|||2301^OBRIEN, KEVIN C|I|1783332658^1^1||||||||||||||||||||DISNEY CLINIC||N|||20090514205600\nORC|RE|928272608|056696716^LA||CM||||20090601105600|||| C3E|||^RESULT PERFORMED\nOBR|1|928272608|056696716^LA|1001520^K|||20090601101300|||MLH25|||HEMOLYZED/VP REDRAW|20090601102400||2301^OBRIEN, KEVIN C||||01123085310001100100152023509915823509915800000000101|0000915200932|20090601105600||LAB|F||^^^20090601084100^^ST~^^^^^ST\nOBX|1|NM|1001520^K||5.3|MMOL/L|3.5-5.5||||F|||20090601105600|IIM|IIM"; final public static String CHANNEL_ID = "newtestchannel"; final public static String SERVER_ID = "testserver"; private static Logger logger = Logger.getLogger(TestUtils.class); public static void startMirthServer() throws InterruptedException { startMirthServer(1000); } public static void startMirthServer(int sleepMillis) throws InterruptedException { Executors.newSingleThreadExecutor().execute(new Runnable() { @Override public void run() { new Mirth().run(); } }); while (ConfigurationController.getInstance().getStatus() != ConfigurationController.STATUS_OK) { Thread.sleep(sleepMillis); } } public static void runChannelTest(Channel channel, final String testMessage, final int testSize) throws Exception { channel.deploy(); channel.start(null); SourceConnector sourceConnector = channel.getSourceConnector(); RawMessage rawMessage = new RawMessage(testMessage); for (int i = 0; i < testSize; i++) { DispatchResult dispatchResult = null; try { dispatchResult = sourceConnector.dispatchRawMessage(rawMessage); if (dispatchResult.getChannelException() != null) { throw dispatchResult.getChannelException(); } } finally { sourceConnector.finishDispatch(dispatchResult); } } channel.stop(); channel.undeploy(); } public static com.mirth.connect.model.Channel createTestChannelModel(String channelId, String channelName) { Transformer transformer = new Transformer(); transformer.setInboundDataType("HL7V2"); transformer.setInboundProperties(new HL7v2DataTypeProperties()); transformer.setOutboundDataType("HL7V2"); transformer.setOutboundProperties(new HL7v2DataTypeProperties()); Filter filter = new Filter(); filter.setRules(new ArrayList<Rule>()); Connector sourceConnector = new Connector(); sourceConnector.setEnabled(true); sourceConnector.setMetaDataId(0); sourceConnector.setMode(Mode.SOURCE); sourceConnector.setName("source"); sourceConnector.setProperties(new VmReceiverProperties()); sourceConnector.setTransportName(sourceConnector.getProperties().getName()); sourceConnector.setWaitForPrevious(true); sourceConnector.setTransformer(transformer); sourceConnector.setFilter(filter); transformer = new Transformer(); transformer.setInboundDataType("HL7V2"); transformer.setInboundProperties(new HL7v2DataTypeProperties()); transformer.setOutboundDataType("HL7V2"); transformer.setOutboundProperties(new HL7v2DataTypeProperties()); filter = new Filter(); filter.setRules(new ArrayList<Rule>()); Connector destinationConnector = new Connector(); destinationConnector.setEnabled(true); destinationConnector.setMetaDataId(1); destinationConnector.setMode(Mode.DESTINATION); destinationConnector.setName("destination"); destinationConnector.setProperties(new VmDispatcherProperties()); destinationConnector.setTransportName(destinationConnector.getProperties().getName()); destinationConnector.setTransformer(transformer); destinationConnector.setFilter(filter); transformer = new Transformer(); transformer.setInboundDataType("HL7V2"); transformer.setInboundProperties(new HL7v2DataTypeProperties()); transformer.setOutboundDataType("HL7V2"); transformer.setOutboundProperties(new HL7v2DataTypeProperties()); destinationConnector.setResponseTransformer(transformer); com.mirth.connect.model.Channel channel = new com.mirth.connect.model.Channel(); channel.setId(channelId); channel.setEnabled(true); channel.setLastModified(Calendar.getInstance()); channel.setName(channelName); channel.setRevision(0); channel.setSourceConnector(sourceConnector); channel.addDestination(destinationConnector); return channel; } public static Channel createChannel(String channelId, String serverId, SourceConnector sourceConnector, DestinationConnector destinationConnector) { Channel channel = new Channel(); channel.setChannelId(channelId); channel.setServerId(serverId); channel.setEnabled(true); channel.setSourceConnector(sourceConnector); channel.setPreProcessor(new TestPreProcessor()); channel.setPostProcessor(new TestPostProcessor()); FilterTransformerExecutor filterTransformer = new FilterTransformerExecutor( new DataType("XML", new TestSerializer(), new TestAutoResponder()), new DataType("XML", new TestSerializer(), new TestAutoResponder())); filterTransformer.setFilterTransformer(new TestFilterTransformer()); sourceConnector.setFilterTransformerExecutor(filterTransformer); sourceConnector.setChannelId(channel.getChannelId()); sourceConnector.setChannel(channel); DestinationChainProvider chain = new DestinationChainProvider(); filterTransformer = new FilterTransformerExecutor( new DataType("XML", new TestSerializer(), new TestAutoResponder()), new DataType("XML", new TestSerializer(), new TestAutoResponder())); filterTransformer.setFilterTransformer(new TestFilterTransformer()); destinationConnector.setFilterTransformerExecutor(filterTransformer); chain.addDestination(1, destinationConnector); channel.getDestinationChainProviders().add(chain); destinationConnector.setChannelId(channelId); ResponseTransformerExecutor responseTransformerExecutor = new ResponseTransformerExecutor( new DataType("XML", new TestSerializer(), new TestAutoResponder()), new DataType("XML", new TestSerializer(), new TestAutoResponder())); responseTransformerExecutor.setResponseTransformer(new TestResponseTransformer()); destinationConnector.setResponseTransformerExecutor(responseTransformerExecutor); DestinationConnectorProperties destinationConnectorProperties = ((DestinationConnectorPropertiesInterface) destinationConnector .getConnectorProperties()).getDestinationConnectorProperties(); DestinationQueue queue = new DestinationQueue(destinationConnectorProperties.getThreadAssignmentVariable(), destinationConnectorProperties.getThreadCount(), destinationConnectorProperties.isRegenerateTemplate(), destinationConnector.getSerializer(), destinationConnector.getMessageMaps()); queue.setDataSource(new ConnectorMessageQueueDataSource(channelId, serverId, 1, Status.QUEUED, false, Donkey.getInstance().getDaoFactory())); destinationConnector.setQueue(queue); return channel; } public static Channel createChannel(String channelId, String serverId, boolean respondAfterProcessing, int numChains, int destinationsPerChain) { // create channel Channel channel = new Channel(); channel.setChannelId(channelId); channel.setServerId(serverId); channel.setEnabled(true); channel.setDaoFactory( new BufferedDaoFactory(Donkey.getInstance().getDaoFactory(), new SerializerProvider() { @Override public Serializer getSerializer(Integer metaDataId) { return new XStreamSerializer(); } }, Donkey.getInstance().getStatisticsUpdater())); channel.setPreProcessor(new TestPreProcessor()); channel.setPostProcessor(new TestPostProcessor()); DataType dataType = new DataType("HL7V2", new TestSerializer(), new TestAutoResponder()); // create source connector TestSourceConnector sourceConnector = new TestSourceConnector(); sourceConnector.setChannelId(channel.getChannelId()); sourceConnector.setChannel(channel); sourceConnector.setRespondAfterProcessing(respondAfterProcessing); sourceConnector.setMetaDataReplacer(new MetaDataReplacer()); sourceConnector.setInboundDataType(dataType); FilterTransformerExecutor filterTransformer = new FilterTransformerExecutor(dataType, dataType); filterTransformer.setFilterTransformer(new TestFilterTransformer()); sourceConnector.setFilterTransformerExecutor(filterTransformer); channel.setSourceConnector(sourceConnector); channel.setResponseSelector(new ResponseSelector(sourceConnector.getInboundDataType())); channel.getResponseSelector().setRespondFromName("destination1"); int metaDataId = 1; // create destination chains for (int i = 0; i < numChains; i++) { DestinationChainProvider chain = new DestinationChainProvider(); chain.setChannelId(channelId); channel.getDestinationChainProviders().add(chain); for (int j = 0; j < destinationsPerChain; j++) { TestDestinationConnector testDestinationConnector = new TestDestinationConnector(); testDestinationConnector.setChannelId(channelId); testDestinationConnector.setDestinationName("destination" + metaDataId); testDestinationConnector.setEnabled(true); DestinationConnectorProperties destinationConnectorProperties = ((DestinationConnectorPropertiesInterface) testDestinationConnector .getConnectorProperties()).getDestinationConnectorProperties(); DestinationQueue queue = new DestinationQueue( destinationConnectorProperties.getThreadAssignmentVariable(), destinationConnectorProperties.getThreadCount(), destinationConnectorProperties.isRegenerateTemplate(), testDestinationConnector.getSerializer(), testDestinationConnector.getMessageMaps()); queue.setDataSource(new ConnectorMessageQueueDataSource(channelId, serverId, metaDataId, Status.QUEUED, false, Donkey.getInstance().getDaoFactory())); testDestinationConnector.setQueue(queue); testDestinationConnector.setResponseValidator(new HL7v2ResponseValidator( new HL7v2SerializationProperties(), new HL7v2ResponseValidationProperties())); ResponseTransformerExecutor responseTransformerExecutor = new ResponseTransformerExecutor(dataType, dataType); responseTransformerExecutor.setResponseTransformer(new TestResponseTransformer()); testDestinationConnector.setResponseTransformerExecutor(responseTransformerExecutor); filterTransformer = new FilterTransformerExecutor(dataType, dataType); filterTransformer.setFilterTransformer(new TestFilterTransformer()); testDestinationConnector.setMetaDataReplacer(sourceConnector.getMetaDataReplacer()); testDestinationConnector.setMetaDataColumns(channel.getMetaDataColumns()); testDestinationConnector.setFilterTransformerExecutor(filterTransformer); chain.addDestination(metaDataId++, testDestinationConnector); } } return channel; } public static void deployTestChannel(com.mirth.connect.model.Channel channel) throws Exception { com.mirth.connect.server.controllers.ChannelController.getInstance().updateChannel(channel, ServerEventContext.SYSTEM_USER_EVENT_CONTEXT, true); Set<String> channelIds = new LinkedHashSet<String>(); channelIds.add(channel.getId()); ControllerFactory.getFactory().createEngineController().deployChannels(channelIds, ServerEventContext.SYSTEM_USER_EVENT_CONTEXT, null); } public static Properties getSqlProperties() { PropertiesConfiguration mirthProperties = new PropertiesConfiguration(); try { InputStream is = ResourceUtil.getResourceStream(SqlSession.class, "mirth.properties"); mirthProperties.setDelimiterParsingDisabled(true); mirthProperties.load(is); IOUtils.closeQuietly(is); } catch (Exception e) { e.printStackTrace(); return null; } Properties donkeyProperties = new Properties(); donkeyProperties.setProperty("database.driver", mirthProperties.getString("database.driver")); donkeyProperties.setProperty("database.url", mirthProperties.getString("database.url")); donkeyProperties.setProperty("database.username", mirthProperties.getString("database.username")); if (mirthProperties.containsKey("database.password")) { donkeyProperties.setProperty("database.password", mirthProperties.getString("database.password")); } return donkeyProperties; } public static Connection getConnection() throws Exception { Properties configuration = Donkey.getInstance().getConfiguration().getDonkeyProperties(); String driver = configuration.getProperty("database.driver"); if (driver != null) { Class.forName(driver); } Connection connection = DriverManager.getConnection(configuration.getProperty("database.url"), configuration.getProperty("database.username"), configuration.getProperty("database.password")); connection.setAutoCommit(false); return connection; } public static boolean channelExists(String channelId) throws Exception { boolean exists = false; Connection connection = getConnection(); PreparedStatement statement = connection.prepareStatement("SELECT 1 FROM channels WHERE channel_id = ?"); statement.setString(1, channelId); ResultSet result = statement.executeQuery(); if (result.next()) { exists = true; } result.close(); connection.close(); return exists; } public static String getPerformanceText(String testName, int testSize, long milliseconds) { double seconds = ((double) milliseconds) / 1000.0; return StringUtils.rightPad(testName, 50) + ((int) (testSize / seconds)) + " messages/second"; } public static Message createMessage(RawMessage rawMessage, String channelId, String channelName, String serverId, long messageId) { Message message = new Message(); message.setMessageId(messageId); message.setChannelId(channelId); message.setServerId(serverId); message.setReceivedDate(Calendar.getInstance()); ConnectorMessage sourceMessage = new ConnectorMessage(channelId, channelName, message.getMessageId(), 0, serverId, message.getReceivedDate(), Status.RECEIVED); sourceMessage.setRaw(new MessageContent(channelId, message.getMessageId(), 0, ContentType.RAW, rawMessage.getRawData(), null, false)); if (rawMessage.getSourceMap() != null) { sourceMessage.setSourceMap(rawMessage.getSourceMap()); } message.getConnectorMessages().put(0, sourceMessage); return message; } public static Message createAndStoreNewMessage(RawMessage rawMessage, String channelId, String channelName, String serverId, DonkeyDao dao) { Message message = createMessage(rawMessage, channelId, channelName, serverId, dao.getNextMessageId(channelId)); ConnectorMessage sourceMessage = message.getConnectorMessages().get(0); dao.insertMessage(message); dao.insertConnectorMessage(sourceMessage, true, true); dao.insertMessageContent(sourceMessage.getRaw()); return message; } @SuppressWarnings("unchecked") public static List<Long> getMessageIds(String channelId) throws Exception { return (List<Long>) selectColumn( "SELECT id FROM d_m" + ChannelController.getInstance().getLocalChannelId(channelId)); } public static int getNumMessages(String channelId) throws Exception { return getNumMessages(channelId, false); } public static int getNumMessages(String channelId, boolean onlyCountMessagesWithContent) throws Exception { Connection connection = null; PreparedStatement statement = null; ResultSet result = null; try { long localChannelId = ChannelController.getInstance().getLocalChannelId(channelId); StringBuilder query = new StringBuilder("SELECT COUNT(*) FROM d_m" + localChannelId + " m"); if (onlyCountMessagesWithContent) { query.append(" WHERE EXISTS (SELECT 1 FROM d_mc" + localChannelId + " WHERE message_id = m.id)"); } connection = getConnection(); statement = connection.prepareStatement(query.toString()); result = statement.executeQuery(); result.next(); return result.getInt(1); } finally { close(result); close(statement); close(connection); } } public static void close(Connection connection) { try { if (connection != null && !connection.isClosed()) { connection.rollback(); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } public static void close(Statement statement) { try { DbUtils.close(statement); } catch (SQLException e) { e.printStackTrace(); } } public static void close(PreparedStatement preparedStatement) { try { DbUtils.close(preparedStatement); } catch (SQLException e) { e.printStackTrace(); } } public static void close(ResultSet resultSet) { try { DbUtils.close(resultSet); } catch (SQLException e) { e.printStackTrace(); } } public static void close(DonkeyDao dao) { if (dao != null && !dao.isClosed()) { dao.close(); } } public static void deleteAllMessages(String channelId) throws Exception { DonkeyDao dao = Donkey.getInstance().getDaoFactory().getDao(); try { dao.deleteAllMessages(channelId); dao.commit(); } finally { dao.close(); } fixMessageIdSequence(channelId); } public static void createTestMessages(String channelId, Message templateMessage, int count) throws Exception { DonkeyDao dao = Donkey.getInstance().getDaoFactory().getDao(); try { for (int i = 0; i < count; i++) { insertCompleteMessage(templateMessage, dao); } dao.commit(); } finally { dao.close(); } } public static void createTestMessagesFast(String channelId, String channelName, int power) throws Exception { createTestMessagesFast(channelId, TestUtils.createMessage(new RawMessage(TestUtils.TEST_HL7_MESSAGE), channelId, channelName, "testserver", 1), power); } public static void createTestMessagesFast(String channelId, Message templateMessage, int power) throws Exception { long localChannelId = ChannelController.getInstance().getLocalChannelId(channelId); deleteAllMessages(channelId); createTestMessages(channelId, templateMessage, 1); Connection connection = null; PreparedStatement messageStatement = null; PreparedStatement metaDataStatement = null; PreparedStatement contentStatement = null; long idOffset = templateMessage.getMessageId(); logger.debug("Replicating messages in channel \"" + channelId + "\""); try { connection = getConnection(); messageStatement = connection.prepareStatement("INSERT INTO d_m" + localChannelId + " (id, server_id, received_date, processed) SELECT id + ?, server_id, received_date, processed FROM d_m" + localChannelId); metaDataStatement = connection.prepareStatement("INSERT INTO d_mm" + localChannelId + " (id, server_id, message_id, chain_id, received_date, status, order_id) SELECT id, server_id, message_id + ?, chain_id, received_date, status, order_id FROM d_mm" + localChannelId); contentStatement = connection.prepareStatement("INSERT INTO d_mc" + localChannelId + " (metadata_id, message_id, content_type, content, is_encrypted, data_type) SELECT metadata_id, message_id + ?, content_type, content, is_encrypted, data_type FROM d_mc" + localChannelId); for (int i = 0; i < power; i++) { messageStatement.setLong(1, idOffset); metaDataStatement.setLong(1, idOffset); contentStatement.setLong(1, idOffset); messageStatement.executeUpdate(); metaDataStatement.executeUpdate(); contentStatement.executeUpdate(); idOffset *= 2; connection.commit(); logger.debug("# of messages in channel \"" + channelId + "\" is now " + getNumMessages(channelId)); } } finally { close(messageStatement); close(metaDataStatement); close(contentStatement); close(connection); } fixMessageIdSequence(channelId); logger.debug("Finished replicating messages in channel \"" + channelId + "\""); } public static void fixMessageIdSequence(String channelId) throws Exception { Connection connection = null; long localChannelId = ChannelController.getInstance().getLocalChannelId(channelId); String database = (String) Donkey.getInstance().getConfiguration().getDonkeyProperties().get("database"); Long maxId = null; if (database.equals("derby") || database.equals("mysql") || database.equals("sqlserver")) { Statement statement = null; ResultSet result = null; try { connection = getConnection(); statement = connection.createStatement(); result = statement.executeQuery("SELECT MAX(id) FROM d_m" + localChannelId); result.next(); maxId = result.getLong(1) + 1; close(result); statement.execute("DELETE FROM d_message_sequences WHERE local_channel_id = " + localChannelId); statement.execute( "INSERT INTO d_message_sequences (local_channel_id) VALUES (" + localChannelId + ")"); connection.commit(); } finally { close(result); close(statement); close(connection); } } logger.debug("Message ID sequence updated to: " + maxId); } private static void insertCompleteMessage(Message message, DonkeyDao dao) { dao.insertMessage(message); if (message.isProcessed()) { dao.markAsProcessed(message.getChannelId(), message.getMessageId()); } for (ConnectorMessage connectorMessage : message.getConnectorMessages().values()) { dao.insertConnectorMessage(connectorMessage, true, true); for (ContentType contentType : ContentType.getMessageTypes()) { MessageContent messageContent = connectorMessage.getMessageContent(contentType); if (messageContent != null) { dao.insertMessageContent(messageContent); } } } } public static double getPerSecondRate(long size, long millis, Integer precision) { double rate = ((double) size) / ((double) millis / 1000d); if (precision != null) { rate = Precision.round(rate, 2); } return rate; } public static List<?> selectColumn(String query) { Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { connection = getConnection(); statement = connection.createStatement(); resultSet = statement.executeQuery(query); List<Object> col = new ArrayList<Object>(); while (resultSet.next()) { col.add(resultSet.getObject(1)); } return col; } catch (Exception e) { throw new RuntimeException(e); } finally { DbUtils.closeQuietly(resultSet); DbUtils.closeQuietly(statement); DbUtils.closeQuietly(connection); } } }