/**
*
*/
package hk.hku.cecid.ebms.spa.handler.jms;
import hk.hku.cecid.ebms.pkg.EbxmlMessage;
import hk.hku.cecid.ebms.pkg.MessageHeader;
import hk.hku.cecid.ebms.spa.EbmsProcessor;
import hk.hku.cecid.ebms.spa.EbmsUtility;
import hk.hku.cecid.ebms.spa.handler.MessageServiceHandler;
import hk.hku.cecid.ebms.spa.listener.EbmsRequest;
import hk.hku.cecid.ebms.spa.util.PartnershipDAOHelper;
import hk.hku.cecid.piazza.commons.dao.DAOException;
import hk.hku.cecid.piazza.commons.message.Message;
import hk.hku.cecid.piazza.commons.message.MessageHandler;
import hk.hku.cecid.piazza.commons.util.Generator;
import hk.hku.cecid.piazza.commons.util.Logger;
import java.util.List;
import java.util.Map;
import javax.activation.DataHandler;
/**
* @author aaronwalker
*
*/
public class EbmsMessageHandler implements MessageHandler {
public void onMessage(Message message) {
log().debug("got message:" + message.getSource().toString());
try {
EbmsRequest ebmsRequest = buildEbmsRequest(message);
getMSH().processOutboundMessage(ebmsRequest, null);
} catch (Exception e) {
log().error("Failed to process outbound message: " + e);
log().debug("",e);
throw new RuntimeException(e);
}
}
protected MessageServiceHandler getMSH() {
return MessageServiceHandler.getInstance();
}
private EbmsRequest buildEbmsRequest(Message message) throws Exception {
EbmsRequest request = new EbmsRequest();
//extract delivery info from the message
Map<String,Object> header = message.getHeader();
String cpaId = asString(header,"cpaId");
String conversationId = asString(header,"conversationId");
String serviceType = asString(header, "serviceType");
String service = asString(header, "service");
String action = asString(header,"action");
Integer timeToLiveOffset = asInt(header, "timeToLiveOffset");
String ebxmlMessageId = asString(header,"ebxmlMessageId");
String refToMessageId = asString(header,"refToMessageId");
String [] toPartyIds = asStringArray(header,"toPartyId");
String [] toPartyIdTypes = asStringArray(header, "toPartyType");
String toPartyRole = asString(header, "toPartyRole");
String [] fromPartyIds = asStringArray(header,"fromPartyId");
String [] fromPartyIdTypes = asStringArray(header, "fromPartyType");
String fromPartyRole = asString(header, "fromPartyRole");
String [] payloadContentIds = asStringArray(header,"payload-contentId");
String [] payloadContentTypes = asStringArray(header,"payload-contentType");
//check if there is a valid registered channel for this message
if(!checkValidChannel(cpaId, service, action)) {
throw new RuntimeException("No registered sender channel");
}
//create the ebxml message
EbxmlMessage ebxml = new EbxmlMessage();
MessageHeader ebxmlHeader = ebxml.addMessageHeader();
addFromParty(ebxmlHeader,fromPartyIds,fromPartyIdTypes);
if(fromPartyRole != null && !fromPartyRole.isEmpty()) {
ebxmlHeader.setFromRole(fromPartyRole);
}
addToParty(ebxmlHeader,toPartyIds,toPartyIdTypes);
if(toPartyRole != null && !toPartyRole.isEmpty()) {
ebxmlHeader.setToRole(toPartyRole);
}
//These methods need to be call in this exact order
ebxmlHeader.setCpaId(cpaId);
ebxmlHeader.setConversationId(conversationId);
ebxmlHeader.setService(service);
ebxmlHeader.setAction(action);
if (serviceType != null && !serviceType.equals("")) {
ebxmlHeader.setServiceType(serviceType);
}
if(ebxmlMessageId == null) {
ebxmlMessageId = Generator.generateMessageID();
}
ebxmlHeader.setMessageId(ebxmlMessageId);
log().info("ebXML message id: " + ebxmlMessageId);
if(refToMessageId != null) {
ebxmlHeader.setRefToMessageId(refToMessageId);
}
ebxmlHeader.setTimestamp(EbmsUtility.getCurrentUTCDateTime());
if(timeToLiveOffset != null) {
ebxmlHeader.setTimeToLive(EbmsUtility.applyTimeToLiveOffset(timeToLiveOffset));
}
log().info("Outbound payload received - cpaId: " + cpaId
+ ", messageId: " + ebxmlMessageId
+ ", service: " + service
+ ", serviceType:" + serviceType
+ ", action: " + action
+ ", convId: " + conversationId
+ ", fromPartyId: " + fromPartyIds
+ ", fromPartyType: " + fromPartyIdTypes
+ ", toPartyId: " + toPartyIds
+ ", toPartyType: " + toPartyIdTypes
+ ", refToMessageId: " + refToMessageId
+ ", timeToLiveOffset: " + timeToLiveOffset);
//If no payloadIds then assume the default Payload-0
//If no contentIds then assume text/xml
if(payloadContentIds == null || payloadContentTypes == null) {
attachPayloads(ebxml,message.getPayloads());
} else {
attachPayloads(ebxml,payloadContentIds,payloadContentTypes,message.getPayloads());
}
request.setSource(message);
request.setMessage(ebxml);
return request;
}
protected boolean checkValidChannel(String cpaId, String service, String action) throws DAOException {
return PartnershipDAOHelper.isChannelRegistered(cpaId, service, action);
}
protected Logger log() {
return EbmsProcessor.core.log;
}
private void attachPayloads(EbxmlMessage ebxml, List<byte[]> payloads) throws Exception {
String [] payloadIds = {"Payload-0"};
String [] contentIds = {"text/xml; charset=UTF-8"};
attachPayloads(ebxml,payloadIds,contentIds,payloads);
}
private void attachPayloads(EbxmlMessage ebxml, String [] payloadIds, String [] contentIds, List<byte[]> payloads) throws Exception {
int i=0;
for(byte [] payload:payloads) {
ebxml.addPayloadContainer(new DataHandler(new String(payload),contentIds[i]), payloadIds[i], null);
i++;
}
}
private void addToParty(MessageHeader ebxmlHeader, String[] toPartyIds, String[] toPartyIdTypes) throws Exception {
for(int i=0;i<toPartyIds.length;i++) {
ebxmlHeader.addToPartyId(toPartyIds[i], toPartyIdTypes[i]);
}
}
private void addFromParty(MessageHeader ebxmlHeader, String[] fromPartyIds, String[] fromPartyIdTypes) throws Exception {
for(int i=0;i<fromPartyIds.length;i++) {
ebxmlHeader.addFromPartyId(fromPartyIds[i], fromPartyIdTypes[i]);
}
}
private String[] asStringArray(Map<String, Object> map, String key) {
String value = asString(map, key);
if(value != null) {
return value.split(",");
}
return null;
}
private String asString(Map<String,Object> map, String key) {
Object o = map.get(key);
if(o != null) {
return o.toString();
}
return null;
}
private Integer asInt(Map<String, Object> map, String key) {
Object o = map.get(key);
if(o != null) {
try {
return Integer.parseInt(o.toString());
} catch (NumberFormatException ex) {
log().warn("unable to parse an integer " + key + " from map " + map);
}
}
return null;
}
}