package org.wso2.carbon.inbound.endpoint.protocol.hl7.management;
import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.Message;
import ca.uhn.hl7v2.parser.Parser;
import ca.uhn.hl7v2.parser.PipeParser;
import org.apache.http.nio.util.HeapByteBufferAllocator;
import org.apache.log4j.Logger;
import org.apache.synapse.SynapseException;
import org.apache.synapse.inbound.InboundProcessorParams;
import org.apache.synapse.transport.passthru.util.BufferFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.inbound.endpoint.common.AbstractInboundEndpointManager;
import org.wso2.carbon.inbound.endpoint.inboundfactory.InboundRequestProcessorFactoryImpl;
import org.wso2.carbon.inbound.endpoint.protocol.hl7.*;
import org.wso2.carbon.inbound.endpoint.protocol.hl7.core.HL7Processor;
import org.wso2.carbon.inbound.endpoint.protocol.hl7.core.InboundHL7IOReactor;
import org.wso2.carbon.inbound.endpoint.protocol.hl7.core.MLLPConstants;
import org.wso2.carbon.inbound.endpoint.protocol.hl7.util.Axis2HL7Constants;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.HashMap;
import java.util.Map;
/**
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
public class HL7EndpointManager extends AbstractInboundEndpointManager {
private static final Logger log = Logger.getLogger(HL7EndpointManager.class);
private static HL7EndpointManager instance = new HL7EndpointManager();
private HL7EndpointManager() {
super();
}
public static HL7EndpointManager getInstance() {
return instance;
}
@Override
public boolean startListener(int port, String name, InboundProcessorParams params) {
log.info("Starting HL7 Inbound Endpoint on port " + port);
PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
String tenantDomain = carbonContext.getTenantDomain();
if (params.getProperties().getProperty(MLLPConstants.HL7_INBOUND_TENANT_DOMAIN) == null) {
params.getProperties().put(MLLPConstants.HL7_INBOUND_TENANT_DOMAIN, tenantDomain);
}
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put(MLLPConstants.INBOUND_PARAMS, params);
parameters.put(MLLPConstants.INBOUND_HL7_BUFFER_FACTORY,
new BufferFactory(8 * 1024, new HeapByteBufferAllocator(), 1024));
validateParameters(params, parameters);
HL7Processor hl7Processor = new HL7Processor(parameters);
parameters.put(MLLPConstants.HL7_REQ_PROC, hl7Processor);
return InboundHL7IOReactor.bind(port, hl7Processor);
}
@Override
public boolean startEndpoint(int port, String name, InboundProcessorParams params) {
PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
String tenantDomain = carbonContext.getTenantDomain();
params.getProperties().setProperty(MLLPConstants.HL7_INBOUND_TENANT_DOMAIN, tenantDomain);
String epName = dataStore.getListeningEndpointName(port, tenantDomain);
if (epName != null) {
if (epName.equalsIgnoreCase(name)) {
log.info(epName + " Endpoint is already started in port : " + port);
} else {
String msg = "Another endpoint named : " + epName + " is currently using this port: " + port;
log.warn(msg);
throw new SynapseException(msg);
}
} else {
dataStore.registerListeningEndpoint(port, tenantDomain,
InboundRequestProcessorFactoryImpl.Protocols.hl7.toString(), name, params);
return startListener(port, name, params);
}
return false;
}
@Override
public void closeEndpoint(int port) {
PrivilegedCarbonContext cc = PrivilegedCarbonContext.getThreadLocalCarbonContext();
String tenantDomain = cc.getTenantDomain();
dataStore.unregisterListeningEndpoint(port, tenantDomain);
if (!InboundHL7IOReactor.isEndpointRunning(port)) {
log.info("Listener Endpoint is not started");
return ;
} else if (dataStore.isEndpointRegistryEmpty(port)) {
// if no other endpoint is working on this port. close the listening endpoint
InboundHL7IOReactor.unbind(port);
}
}
private void validateParameters(InboundProcessorParams params, Map<String, Object> parameters) {
if (!params.getProperties().getProperty(MLLPConstants.PARAM_HL7_AUTO_ACK).equalsIgnoreCase("true")
&& !params.getProperties().getProperty(MLLPConstants.PARAM_HL7_AUTO_ACK).equalsIgnoreCase("false")) {
log.warn("Parameter inbound.hl7.AutoAck in HL7 inbound " + params.getName() + " is not valid. Default " +
"value of true will be used.");
params.getProperties().setProperty(MLLPConstants.PARAM_HL7_AUTO_ACK, "true");
}
try {
Integer.valueOf(params.getProperties().getProperty(MLLPConstants.PARAM_HL7_TIMEOUT));
} catch (NumberFormatException e) {
log.warn("Parameter inbound.hl7.TimeOut in HL7 inbound " + params.getName() + " is not valid. Default timeout " +
"of " + MLLPConstants.DEFAULT_HL7_TIMEOUT + " milliseconds will be used.");
params.getProperties().setProperty(MLLPConstants.PARAM_HL7_TIMEOUT,
String.valueOf(MLLPConstants.DEFAULT_HL7_TIMEOUT));
}
try {
if (params.getProperties().getProperty(MLLPConstants.PARAM_HL7_PRE_PROC) != null) {
final HL7MessagePreprocessor preProcessor = (HL7MessagePreprocessor) Class.forName(params.getProperties()
.getProperty(MLLPConstants.PARAM_HL7_PRE_PROC)).newInstance();
Parser preProcParser = new PipeParser() {
public Message parse(String message) throws HL7Exception {
message = preProcessor.process(message, Axis2HL7Constants.MessageType.V2X,
Axis2HL7Constants.MessageEncoding.ER7);
return super.parse(message);
}
};
parameters.put(MLLPConstants.HL7_PRE_PROC_PARSER_CLASS, preProcParser);
}
} catch (Exception e) {
log.error("Error creating message preprocessor for HL7 inbound " + params.getName() + ": ", e);
}
try {
if (params.getProperties().getProperty(MLLPConstants.PARAM_HL7_CHARSET) == null) {
params.getProperties().setProperty(MLLPConstants.PARAM_HL7_CHARSET, MLLPConstants.UTF8_CHARSET.displayName());
parameters.put(MLLPConstants.HL7_CHARSET_DECODER, MLLPConstants.UTF8_CHARSET.newDecoder());
} else {
parameters.put(MLLPConstants.HL7_CHARSET_DECODER, Charset
.forName(params.getProperties().getProperty(MLLPConstants.PARAM_HL7_CHARSET)).newDecoder());
}
} catch (UnsupportedCharsetException e) {
parameters.put(MLLPConstants.HL7_CHARSET_DECODER, MLLPConstants.UTF8_CHARSET.newDecoder());
log.error("Unsupported charset '" + params.getProperties()
.getProperty(MLLPConstants.PARAM_HL7_CHARSET) + "' specified in HL7 inbound " + params.getName() +
". Default UTF-8 will be used instead.");
}
if (params.getProperties().getProperty(MLLPConstants.PARAM_HL7_VALIDATE) == null) {
params.getProperties().setProperty(MLLPConstants.PARAM_HL7_VALIDATE, "true");
}
if (params.getProperties().getProperty(MLLPConstants.PARAM_HL7_BUILD_RAW_MESSAGE) == null) {
params.getProperties().setProperty(MLLPConstants.PARAM_HL7_BUILD_RAW_MESSAGE, "false");
} else {
if (!params.getProperties().getProperty(MLLPConstants.PARAM_HL7_BUILD_RAW_MESSAGE).equalsIgnoreCase("true") &&
!params.getProperties().getProperty(MLLPConstants.PARAM_HL7_BUILD_RAW_MESSAGE).equalsIgnoreCase("false")) {
params.getProperties().setProperty(MLLPConstants.PARAM_HL7_BUILD_RAW_MESSAGE, "false");
}
}
if (params.getProperties().getProperty(MLLPConstants.PARAM_HL7_PASS_THROUGH_INVALID_MESSAGES) == null) {
params.getProperties().setProperty(MLLPConstants.PARAM_HL7_PASS_THROUGH_INVALID_MESSAGES, "false");
} else {
if (!params.getProperties().getProperty(MLLPConstants.PARAM_HL7_PASS_THROUGH_INVALID_MESSAGES).equalsIgnoreCase("true") &&
!params.getProperties().getProperty(MLLPConstants.PARAM_HL7_PASS_THROUGH_INVALID_MESSAGES).equalsIgnoreCase("false")) {
params.getProperties().setProperty(MLLPConstants.PARAM_HL7_PASS_THROUGH_INVALID_MESSAGES, "false");
}
}
}
}