/*
* Copyright(c) 2005 Center for E-Commerce Infrastructure Development, The
* University of Hong Kong (HKU). All Rights Reserved.
*
* This software is licensed under the GNU GENERAL PUBLIC LICENSE Version 2.0 [1]
*
* [1] http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
*/
package hk.hku.cecid.ebms.spa.handler;
import hk.hku.cecid.ebms.pkg.Description;
import hk.hku.cecid.ebms.pkg.EbxmlMessage;
import hk.hku.cecid.ebms.pkg.ErrorList;
import hk.hku.cecid.ebms.pkg.MessageHeader;
import hk.hku.cecid.ebms.pkg.Signature;
import hk.hku.cecid.ebms.pkg.SignatureException;
import hk.hku.cecid.ebms.pkg.SignatureHandler;
import hk.hku.cecid.ebms.pkg.validation.EbxmlMessageValidator;
import hk.hku.cecid.ebms.spa.EbmsProcessor;
import hk.hku.cecid.ebms.spa.EbmsUtility;
import hk.hku.cecid.ebms.spa.dao.MessageDAO;
import hk.hku.cecid.ebms.spa.dao.MessageDVO;
import hk.hku.cecid.ebms.spa.dao.MessageServerDAO;
import hk.hku.cecid.ebms.spa.dao.PartnershipDAO;
import hk.hku.cecid.ebms.spa.dao.PartnershipDVO;
import hk.hku.cecid.ebms.spa.dao.RepositoryDVO;
import hk.hku.cecid.ebms.spa.listener.EbmsRequest;
import hk.hku.cecid.ebms.spa.listener.EbmsResponse;
import hk.hku.cecid.ebms.spa.task.AgreementHandler;
import hk.hku.cecid.piazza.commons.dao.DAOException;
import hk.hku.cecid.piazza.commons.soap.SOAPRequest;
import hk.hku.cecid.piazza.commons.net.HostInfo;
import java.io.ByteArrayInputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.TimeZone;
import javax.servlet.http.HttpServletRequest;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
/**
* @author Donahue Sze
*
* Preferences - Java - Code Style - Code Templates
*/
public class InboundMessageProcessor {
static InboundMessageProcessor inboundMessageProcessor;
static boolean inboundMessageProcessor_initFlag = false;
public static InboundMessageProcessor getInstance() {
if (!inboundMessageProcessor_initFlag) {
inboundMessageProcessor = new InboundMessageProcessor();
inboundMessageProcessor_initFlag = true;
}
return inboundMessageProcessor;
}
private InboundMessageProcessor() {
}
public void processIncomingMessage(EbmsRequest request,
EbmsResponse response) throws MessageServiceHandlerException {
EbxmlMessage ebxmlRequestMessage = request.getMessage();
// Modified by Steve Chan
// To enforce the async empty message response
EbxmlMessage ebxmlResponseMessage = null;
// validation of ebxml message
try {
EbxmlMessageValidator validator = new EbxmlMessageValidator();
validator.validate(ebxmlRequestMessage);
} catch (Exception e) {
EbmsProcessor.core.log.error(
"Incoming message is not a valid ebxml message", e);
ebxmlResponseMessage = processInvalidMessage(ebxmlRequestMessage,
false);
response.setMessage(ebxmlResponseMessage);
return;
}
// message type classification
MessageClassifier messageClassifier = new MessageClassifier(
ebxmlRequestMessage);
String messageType = messageClassifier.getMessageType();
boolean isSync = messageClassifier.isSync();
// validation of partnership
String partnershipId = findPartnershipId(ebxmlRequestMessage);
if (partnershipId == null) {
// unauthorized user
// generate error msg (sync reply)
EbmsProcessor.core.log
.error("Unauthorized message, no partnership is found");
ebxmlResponseMessage = processUnauthorizedMessage(
ebxmlRequestMessage, false);
response.setMessage(ebxmlResponseMessage);
return;
}
EbmsProcessor.core.log.info("Incoming ebxml message received: "
+ ebxmlRequestMessage.getMessageId());
// get content type
String contentType = null;
if (request.getSource() != null) {
if (request.getSource() instanceof SOAPRequest) {
SOAPRequest soapRequest = (SOAPRequest) request.getSource();
if (soapRequest.getSource() instanceof HttpServletRequest) {
HttpServletRequest httpServletRequest = (HttpServletRequest) soapRequest
.getSource();
contentType = httpServletRequest.getHeader("Content-Type");
}
}
}
// check signature & verify it
boolean isVerifySuccess = checkSignature(ebxmlRequestMessage);
if (!isVerifySuccess) {
// store process error message
storeIncomingMessage(ebxmlRequestMessage,
MessageClassifier.MESSAGE_TYPE_PROCESSED_ERROR, contentType);
ebxmlResponseMessage = processVerificationFail(ebxmlRequestMessage,
isSync);
response.setMessage(ebxmlResponseMessage);
return;
}
// Check Agreement
if (MessageServiceHandler.getInstance().isInboundAgreementCheck()) {
EbmsProcessor.core.log
.info("Inbound agreement checking for interop");
if (messageType
.equalsIgnoreCase(MessageClassifier.MESSAGE_TYPE_ORDER)) {
try {
new AgreementHandler(ebxmlRequestMessage,
MessageClassifier.MESSAGE_BOX_INBOX, messageType,
true);
} catch (Exception e) {
// store process error message
storeIncomingMessage(ebxmlRequestMessage,
MessageClassifier.MESSAGE_TYPE_PROCESSED_ERROR,
contentType);
EbmsProcessor.core.log.error(
"Incoming message is violate the agreement", e);
ebxmlResponseMessage = processAgreementViolationMessage(
ebxmlRequestMessage, isSync);
response.setMessage(ebxmlResponseMessage);
return;
}
}
}
// check dup msg
boolean hasReceived = checkDuplicate(ebxmlRequestMessage);
// process dup elimination
if (hasReceived) {
EbmsProcessor.core.log.info("The message has received before: "
+ ebxmlRequestMessage.getMessageId());
if (messageClassifier.isAckRequested()) {
// resend the acknowledgement
ebxmlResponseMessage = processDuplicateAckRequestedMessage(
ebxmlRequestMessage, isSync);
response.setMessage(ebxmlResponseMessage);
} else {
if (messageClassifier.isDupElimination()) {
// generate error message
EbmsProcessor.core.log
.info("Duplicate message received, and ignored: "
+ ebxmlRequestMessage.getMessageId());
} else {
// simply ignore it
EbmsProcessor.core.log
.info("Duplicate message received, and ignored: "
+ ebxmlRequestMessage.getMessageId());
}
}
return;
}
boolean isValidPayload = validateAttachments(ebxmlRequestMessage);
if (!isValidPayload) {
storeIncomingMessage(ebxmlRequestMessage,
MessageClassifier.MESSAGE_TYPE_PROCESSED_ERROR, contentType);
ebxmlResponseMessage = processInvalidAttachmentMessage(
ebxmlRequestMessage, isSync);
response.setMessage(ebxmlResponseMessage);
return;
}
// check time to live
boolean isExpired = checkExpiredMessage(ebxmlRequestMessage);
if (isExpired) {
// store process error message
storeIncomingMessage(ebxmlRequestMessage,
MessageClassifier.MESSAGE_TYPE_PROCESSED_ERROR, contentType);
ebxmlResponseMessage = processExpiredMessage(ebxmlRequestMessage,
isSync);
response.setMessage(ebxmlResponseMessage);
return;
}
// receive error msg
if (messageType.equalsIgnoreCase(MessageClassifier.MESSAGE_TYPE_ERROR)) {
EbmsProcessor.core.log.info("It is an error message: "
+ ebxmlRequestMessage.getMessageId());
ebxmlResponseMessage = processErrorMessage(ebxmlRequestMessage,
isSync, messageType, contentType);
response.setMessage(ebxmlResponseMessage);
return;
}
// receive acknowledgement
if (messageType
.equalsIgnoreCase(MessageClassifier.MESSAGE_TYPE_ACKNOWLEDGEMENT)) {
EbmsProcessor.core.log.info("It is an acknowledgement message: "
+ ebxmlRequestMessage.getMessageId());
ebxmlResponseMessage = processAcknowledgement(ebxmlRequestMessage,
isSync, messageType, contentType);
response.setMessage(ebxmlResponseMessage);
return;
}
// receive ping message
if (messageType.equalsIgnoreCase(MessageClassifier.MESSAGE_TYPE_PING)) {
EbmsProcessor.core.log.info("It is a ping message: "
+ ebxmlRequestMessage.getMessageId());
ebxmlResponseMessage = processPingMessage(ebxmlRequestMessage,
isSync, messageType, contentType);
response.setMessage(ebxmlResponseMessage);
return;
}
// receive pong message
if (messageType.equalsIgnoreCase(MessageClassifier.MESSAGE_TYPE_PONG)) {
EbmsProcessor.core.log.info("It is a pong message: "
+ ebxmlRequestMessage.getMessageId());
ebxmlResponseMessage = processPongMessage(ebxmlRequestMessage,
isSync, messageType, contentType);
response.setMessage(ebxmlResponseMessage);
return;
}
// receive status request message
if (messageType
.equalsIgnoreCase(MessageClassifier.MESSAGE_TYPE_STATUS_REQUEST)) {
EbmsProcessor.core.log.info("It is a status request message: "
+ ebxmlRequestMessage.getMessageId());
ebxmlResponseMessage = processStatusRequestMessage(
ebxmlRequestMessage, isSync, messageType, contentType);
response.setMessage(ebxmlResponseMessage);
return;
}
// receive status response message
if (messageType
.equalsIgnoreCase(MessageClassifier.MESSAGE_TYPE_STATUS_RESPONSE)) {
EbmsProcessor.core.log.info("It is a status response message: "
+ ebxmlRequestMessage.getMessageId());
ebxmlResponseMessage = processStatusResponseMessage(
ebxmlRequestMessage, isSync, messageType, contentType);
response.setMessage(ebxmlResponseMessage);
return;
}
// receive order message
if (messageType.equalsIgnoreCase(MessageClassifier.MESSAGE_TYPE_ORDER)) {
EbmsProcessor.core.log.info("It is an order message: "
+ ebxmlRequestMessage.getMessageId());
ebxmlResponseMessage = processOrderMessage(ebxmlRequestMessage,
isSync, messageClassifier, messageType, contentType);
response.setMessage(ebxmlResponseMessage);
return;
}
}
/**
* @param ebxmlRequestMessage
* @param isSync
* @return
* @throws MessageServiceHandlerException
*/
private EbxmlMessage processAgreementViolationMessage(
EbxmlMessage ebxmlRequestMessage, boolean isSync)
throws MessageServiceHandlerException {
EbxmlMessage ebxmlResponseMessage = null;
try {
// generate error msg
EbxmlMessage responseMessage = SignalMessageGenerator
.generateErrorMessage(ebxmlRequestMessage,
ErrorList.CODE_INCONSISTENT,
ErrorList.SEVERITY_ERROR, "Agreement violation",
null);
if (isSync) {
ebxmlResponseMessage = responseMessage;
storeOutgoingMessage(ebxmlResponseMessage);
} else {
sendAsyncMessage(responseMessage);
}
} catch (SOAPException e) {
EbmsProcessor.core.log
.error("Cannot generate error message in processing agreement violation message");
throw new MessageServiceHandlerException(
"Cannot generate error message in processing agreement violation message",
e);
}
return ebxmlResponseMessage;
}
/**
* @throws MessageServiceHandlerException
*
*/
private EbxmlMessage processInvalidMessage(
EbxmlMessage ebxmlRequestMessage, boolean isSync)
throws MessageServiceHandlerException {
EbxmlMessage ebxmlResponseMessage = null;
// generate error msg (sync reply)
try {
// generate error msg
EbxmlMessage responseMessage = SignalMessageGenerator
.generateErrorMessage(ebxmlRequestMessage,
ErrorList.CODE_INCONSISTENT,
ErrorList.SEVERITY_ERROR,
"It is not a valid ebxml message", null);
ebxmlResponseMessage = responseMessage;
storeOutgoingMessage(ebxmlResponseMessage);
} catch (SOAPException e) {
EbmsProcessor.core.log
.error("Cannot generate error message in processing invalid message");
throw new MessageServiceHandlerException(
"Cannot generate error message in processing invalid message",
e);
}
return ebxmlResponseMessage;
}
/**
* @param ebxmlRequestMessage
* @param ebxmlResponseMessage
* @return
* @throws MessageServiceHandlerException
*/
private EbxmlMessage processUnauthorizedMessage(
EbxmlMessage ebxmlRequestMessage, boolean isSync)
throws MessageServiceHandlerException {
EbxmlMessage ebxmlResponseMessage = null;
// generate error msg (sync reply)
try {
// generate error msg
EbxmlMessage responseMessage = SignalMessageGenerator
.generateErrorMessage(ebxmlRequestMessage,
ErrorList.CODE_SECURITY_FAILURE,
ErrorList.SEVERITY_ERROR, "Unauthorized Msg", null);
ebxmlResponseMessage = responseMessage;
storeOutgoingMessage(ebxmlResponseMessage);
} catch (SOAPException e) {
EbmsProcessor.core.log
.error("Cannot generate error message in processing unauthorized message");
throw new MessageServiceHandlerException(
"Cannot generate error message in processing unauthorized message",
e);
}
return ebxmlResponseMessage;
}
/**
* @param ebxmlRequestMessage
* @param ebxmlResponseMessage
* @return
* @throws MessageServiceHandlerException
*/
private EbxmlMessage processVerificationFail(
EbxmlMessage ebxmlRequestMessage, boolean isSync)
throws MessageServiceHandlerException {
EbxmlMessage ebxmlResponseMessage = null;
try {
// generate error msg
EbxmlMessage responseMessage = SignalMessageGenerator
.generateErrorMessage(ebxmlRequestMessage,
ErrorList.CODE_SECURITY_FAILURE,
ErrorList.SEVERITY_ERROR, "Security Checks Failed",
null);
if (isSync) {
ebxmlResponseMessage = responseMessage;
storeOutgoingMessage(ebxmlResponseMessage);
} else {
sendAsyncMessage(responseMessage);
}
} catch (SOAPException e) {
EbmsProcessor.core.log
.error("Cannot generate error message in processing unverified message");
throw new MessageServiceHandlerException(
"Cannot generate error message in processing unverified message",
e);
}
return ebxmlResponseMessage;
}
/**
* @param ebxmlRequestMessage
* @param ebxmlResponseMessage
* @throws MessageServiceHandlerException
*/
private EbxmlMessage processDuplicateAckRequestedMessage(
EbxmlMessage ebxmlRequestMessage, boolean isSync)
throws MessageServiceHandlerException {
EbxmlMessage ebxmlResponseMessage = null;
// find the original acknowledgement and resend
try {
MessageDAO messageDAO = (MessageDAO) EbmsProcessor.core.dao
.createDAO(MessageDAO.class);
MessageDVO messageDVO = (MessageDVO) messageDAO.createDVO();
messageDVO.setRefToMessageId(ebxmlRequestMessage.getMessageId());
messageDVO.setMessageBox(MessageClassifier.MESSAGE_BOX_OUTBOX);
messageDVO
.setMessageType(MessageClassifier.MESSAGE_TYPE_ACKNOWLEDGEMENT);
if (messageDAO.findRefToMessage(messageDVO)) {
if (isSync) {
// find the ack in repository and send directly
EbmsProcessor.core.log
.info("Previous acknowledgement found ("
+ messageDVO.getMessageId()
+ ") and reply synchronously for message: "
+ ebxmlRequestMessage.getMessageId());
try {
ebxmlResponseMessage = EbxmlMessageDAOConvertor
.getEbxmlMessage(messageDVO.getMessageId(),
MessageClassifier.MESSAGE_BOX_OUTBOX);
} catch (Exception e) {
EbmsProcessor.core.log
.error("Cannot reconstruct the ebxml message from repository: "
+ messageDVO.getMessageId());
throw new MessageServiceHandlerException(
"Cannot reconstruct the ebxml message from repository: "
+ messageDVO.getMessageId(), e);
}
} else {
// set status to pending, it will resend again
EbmsProcessor.core.log
.info("Previous acknowledgement found ("
+ messageDVO.getMessageId()
+ ") and reply asynchronously for message: "
+ ebxmlRequestMessage.getMessageId());
messageDVO
.setStatus(MessageClassifier.INTERNAL_STATUS_PENDING);
messageDAO.updateMessage(messageDVO);
}
} else {
// acknowledgement missing (internal error) or
// the acknowledgement is generating
EbmsProcessor.core.log
.error("Acknowldegement missed. Internal server error or the acknowledgement is generating for message: "
+ ebxmlRequestMessage.getMessageId());
throw new MessageServiceHandlerException(
"Acknowldegement missed. Internal server error or the acknowledgement is generating for message: "
+ ebxmlRequestMessage.getMessageId());
}
} catch (DAOException e) {
EbmsProcessor.core.log.error(
"Error in processing duplicate acknowledgement requested message for message: "
+ ebxmlRequestMessage.getMessageId(), e);
throw new MessageServiceHandlerException(
"Error in processing duplicate acknowledgement requested message for message: "
+ ebxmlRequestMessage.getMessageId(), e);
}
return ebxmlResponseMessage;
}
private boolean validateAttachments(EbxmlMessage requestMessage) {
SOAPMessage msg = requestMessage.getSOAPMessage();
Iterator<AttachmentPart> it = msg.getAttachments();
while (it.hasNext()) {
try {
validateAttachment(it.next());
} catch (InvalidAttachmentException e) {
EbmsProcessor.core.log.warn(e);
return false;
} catch (SOAPException e) {
EbmsProcessor.core.log.error(e);
}
}
return true;
}
private void validateAttachment(AttachmentPart attachment)
throws InvalidAttachmentException, SOAPException {
if (EbmsProcessor.getValidator() != null) {
EbmsProcessor.getValidator().validate(attachment);
}
}
/**
* @param ebxmlRequestMessage
* @return
* @throws MessageServiceHandlerException
*/
private boolean checkExpiredMessage(EbxmlMessage ebxmlRequestMessage)
throws MessageServiceHandlerException {
String ttlString = ebxmlRequestMessage.getTimeToLive();
if (ttlString != null) {
try {
Calendar ebxmlCal;
try {
ebxmlCal = EbmsUtility.UTC2Calendar(ttlString);
} catch (Exception ex) {
ebxmlCal = EbmsUtility.GMT2Calender(ttlString);
}
// Transformation System Clock calendar to sender GMT.
Calendar sysTzCal = Calendar.getInstance(TimeZone.getDefault());
return ebxmlCal.getTime().before(sysTzCal.getTime());
} catch (Exception e) {
EbmsProcessor.core.log.info(
"Cannot convert time to live for message: "
+ ebxmlRequestMessage.getMessageId()
+ " with format: " + ttlString, e);
throw new MessageServiceHandlerException(
"Cannot convert time to live for message: "
+ ebxmlRequestMessage.getMessageId()
+ " with format: " + ttlString, e);
}
}
return false;
}
private EbxmlMessage processInvalidAttachmentMessage(
EbxmlMessage ebxmlRequestMessage, boolean isSync)
throws MessageServiceHandlerException {
EbxmlMessage ebxmlResponseMessage = null;
try {
EbxmlMessage errorMessage = SignalMessageGenerator
.generateErrorMessage(ebxmlRequestMessage,
ErrorList.CODE_MIME_PROBLEM,
ErrorList.SEVERITY_ERROR,
"Invalid message attachment", null);
if (isSync) {
ebxmlResponseMessage = errorMessage;
storeOutgoingMessage(ebxmlResponseMessage);
} else {
sendAsyncMessage(errorMessage);
}
String messageId = ebxmlRequestMessage.getMessageId();
if(messageId != null) {
updateMessageStatus(messageId,
MessageClassifier.MESSAGE_BOX_INBOX,
MessageClassifier.INTERNAL_STATUS_PROCESSED_ERROR,
"Invalid attachment");
}
} catch (Exception e) {
EbmsProcessor.core.log
.error("Cannot generate error msg in processing invalid attachment message: "
+ ebxmlRequestMessage.getMessageId() + " " + e.getMessage());
throw new MessageServiceHandlerException(
"Cannot generate error msg in processing invalid attachment message: "
+ ebxmlRequestMessage.getMessageId(), e);
}
return ebxmlResponseMessage;
}
/**
* @param ebxmlRequestMessage
* @return
* @throws MessageServiceHandlerException
*/
private EbxmlMessage processExpiredMessage(
EbxmlMessage ebxmlRequestMessage, boolean isSync)
throws MessageServiceHandlerException {
EbxmlMessage ebxmlResponseMessage = null;
try {
EbxmlMessage errorMessage = SignalMessageGenerator
.generateErrorMessage(ebxmlRequestMessage,
ErrorList.CODE_TIME_TO_LIVE_EXPIRED,
ErrorList.SEVERITY_ERROR,
"TimeToLive value expired", null);
if (isSync) {
ebxmlResponseMessage = errorMessage;
storeOutgoingMessage(ebxmlResponseMessage);
} else {
sendAsyncMessage(errorMessage);
}
String messageId = ebxmlRequestMessage.getMessageId();
if(messageId != null) {
updateMessageStatus(messageId,
MessageClassifier.MESSAGE_BOX_INBOX,
MessageClassifier.INTERNAL_STATUS_PROCESSED_ERROR,
"TimeToLive value expired");
}
} catch (Exception e) {
EbmsProcessor.core.log
.error("Cannot generate error msg in processing expired message: "
+ ebxmlRequestMessage.getMessageId() + " " + e.getMessage());
throw new MessageServiceHandlerException(
"Cannot generate error msg in processing expired message: "
+ ebxmlRequestMessage.getMessageId(), e);
}
return ebxmlResponseMessage;
}
/**
* @param ebxmlRequestMessage
* @return
* @throws MessageServiceHandlerException
*/
private EbxmlMessage processStatusResponseMessage(
EbxmlMessage ebxmlRequestMessage, boolean isSync,
String messageType, String contentType)
throws MessageServiceHandlerException {
EbxmlMessage ebxmlResponseMessage = null;
boolean hasRefMessageId = checkRefToMessage(ebxmlRequestMessage);
if (hasRefMessageId) {
// store the response msg in repository
storeIncomingMessage(ebxmlRequestMessage, messageType, contentType);
} else {
EbmsProcessor.core.log.error("Cannot find the ref to message: "
+ ebxmlRequestMessage.getMessageId());
// store process error message
storeIncomingMessage(ebxmlRequestMessage,
MessageClassifier.MESSAGE_TYPE_PROCESSED_ERROR, contentType);
// generate error msg
EbxmlMessage responseMessage;
try {
responseMessage = SignalMessageGenerator.generateErrorMessage(
ebxmlRequestMessage,
ErrorList.CODE_VALUE_NOT_RECOGNIZED,
ErrorList.SEVERITY_ERROR, "Unknown Ref To Message Id",
null);
} catch (SOAPException e) {
EbmsProcessor.core.log
.error("Cannot generate error msg in processing unknown status response message: "
+ ebxmlRequestMessage.getMessageId());
throw new MessageServiceHandlerException(
"Cannot generate error msg in processing unknown status response message: "
+ ebxmlRequestMessage.getMessageId(), e);
}
if (isSync) {
ebxmlResponseMessage = responseMessage;
storeOutgoingMessage(ebxmlResponseMessage);
} else {
sendAsyncMessage(responseMessage);
}
}
return ebxmlResponseMessage;
}
/**
* @param ebxmlRequestMessage
* @return
* @throws MessageServiceHandlerException
*/
private EbxmlMessage processStatusRequestMessage(
EbxmlMessage ebxmlRequestMessage, boolean isSync,
String messageType, String contentType)
throws MessageServiceHandlerException {
// store the request message in repository
storeIncomingMessage(ebxmlRequestMessage, messageType, contentType);
EbxmlMessage ebxmlResponseMessage = null;
try {
MessageDAO messageDAO = (MessageDAO) EbmsProcessor.core.dao
.createDAO(MessageDAO.class);
MessageDVO messageDVO = (MessageDVO) messageDAO.createDVO();
messageDVO.setMessageId(ebxmlRequestMessage.getMessageHeader()
.getRefToMessageId());
messageDVO.setMessageBox(MessageClassifier.MESSAGE_BOX_INBOX);
EbxmlMessage responseMessage = null;
Date timestamp = new Date();
String status = new String();
// map the message status obey specification
if (messageDAO.findMessage(messageDVO)) {
if (messageDVO.getStatus().equals(
MessageClassifier.INTERNAL_STATUS_PENDING)
|| messageDVO.getStatus().equals(
MessageClassifier.INTERNAL_STATUS_PROCESSED)) {
status = MessageClassifier.STATUS_RECEIVED;
} else if (messageDVO.getStatus().equals(
MessageClassifier.INTERNAL_STATUS_DELIVERED)
|| messageDVO
.getStatus()
.equals(MessageClassifier.INTERNAL_STATUS_PROCESSED_ERROR)) {
status = MessageClassifier.STATUS_PROCESSED;
}
timestamp = messageDVO.getTimeStamp();
} else {
status = MessageClassifier.STATUS_NOT_RECOGNIZED;
}
responseMessage = SignalMessageGenerator
.generateStatusResponseMessage(ebxmlRequestMessage, status,
timestamp);
if (isSync) {
ebxmlResponseMessage = responseMessage;
storeOutgoingMessage(ebxmlResponseMessage);
} else {
sendAsyncMessage(responseMessage);
}
} catch (Exception e) {
EbmsProcessor.core.log
.error("Cannot generate status response message: "
+ ebxmlRequestMessage.getMessageId());
throw new MessageServiceHandlerException(
"Cannot generate status response message: "
+ ebxmlRequestMessage.getMessageId(), e);
}
return ebxmlResponseMessage;
}
/**
* @param ebxmlRequestMessage
* @return
* @throws MessageServiceHandlerException
*/
private EbxmlMessage processPongMessage(EbxmlMessage ebxmlRequestMessage,
boolean isSync, String messageType, String contentType)
throws MessageServiceHandlerException {
EbxmlMessage ebxmlResponseMessage = null;
boolean hasRefMessageId = checkRefToMessage(ebxmlRequestMessage);
if (hasRefMessageId) {
// store the pong msg in repository
storeIncomingMessage(ebxmlRequestMessage, messageType, contentType);
updatePingRefMessage(ebxmlRequestMessage);
} else {
EbmsProcessor.core.log.error("Cannot find the ref to message: : "
+ ebxmlRequestMessage.getMessageId());
// store process error message
storeIncomingMessage(ebxmlRequestMessage,
MessageClassifier.MESSAGE_TYPE_PROCESSED_ERROR, contentType);
// generate error msg
EbxmlMessage responseMessage;
try {
responseMessage = SignalMessageGenerator.generateErrorMessage(
ebxmlRequestMessage,
ErrorList.CODE_VALUE_NOT_RECOGNIZED,
ErrorList.SEVERITY_ERROR, "Unknown Ref To Message Id",
null);
} catch (SOAPException e) {
EbmsProcessor.core.log
.error("Cannot generate error msg in processing invalid pong message: "
+ ebxmlRequestMessage.getMessageId());
throw new MessageServiceHandlerException(
"Cannot generate error msg in processing invalid pong message: "
+ ebxmlRequestMessage.getMessageId(), e);
}
if (isSync) {
ebxmlResponseMessage = responseMessage;
storeOutgoingMessage(ebxmlResponseMessage);
} else {
sendAsyncMessage(responseMessage);
}
}
return ebxmlResponseMessage;
}
private void updatePingRefMessage(EbxmlMessage ebxmlRequestMessage)
throws MessageServiceHandlerException {
// Try to query the Ping message corresponding to this Pong message.
try {
MessageHeader header = ebxmlRequestMessage.getMessageHeader();
if (header != null && header.getRefToMessageId() != null) {
String refMsgId = header.getRefToMessageId();
MessageDAO msgDAO = (MessageDAO) EbmsProcessor.core.dao
.createDAO(MessageDAO.class);
MessageDVO refToMsgDVO = (MessageDVO) msgDAO.createDVO();
refToMsgDVO.setMessageId(refMsgId);
refToMsgDVO.setMessageBox(MessageClassifier.MESSAGE_BOX_OUTBOX);
boolean hasRefMessageId = msgDAO.findMessage(refToMsgDVO);
if (hasRefMessageId) {
if (!refToMsgDVO.getStatus().equalsIgnoreCase(
MessageClassifier.INTERNAL_STATUS_DELIVERY_FAILURE)) {
// If it is failed already..don't mark it as deliveried
// it is because it is timeout failure
EbmsProcessor.core.log.info("Reliable message ("
+ refToMsgDVO.getMessageId()
+ ") - pong received with message id: "
+ ebxmlRequestMessage.getMessageId());
refToMsgDVO
.setStatus(MessageClassifier.INTERNAL_STATUS_PROCESSED);
refToMsgDVO.setStatusDescription("Pong received");
refToMsgDVO.setTimeoutTimestamp(null);
msgDAO.updateMessage(refToMsgDVO);
} else {
EbmsProcessor.core.log.info("Reliable message ("
+ refToMsgDVO.getMessageId()
+ ") - has been timed-out already");
}
}
}
} catch (DAOException ex) {
EbmsProcessor.core.log
.error("Cannot update ping msg in processing invalid pong message: "
+ ebxmlRequestMessage.getMessageId() + " " + ex);
throw new MessageServiceHandlerException(
"Cannot update ping msg in processing invalid pong message: "
+ ebxmlRequestMessage.getMessageId(), ex);
}
}
private void updateMessageStatus(String messageId, String messageBox, String status, String description) throws DAOException {
MessageDAO msgDAO = (MessageDAO) EbmsProcessor.core.dao.createDAO(MessageDAO.class);
MessageDVO msgDVO = (MessageDVO) msgDAO.createDVO();
msgDVO.setMessageId(messageId);
msgDVO.setMessageBox(messageBox);
boolean exists = msgDAO.findMessage(msgDVO);
if(exists) {
if (!msgDVO.getStatus().equalsIgnoreCase(
MessageClassifier.INTERNAL_STATUS_DELIVERY_FAILURE)) {
msgDVO.setStatus(status);
msgDVO.setStatusDescription(description);
msgDAO.updateMessage(msgDVO);
}
}
}
/**
* @param ebxmlRequestMessage
* @return
* @throws MessageServiceHandlerException
*/
private EbxmlMessage processPingMessage(EbxmlMessage ebxmlRequestMessage,
boolean isSync, String messageType, String contentType)
throws MessageServiceHandlerException {
// store the ping msg in repository
storeIncomingMessage(ebxmlRequestMessage, messageType, contentType);
EbxmlMessage ebxmlResponseMessage = null;
try {
EbxmlMessage responseMessage = SignalMessageGenerator
.generatePongMessage(ebxmlRequestMessage);
if (isSync) {
ebxmlResponseMessage = responseMessage;
storeOutgoingMessage(ebxmlResponseMessage);
} else {
sendAsyncMessage(responseMessage);
}
} catch (SOAPException e) {
EbmsProcessor.core.log.error("Cannot generate pong message: "
+ ebxmlRequestMessage.getMessageId());
throw new MessageServiceHandlerException(
"Cannot generate pong message: "
+ ebxmlRequestMessage.getMessageId(), e);
}
return ebxmlResponseMessage;
}
/**
* Process the incoming <code>EbXML Acknowledgment Message</code>.
*
* @param ebxmlRequestMessage
* The dispatched incoming <code>EbXML Message</code>.
* @param isSync
* Whether the <code>EbXML Response message</code> returns in
* HTTP/SOAP response or different HTTP/SOAP connection.
* @param messageType
* the value equal to
* MessageClassifier.MESSAGE_TYPE_ACKNOWLEDGEMENT.
* @param contentType
*
* @return return Null if <code>isSync</code> is set to false. otherwise
* return the <code>EbXML Response Message</code>.
*
* @throws MessageServiceHandlerException
* When unable to generate the <code>EbXML error message</code>
*/
private EbxmlMessage processAcknowledgement(
EbxmlMessage ebxmlRequestMessage, boolean isSync,
String messageType, String contentType)
throws MessageServiceHandlerException {
// Since H20 01062007, the checkRefToMessage has been inlined for new
// handling in acknowledgment.
EbxmlMessage ebxmlResponseMessage = null;
String ackID = ebxmlRequestMessage.getMessageId();
MessageDAO msgDAO = null;
MessageDVO refToMsgDVO = null;
boolean hasRefMessageId = false;
try {
// Try to query the ORDER message corresponding to this ACK message.
if (ebxmlRequestMessage.getAcknowledgment() != null
&& ebxmlRequestMessage.getAcknowledgment()
.getRefToMessageId() != null) {
msgDAO = (MessageDAO) EbmsProcessor.core.dao
.createDAO(MessageDAO.class);
refToMsgDVO = (MessageDVO) msgDAO.createDVO();
refToMsgDVO.setMessageId(ebxmlRequestMessage
.getAcknowledgment().getRefToMessageId());
refToMsgDVO.setMessageBox(MessageClassifier.MESSAGE_BOX_OUTBOX);
hasRefMessageId = msgDAO.findMessage(refToMsgDVO);
}
// If the corresponding ORDER message is found, Update the message
// status if
// it's acknowledgement or error is received.
if (hasRefMessageId) {
if (ebxmlRequestMessage.getAcknowledgment() != null) {
if (!refToMsgDVO.getStatus().equalsIgnoreCase(
MessageClassifier.INTERNAL_STATUS_DELIVERY_FAILURE)) {
// If it is failed already..don't mark it as deliveried
// it is because it is timeout failure
EbmsProcessor.core.log
.info("Reliable message ("
+ refToMsgDVO.getMessageId()
+ ") - acknowledgement received with message id: "
+ ackID);
refToMsgDVO
.setStatus(MessageClassifier.INTERNAL_STATUS_PROCESSED);
refToMsgDVO
.setStatusDescription("Acknowledgement is received");
refToMsgDVO.setTimeoutTimestamp(null);
msgDAO.updateMessage(refToMsgDVO);
} else {
EbmsProcessor.core.log.info("Reliable message ("
+ refToMsgDVO.getMessageId()
+ ") - has been timed-out already");
}
} else if (ebxmlRequestMessage.getErrorList() != null) {
EbmsProcessor.core.log.info("Reliable message ("
+ refToMsgDVO.getMessageId()
+ ") - error message received with message id: "
+ ackID);
refToMsgDVO
.setStatus(MessageClassifier.INTERNAL_STATUS_PROCESSED_ERROR);
refToMsgDVO.setTimeoutTimestamp(null);
StringBuffer sb = new StringBuffer();
Iterator i = ebxmlRequestMessage.getErrorList().getErrors();
while (i.hasNext()) {
ErrorList.Error error = (ErrorList.Error) i.next();
Description description = error.getDescription();
sb.append(error.getErrorCode() + ": "
+ description.getDescription());
}
refToMsgDVO.setStatusDescription(sb.toString());
msgDAO.updateMessage(refToMsgDVO);
}
// Store the ACK / ERROR in persistence storage.
storeIncomingMessage(ebxmlRequestMessage, messageType,
contentType);
// Clear the ORDER message in Outbox.
MessageServerDAO msgServerDAO = (MessageServerDAO) EbmsProcessor.core.dao
.createDAO(MessageServerDAO.class);
msgServerDAO.clearMessage(refToMsgDVO);
// If the corresponding ORDER message isn't found, Create an
// error message
// and send back to recipient.
} else {
EbmsProcessor.core.log.error("Cannot find the ref to message: "
+ ackID);
// Store processed error message
storeIncomingMessage(ebxmlRequestMessage,
MessageClassifier.MESSAGE_TYPE_PROCESSED_ERROR,
contentType);
// Generate error message
EbxmlMessage responseMessage;
try {
responseMessage = SignalMessageGenerator
.generateErrorMessage(ebxmlRequestMessage,
ErrorList.CODE_VALUE_NOT_RECOGNIZED,
ErrorList.SEVERITY_ERROR,
"Unknown Ref To Message Id", null);
} catch (SOAPException se) {
String detail = "Cannont generate error message in processing acknolwedgment message: "
+ ackID;
EbmsProcessor.core.log.error(detail);
throw new MessageServiceHandlerException(detail, se);
}
// Send back the error message whether using same connection
// (sync | async)
if (isSync) {
ebxmlResponseMessage = responseMessage;
storeOutgoingMessage(ebxmlResponseMessage);
} else {
sendAsyncMessage(responseMessage);
}
}
} catch (DAOException daoe) {
String detail = "Error in checking the reference to message: "
+ ackID;
EbmsProcessor.core.log.error(detail, daoe);
throw new MessageServiceHandlerException(detail, daoe);
}
return ebxmlResponseMessage;
}
/**
* @param ebxmlRequestMessage
* @return
* @throws MessageServiceHandlerException
*/
private EbxmlMessage processErrorMessage(EbxmlMessage ebxmlRequestMessage,
boolean isSync, String messageType, String contentType)
throws MessageServiceHandlerException {
EbxmlMessage ebxmlResponseMessage = null;
boolean hasRefMessageId = checkRefToMessage(ebxmlRequestMessage);
if (hasRefMessageId) {
// store the error message in repository
storeIncomingMessage(ebxmlRequestMessage, messageType, contentType);
} else {
EbmsProcessor.core.log.error("Cannot find the ref to message: : "
+ ebxmlRequestMessage.getMessageId());
// store process error message
storeIncomingMessage(ebxmlRequestMessage,
MessageClassifier.MESSAGE_TYPE_PROCESSED_ERROR, contentType);
}
return ebxmlResponseMessage;
}
/**
* @param ebxmlRequestMessage
* @return
* @throws MessageServiceHandlerException
* @throws SignatureException
*/
private EbxmlMessage processOrderMessage(EbxmlMessage ebxmlRequestMessage,
boolean isSync, MessageClassifier messageClassifier,
String messageType, String contentType)
throws MessageServiceHandlerException {
EbxmlMessage ebxmlResponseMessage = null;
if (messageClassifier.isMessageOrder()) {
ebxmlResponseMessage = processMessageOrderMessage(
ebxmlRequestMessage, isSync, messageClassifier,
messageType, contentType);
} else if (messageClassifier.isAckRequested()) {
// store the ack request message in repository
storeIncomingMessage(ebxmlRequestMessage, messageType, contentType);
try {
EbxmlMessage responseMessage = SignalMessageGenerator
.generateAcknowledgment(ebxmlRequestMessage);
if (ebxmlRequestMessage.getAckRequested().getSigned()) {
EbmsProcessor.core.log.info("Sign the acknowledgement ("
+ responseMessage.getMessageId()
+ ") for message: "
+ ebxmlRequestMessage.getMessageId());
signAcknowledgement(responseMessage);
}
if (isSync) {
ebxmlResponseMessage = responseMessage;
storeOutgoingMessage(ebxmlResponseMessage);
} else {
sendAsyncMessage(responseMessage);
}
} catch (Exception e) {
EbmsProcessor.core.log
.error("Cannot generate acknowledgement for message: "
+ ebxmlRequestMessage.getMessageId());
throw new MessageServiceHandlerException(
"Cannot generate acknowledgement for message: "
+ ebxmlRequestMessage.getMessageId(), e);
}
} else {
// store the order message in repository
storeIncomingMessage(ebxmlRequestMessage, messageType, contentType);
}
return ebxmlResponseMessage;
}
/**
* @param ebxmlRequestMessage
* @param ebxmlResponseMessage
* @return
* @throws MessageServiceHandlerException
*/
private synchronized EbxmlMessage processMessageOrderMessage(
EbxmlMessage ebxmlRequestMessage, boolean isSync,
MessageClassifier messageClassifier, String messageType,
String contentType) throws MessageServiceHandlerException {
EbxmlMessage ebxmlResponseMessage = null;
if (!isSync) {
if (messageClassifier.isAckRequested()) {
if (messageClassifier.isSeqeunceStatusReset()) {
if (!isFirstResetMessage(ebxmlRequestMessage)
&& hasPendingMessage(ebxmlRequestMessage)) {
// store process error message
storeIncomingMessage(ebxmlRequestMessage,
MessageClassifier.MESSAGE_TYPE_PROCESSED_ERROR,
contentType);
// if pending msg exist -> error
String errMessage = "Pending message exist, cannot reset the sequence number for message: "
+ ebxmlRequestMessage.getMessageId();
EbmsProcessor.core.log.error(errMessage);
sendAsyncErrorMessage(ebxmlRequestMessage, errMessage);
} else {
storeIncomingOrderedMessage(ebxmlRequestMessage,
messageClassifier, messageType, contentType);
// else reset allowed -> generate acknowledgement
try {
EbxmlMessage responseMessage = SignalMessageGenerator
.generateAcknowledgment(ebxmlRequestMessage);
if (ebxmlRequestMessage.getAckRequested()
.getSigned()) {
EbmsProcessor.core.log
.info("Sign the acknowledgement ("
+ responseMessage
.getMessageId()
+ ") for message: "
+ ebxmlRequestMessage
.getMessageId());
signAcknowledgement(responseMessage);
}
sendAsyncMessage(responseMessage);
} catch (Exception e) {
EbmsProcessor.core.log
.error("Cannot generate acknowledgement for message: "
+ ebxmlRequestMessage
.getMessageId());
throw new MessageServiceHandlerException(
"Cannot generate acknowledgement for message: "
+ ebxmlRequestMessage
.getMessageId(),
e);
}
}
} else {
if (ebxmlRequestMessage.getMessageOrder()
.getSequenceNumber() == 0) {
// This version of corvus ebms plugin does not support
// (seq no: 0, continue)
EbmsProcessor.core.log
.error("This version of corvus ebms plugin does not support (seq no: 0, continue) for message: "
+ ebxmlRequestMessage.getMessageId());
throw new MessageServiceHandlerException(
"This version of corvus ebms plugin does not support (seq no: 0, continue) for message: "
+ ebxmlRequestMessage.getMessageId());
}
if (hasSequenceNumber(ebxmlRequestMessage)) {
// store process error message
storeIncomingMessage(ebxmlRequestMessage,
MessageClassifier.MESSAGE_TYPE_PROCESSED_ERROR,
contentType);
String errMessage = "Message order is duplicate for message: "
+ ebxmlRequestMessage.getMessageId();
EbmsProcessor.core.log.error(errMessage);
sendAsyncErrorMessage(ebxmlRequestMessage, errMessage);
} else {
storeIncomingOrderedMessage(ebxmlRequestMessage,
messageClassifier, messageType, contentType);
try {
EbxmlMessage responseMessage = SignalMessageGenerator
.generateAcknowledgment(ebxmlRequestMessage);
if (ebxmlRequestMessage.getAckRequested()
.getSigned()) {
EbmsProcessor.core.log
.info("Sign the acknowledgement ("
+ responseMessage
.getMessageId()
+ ") for message: "
+ ebxmlRequestMessage
.getMessageId());
signAcknowledgement(responseMessage);
}
sendAsyncMessage(responseMessage);
} catch (Exception e) {
EbmsProcessor.core.log
.error("Cannot generate acknowledgement for message: "
+ ebxmlRequestMessage
.getMessageId());
throw new MessageServiceHandlerException(
"Cannot generate acknowledgement for message: "
+ ebxmlRequestMessage
.getMessageId(),
e);
}
}
}
} else {
// store process error message
storeIncomingMessage(ebxmlRequestMessage,
MessageClassifier.MESSAGE_TYPE_PROCESSED_ERROR,
contentType);
// error - message order is reliable messaging
String errMessage = "Message order is reliable messaging for message: "
+ ebxmlRequestMessage.getMessageId();
EbmsProcessor.core.log.error(errMessage);
sendAsyncErrorMessage(ebxmlRequestMessage, errMessage);
}
} else {
// error - message order is async (sync reply)
try {
// store process error message
storeIncomingMessage(ebxmlRequestMessage,
MessageClassifier.MESSAGE_TYPE_PROCESSED_ERROR,
contentType);
String errMessage = "Message order is asynchronize for message: "
+ ebxmlRequestMessage.getMessageId();
EbxmlMessage responseMessage = SignalMessageGenerator
.generateErrorMessage(ebxmlRequestMessage,
ErrorList.CODE_INCONSISTENT,
ErrorList.SEVERITY_ERROR, errMessage, null);
EbmsProcessor.core.log.error(errMessage);
ebxmlResponseMessage = responseMessage;
storeOutgoingMessage(ebxmlResponseMessage);
} catch (SOAPException e) {
EbmsProcessor.core.log
.error("Cannot generate error message in processing invalid ordered message: "
+ ebxmlRequestMessage.getMessageId());
throw new MessageServiceHandlerException(
"Cannot generate error message in processing invalid ordered message: "
+ ebxmlRequestMessage.getMessageId(), e);
}
}
return ebxmlResponseMessage;
}
/**
* @param ebxmlRequestMessage
* @param messageType
* @param principalId
* @param contentType
* @throws MessageServiceHandlerException
* @throws DAOException
*/
private void storeIncomingOrderedMessage(EbxmlMessage ebxmlRequestMessage,
MessageClassifier messageClassifier, String messageType,
String contentType) throws MessageServiceHandlerException {
try {
MessageDAO messageDAO = (MessageDAO) EbmsProcessor.core.dao
.createDAO(MessageDAO.class);
EbxmlMessageDAOConvertor message = new EbxmlMessageDAOConvertor(
ebxmlRequestMessage, MessageClassifier.MESSAGE_BOX_INBOX,
messageType);
MessageDVO messageDVO = message.getMessageDVO();
messageDVO.setStatus(MessageClassifier.INTERNAL_STATUS_PENDING);
// update the sequence group
int currentMaxSequenceGroup = messageDAO
.findMaxSequenceGroupByMessageBoxAndCpa(messageDVO);
if (messageClassifier.isSeqeunceStatusReset()) {
if (isFirstResetMessage(ebxmlRequestMessage)) {
EbmsProcessor.core.log
.debug("It is the first reset message: "
+ ebxmlRequestMessage.getMessageId());
currentMaxSequenceGroup = 0;
} else {
currentMaxSequenceGroup++;
}
EbmsProcessor.core.log
.debug("Ordered RESET message with new sequence group "
+ currentMaxSequenceGroup + " for message: "
+ ebxmlRequestMessage.getMessageId());
} else {
if (currentMaxSequenceGroup == -1) {
currentMaxSequenceGroup++;
}
EbmsProcessor.core.log
.debug("Ordered message with sequence group "
+ currentMaxSequenceGroup + " for message: "
+ ebxmlRequestMessage.getMessageId());
}
messageDVO.setSequenceGroup(currentMaxSequenceGroup);
RepositoryDVO repositoryDVO = message.getRepositoryDVO();
MessageServerDAO messageServerDAO = (MessageServerDAO) EbmsProcessor.core.dao
.createDAO(MessageServerDAO.class);
messageServerDAO.storeMessage(messageDVO, repositoryDVO);
EbmsProcessor.core.log.info("Store incoming ordered message: "
+ ebxmlRequestMessage.getMessageId());
} catch (DAOException e) {
EbmsProcessor.core.log.error(
"Error in storing the incoming ordered message", e);
throw new MessageServiceHandlerException(
"Error in storing the incoming ordered message", e);
}
}
/**
* @param ebxmlRequestMessage
* @throws DAOException
* @throws SignatureException
* @throws SOAPException
*/
private void signAcknowledgement(EbxmlMessage responseMessage)
throws DAOException, SOAPException, SignatureException {
try {
String dsAlgorithm = null;
String mdAlgorithm = null;
PartnershipDAO partnershipDAO = (PartnershipDAO) EbmsProcessor.core.dao
.createDAO(PartnershipDAO.class);
PartnershipDVO parntershipDVO = (PartnershipDVO) partnershipDAO
.createDVO();
parntershipDVO.setCpaId(responseMessage.getCpaId());
parntershipDVO.setService(responseMessage.getService());
parntershipDVO.setAction(responseMessage.getAction());
if (partnershipDAO.findPartnershipByCPA(parntershipDVO)) {
dsAlgorithm = parntershipDVO.getDsAlgorithm();
mdAlgorithm = parntershipDVO.getMdAlgorithm();
}
SignatureHandler signatureHandler = MessageServiceHandler
.createSignatureHandler(responseMessage);
if (MessageServiceHandler.getInstance().isSignHeaderOnly()) {
EbmsProcessor.core.log.error("sign header only for interop");
signatureHandler.sign(dsAlgorithm, mdAlgorithm, true);
} else {
signatureHandler.sign(dsAlgorithm, mdAlgorithm, false);
}
} catch (Throwable t) {
throw new SignatureException("Unable to sign acknowledgement", t);
}
}
/**
* @param errMessage
* @throws MessageServiceHandlerException
*/
private void sendAsyncErrorMessage(EbxmlMessage ebxmlRequestMessage,
String errMessage) throws MessageServiceHandlerException {
try {
EbxmlMessage responseMessage = SignalMessageGenerator
.generateErrorMessage(ebxmlRequestMessage,
ErrorList.CODE_INCONSISTENT,
ErrorList.SEVERITY_ERROR, errMessage, null);
sendAsyncMessage(responseMessage);
} catch (SOAPException e) {
EbmsProcessor.core.log.error("Cannot generate error message");
throw new MessageServiceHandlerException(
"Cannot generate error message", e);
}
}
/**
* @param ebxmlRequestMessage
* @return
* @throws MessageServiceHandlerException
*/
private boolean isFirstResetMessage(EbxmlMessage ebxmlRequestMessage)
throws MessageServiceHandlerException {
if (ebxmlRequestMessage.getMessageOrder().getSequenceNumber() != 0) {
throw new MessageServiceHandlerException(
"It is not a reset message");
}
try {
MessageDAO messageDAO = (MessageDAO) EbmsProcessor.core.dao
.createDAO(MessageDAO.class);
MessageDVO messageDVO = (MessageDVO) messageDAO.createDVO();
messageDVO.setMessageBox(MessageClassifier.MESSAGE_BOX_INBOX);
messageDVO.setCpaId(ebxmlRequestMessage.getCpaId());
messageDVO.setService(ebxmlRequestMessage.getService());
messageDVO.setAction(ebxmlRequestMessage.getAction());
messageDVO.setConvId(ebxmlRequestMessage.getConversationId());
messageDVO.setSequenceNo(ebxmlRequestMessage.getMessageOrder()
.getSequenceNumber());
int currentMaxSequenceGroup = messageDAO
.findMaxSequenceGroupByMessageBoxAndCpa(messageDVO);
if (currentMaxSequenceGroup == -1) {
// no any messages
return true;
} else if (currentMaxSequenceGroup == 0) {
// has message in sequence group zero
messageDVO.setSequenceGroup(currentMaxSequenceGroup);
return !messageDAO
.findOrderedMessageByMessageBoxAndCpaAndSequenceGroupAndSequenceNo(messageDVO);
} else {
// has message and reset already
return false;
}
} catch (DAOException e) {
EbmsProcessor.core.log.error(
"Error in checking is first reset message: "
+ ebxmlRequestMessage.getMessageId(), e);
throw new MessageServiceHandlerException(
"Error in checking is first reset message: "
+ ebxmlRequestMessage.getMessageId(), e);
}
}
/**
* @param ebxmlRequestMessage
* @return
* @throws MessageServiceHandlerException
*/
private boolean hasSequenceNumber(EbxmlMessage ebxmlRequestMessage)
throws MessageServiceHandlerException {
try {
MessageDAO messageDAO = (MessageDAO) EbmsProcessor.core.dao
.createDAO(MessageDAO.class);
MessageDVO messageDVO = (MessageDVO) messageDAO.createDVO();
messageDVO.setMessageBox(MessageClassifier.MESSAGE_BOX_INBOX);
messageDVO.setCpaId(ebxmlRequestMessage.getCpaId());
messageDVO.setService(ebxmlRequestMessage.getService());
messageDVO.setAction(ebxmlRequestMessage.getAction());
messageDVO.setConvId(ebxmlRequestMessage.getConversationId());
messageDVO.setSequenceNo(ebxmlRequestMessage.getMessageOrder()
.getSequenceNumber());
int currentMaxSequenceGroup = messageDAO
.findMaxSequenceGroupByMessageBoxAndCpa(messageDVO);
if (currentMaxSequenceGroup == -1) {
return false;
}
messageDVO.setSequenceGroup(currentMaxSequenceGroup);
return messageDAO
.findOrderedMessageByMessageBoxAndCpaAndSequenceGroupAndSequenceNo(messageDVO);
} catch (DAOException e) {
EbmsProcessor.core.log.error("Error in checking sequence number: "
+ ebxmlRequestMessage.getMessageId(), e);
throw new MessageServiceHandlerException(
"Error in checking sequence number: "
+ ebxmlRequestMessage.getMessageId(), e);
}
}
/**
* @param ebxmlRequestMessage
* @throws MessageServiceHandlerException
*/
private boolean hasPendingMessage(EbxmlMessage ebxmlRequestMessage)
throws MessageServiceHandlerException {
try {
MessageDAO messageDAO = (MessageDAO) EbmsProcessor.core.dao
.createDAO(MessageDAO.class);
MessageDVO messageDVO = (MessageDVO) messageDAO.createDVO();
messageDVO.setCpaId(ebxmlRequestMessage.getCpaId());
messageDVO.setService(ebxmlRequestMessage.getService());
messageDVO.setAction(ebxmlRequestMessage.getAction());
messageDVO.setConvId(ebxmlRequestMessage.getConversationId());
messageDVO.setMessageBox(MessageClassifier.MESSAGE_BOX_INBOX);
int currentMaxSequenceGroup = messageDAO
.findMaxSequenceGroupByMessageBoxAndCpa(messageDVO);
if (currentMaxSequenceGroup == -1) {
return false;
}
messageDVO.setSequenceGroup(currentMaxSequenceGroup);
int currentNumOfMessagesInMaxSequenceGroup = messageDAO
.findNumOfMessagesByMessageBoxAndCpaAndSequenceGroup(messageDVO);
int currentMaxSequenceNo = messageDAO
.findMaxSequenceNoByMessageBoxAndCpa(messageDVO);
if (currentNumOfMessagesInMaxSequenceGroup == currentMaxSequenceNo + 1) {
return false;
} else {
return true;
}
} catch (DAOException e) {
EbmsProcessor.core.log.error("Error in checking pending message: "
+ ebxmlRequestMessage.getMessageId(), e);
throw new MessageServiceHandlerException(
"Error in checking pending message: "
+ ebxmlRequestMessage.getMessageId(), e);
}
}
private String findPartnershipId(EbxmlMessage ebxmlRequestMessage)
throws MessageServiceHandlerException {
// first - from ref to message
// second - from receiver channel
if (ebxmlRequestMessage.getMessageHeader().getRefToMessageId() != null) {
// if it contains reference message id
try {
MessageDAO messageDAO = (MessageDAO) EbmsProcessor.core.dao
.createDAO(MessageDAO.class);
MessageDVO messageDVO = (MessageDVO) messageDAO.createDVO();
// if RefToMessageId is not found in eb:Header, try to retrieve
// from eb:Acknowledgement
if (ebxmlRequestMessage.getMessageHeader().getRefToMessageId() != null)
messageDVO.setMessageId(ebxmlRequestMessage
.getMessageHeader().getRefToMessageId());
else if (ebxmlRequestMessage.getAcknowledgment() != null
&& ebxmlRequestMessage.getAcknowledgment()
.getRefToMessageId() != null)
messageDVO.setMessageId(ebxmlRequestMessage
.getAcknowledgment().getRefToMessageId());
messageDVO.setMessageBox(MessageClassifier.MESSAGE_BOX_OUTBOX);
if (messageDAO.findMessage(messageDVO)) {
PartnershipDAO partnershipDAO = (PartnershipDAO) EbmsProcessor.core.dao
.createDAO(PartnershipDAO.class);
PartnershipDVO partnershipDVO = (PartnershipDVO) partnershipDAO
.createDVO();
partnershipDVO.setCpaId(messageDVO.getCpaId());
partnershipDVO.setService(messageDVO.getService());
partnershipDVO.setAction(messageDVO.getAction());
if (partnershipDAO.findPartnershipByCPA(partnershipDVO)) {
return partnershipDVO.getPartnershipId();
}
}
} catch (DAOException e) {
EbmsProcessor.core.log.error(
"Error in finding the partnership of reference message id: "
+ ebxmlRequestMessage.getMessageHeader()
.getRefToMessageId(), e);
throw new MessageServiceHandlerException(
"Error in finding the partnership of reference message id: "
+ ebxmlRequestMessage.getMessageHeader()
.getRefToMessageId(), e);
}
}
// search in receiver channel
try {
PartnershipDAO partnershipDAO = (PartnershipDAO) EbmsProcessor.core.dao
.createDAO(PartnershipDAO.class);
PartnershipDVO partnershipDVO = (PartnershipDVO) partnershipDAO
.createDVO();
partnershipDVO.setCpaId(ebxmlRequestMessage.getCpaId());
partnershipDVO.setService(ebxmlRequestMessage.getService());
partnershipDVO.setAction(ebxmlRequestMessage.getAction());
if (partnershipDAO.findPartnershipByCPA(partnershipDVO)) {
return partnershipDVO.getPartnershipId();
}
} catch (DAOException e) {
EbmsProcessor.core.log.error(
"Error in finding the partnership of message id: "
+ ebxmlRequestMessage.getMessageId(), e);
throw new MessageServiceHandlerException(
"Error in finding the partnership of message id: "
+ ebxmlRequestMessage.getMessageId(), e);
}
return null;
}
/**
* @param ebxmlRequestMessage
* @return
* @throws MessageServiceHandlerException
*/
/*
* private String findPrincipalId(EbxmlMessage ebxmlRequestMessage) throws
* MessageServiceHandlerException { // first - from ref to message // second
* - from receiver channel
*
* if (ebxmlRequestMessage.getMessageHeader().getRefToMessageId() != null) {
* // if it contains reference message id try { MessageDAO messageDAO =
* (MessageDAO) EbmsProcessor.core.dao .createDAO(MessageDAO.class);
* MessageDVO messageDVO = (MessageDVO) messageDAO.createDVO();
* messageDVO.setMessageId(ebxmlRequestMessage.getMessageHeader()
* .getRefToMessageId());
* messageDVO.setMessageBox(MessageClassifier.MESSAGE_BOX_OUTBOX); if
* (messageDAO.findMessage(messageDVO)) { return
* messageDVO.getPrincipalId(); } } catch (DAOException e) {
* EbmsProcessor.core.log.error( "Error in finding the principal id: " +
* ebxmlRequestMessage.getMessageId(), e); throw new
* MessageServiceHandlerException( "Error in finding the principal id: " +
* ebxmlRequestMessage.getMessageId(), e); } } // search in receiver channel
* try { PartnershipDAO partnershipDAO = (PartnershipDAO)
* EbmsProcessor.core.dao .createDAO(PartnershipDAO.class); PartnershipDVO
* partnershipDVO = (PartnershipDVO) partnershipDAO .createDVO();
* partnershipDVO.setCpaId(ebxmlRequestMessage.getCpaId());
* partnershipDVO.setService(ebxmlRequestMessage.getService());
* partnershipDVO.setAction(ebxmlRequestMessage.getAction()); if
* (partnershipDAO.findPartnershipByCPA(partnershipDVO)) { return
* partnershipDVO.getPrincipalId(); } } catch (DAOException e) {
* EbmsProcessor.core.log.error("Error in finding the principal id: " +
* ebxmlRequestMessage.getMessageId(), e); throw new
* MessageServiceHandlerException( "Error in finding the principal id: " +
* ebxmlRequestMessage.getMessageId(), e); } return null; }
*/
/**
* @param ebxmlRequestMessage
* @return
* @throws MessageServiceHandlerException
*/
private X509Certificate findSenderCert(EbxmlMessage ebxmlRequestMessage)
throws MessageServiceHandlerException {
X509Certificate senderCert = null;
// search in receiver channel
try {
PartnershipDAO partnershipDAO = (PartnershipDAO) EbmsProcessor.core.dao
.createDAO(PartnershipDAO.class);
PartnershipDVO partnershipDVO = (PartnershipDVO) partnershipDAO
.createDVO();
partnershipDVO.setCpaId(ebxmlRequestMessage.getCpaId());
if (ebxmlRequestMessage.getAcknowledgment() == null) {
partnershipDVO.setService(ebxmlRequestMessage.getService());
partnershipDVO.setAction(ebxmlRequestMessage.getAction());
} else {
// it is not an order msg.
MessageDAO messageDAO = (MessageDAO) EbmsProcessor.core.dao
.createDAO(MessageDAO.class);
MessageDVO orgMessageDVO = (MessageDVO) messageDAO.createDVO();
// if RefToMessageId is not found in eb:Header, try to retrieve
// from eb:Acknowledgement
if (ebxmlRequestMessage.getMessageHeader().getRefToMessageId() != null)
orgMessageDVO.setMessageId(ebxmlRequestMessage
.getMessageHeader().getRefToMessageId());
else if (ebxmlRequestMessage.getAcknowledgment() != null
&& ebxmlRequestMessage.getAcknowledgment()
.getRefToMessageId() != null)
orgMessageDVO.setMessageId(ebxmlRequestMessage
.getAcknowledgment().getRefToMessageId());
orgMessageDVO
.setMessageBox(MessageClassifier.MESSAGE_BOX_OUTBOX);
if (messageDAO.findMessage(orgMessageDVO)) {
partnershipDVO.setService(orgMessageDVO.getService());
partnershipDVO.setAction(orgMessageDVO.getAction());
}
}
partnershipDAO.findPartnershipByCPA(partnershipDVO);
if (partnershipDVO.getSignCert() != null) {
ByteArrayInputStream bais = new ByteArrayInputStream(
partnershipDVO.getSignCert());
CertificateFactory cf = CertificateFactory.getInstance("X.509");
senderCert = (X509Certificate) cf.generateCertificate(bais);
bais.close();
bais = null;
} else {
EbmsProcessor.core.log.error("Please upload the certificate");
throw new RuntimeException("Please upload the certificate");
}
return senderCert;
} catch (Exception e) {
EbmsProcessor.core.log.error("Error in finding the certificate", e);
throw new MessageServiceHandlerException(
"Error in finding the certificate", e);
}
}
/**
* @param ebxmlRequestMessage
* @return
* @throws MessageServiceHandlerException
*/
private boolean checkDuplicate(EbxmlMessage ebxmlRequestMessage)
throws MessageServiceHandlerException {
try {
MessageDAO messageDAO = (MessageDAO) EbmsProcessor.core.dao
.createDAO(MessageDAO.class);
MessageDVO messageDVO = (MessageDVO) messageDAO.createDVO();
messageDVO.setMessageId(ebxmlRequestMessage.getMessageId());
messageDVO.setMessageBox(MessageClassifier.MESSAGE_BOX_INBOX);
return messageDAO.findMessage(messageDVO);
} catch (DAOException e) {
EbmsProcessor.core.log.error(
"Error in checking duplicate message: "
+ ebxmlRequestMessage.getMessageId(), e);
throw new MessageServiceHandlerException(
"Error in checking duplicate message", e);
}
}
/**
* @param ebxmlRequestMessage
* @return
*/
private boolean checkSignature(EbxmlMessage ebxmlRequestMessage) {
try {
SOAPEnvelope soapEnvelope = ebxmlRequestMessage.getSOAPMessage()
.getSOAPPart().getEnvelope();
Name signatureName = soapEnvelope.createName(
Signature.ELEMENT_SIGNATURE, Signature.NAMESPACE_PREFIX_DS,
Signature.NAMESPACE_URI_DS);
boolean hasSignature = soapEnvelope.getHeader()
.getChildElements(signatureName).hasNext();
// if it has signature, verify it
if (!hasSignature) {
return true;
} else {
SignatureHandler signatureHandler = MessageServiceHandler
.createSignatureHandler(ebxmlRequestMessage,
findSenderCert(ebxmlRequestMessage));
if (!signatureHandler.verifyByPublicKey()) {
EbmsProcessor.core.log
.error("Signature verification fail: "
+ ebxmlRequestMessage.getMessageId());
return false;
} else {
EbmsProcessor.core.log
.info("Signature verification success: "
+ ebxmlRequestMessage.getMessageId());
return true;
}
}
} catch (Throwable e) {
EbmsProcessor.core.log.error("Error in verifying signature", e);
return false;
}
}
private boolean checkRefToMessage(EbxmlMessage ebxmlRequestMessage)
throws MessageServiceHandlerException {
boolean hasRefMessageId = false;
try {
MessageDAO messageDAO = (MessageDAO) EbmsProcessor.core.dao
.createDAO(MessageDAO.class);
MessageDVO messageDVO = (MessageDVO) messageDAO.createDVO();
messageDVO.setMessageId(ebxmlRequestMessage.getMessageHeader()
.getRefToMessageId());
messageDVO.setMessageBox(MessageClassifier.MESSAGE_BOX_OUTBOX);
hasRefMessageId = messageDAO.findMessage(messageDVO);
// update the message status if it's acknowledgement or error is
// received
if (ebxmlRequestMessage.getAcknowledgment() != null) {
if (!messageDVO.getStatus().equalsIgnoreCase(
MessageClassifier.INTERNAL_STATUS_DELIVERY_FAILURE)) {
// if it is failed already..don't mark it as deliveried
// it is because it is timeout failure
messageDVO
.setStatus(MessageClassifier.INTERNAL_STATUS_PROCESSED);
messageDVO
.setStatusDescription("Acknowledgement is received");
messageDVO.setTimeoutTimestamp(null);
messageDAO.updateMessage(messageDVO);
}
} else if (ebxmlRequestMessage.getErrorList() != null) {
messageDVO
.setStatus(MessageClassifier.INTERNAL_STATUS_PROCESSED_ERROR);
StringBuffer sb = new StringBuffer();
Iterator i = ebxmlRequestMessage.getErrorList().getErrors();
while (i.hasNext()) {
ErrorList.Error error = (ErrorList.Error) i.next();
Description description = error.getDescription();
sb.append(error.getErrorCode() + ": "
+ description.getDescription());
}
messageDVO.setStatusDescription(sb.toString());
messageDVO.setTimeoutTimestamp(null);
messageDAO.updateMessage(messageDVO);
}
} catch (DAOException e) {
EbmsProcessor.core.log.error(
"Error in checking the reference to message: "
+ ebxmlRequestMessage.getMessageId(), e);
throw new MessageServiceHandlerException(
"Error in checking the reference to message: "
+ ebxmlRequestMessage.getMessageId(), e);
}
return hasRefMessageId;
}
private void sendAsyncMessage(EbxmlMessage ebxmlResponseMessage)
throws MessageServiceHandlerException {
EbmsProcessor.core.log.info("Sending async reply message: "
+ ebxmlResponseMessage.getMessageId());
EbmsRequest ebmsRequest = new EbmsRequest();
ebmsRequest.setMessage(ebxmlResponseMessage);
MessageServiceHandler.getInstance().processOutboundMessage(ebmsRequest,
null);
}
private void storeIncomingMessage(EbxmlMessage ebxmlRequestMessage,
String messageType, String contentType)
throws MessageServiceHandlerException {
EbxmlMessageDAOConvertor message = new EbxmlMessageDAOConvertor(
ebxmlRequestMessage, MessageClassifier.MESSAGE_BOX_INBOX,
messageType);
try {
MessageDVO messageDVO = message.getMessageDVO();
messageDVO.setHostname(HostInfo.GetLocalhostAddress());
messageDVO.setStatus(MessageClassifier.INTERNAL_STATUS_PENDING);
MessageServerDAO messageServerDAO = (MessageServerDAO) EbmsProcessor.core.dao
.createDAO(MessageServerDAO.class);
RepositoryDVO repositoryDVO = message.getRepositoryDVO();
messageServerDAO.storeMessage(messageDVO, repositoryDVO);
} catch (DAOException e) {
EbmsProcessor.core.log.error(
"Error in storing the incoming message: "
+ ebxmlRequestMessage.getMessageId(), e);
throw new MessageServiceHandlerException(
"Error in storing the incoming message: "
+ ebxmlRequestMessage.getMessageId(), e);
}
EbmsProcessor.core.log.info("Store the incoming message: "
+ ebxmlRequestMessage.getMessageId());
}
private void storeOutgoingMessage(EbxmlMessage ebxmlResponseMessage)
throws MessageServiceHandlerException {
MessageClassifier messageClassifier = new MessageClassifier(
ebxmlResponseMessage);
EbxmlMessageDAOConvertor message = new EbxmlMessageDAOConvertor(
ebxmlResponseMessage, MessageClassifier.MESSAGE_BOX_OUTBOX,
messageClassifier.getMessageType());
try {
MessageDVO messageDVO = message.getMessageDVO();
messageDVO.setHostname(HostInfo.GetLocalhostAddress());
messageDVO.setStatus(MessageClassifier.INTERNAL_STATUS_PROCESSED);
messageDVO.setStatusDescription("Message was sent synchronously");
MessageServerDAO messageServerDAO = (MessageServerDAO) EbmsProcessor.core.dao
.createDAO(MessageServerDAO.class);
messageServerDAO.storeMessage(messageDVO,
message.getRepositoryDVO());
} catch (DAOException e) {
EbmsProcessor.core.log.error(
"Error in storing the outgoing message", e);
throw new MessageServiceHandlerException(
"Error in storing the outgoing message", e);
}
// it is for sync reply msg to store a copy
EbmsProcessor.core.log.info("Store outgoing message: "
+ ebxmlResponseMessage.getMessageId());
}
/**
* Convert a string of data type "dateTime" as specified by XML-Schema Part
* 2: Datatypes section 3.2.7 to local date/time. Only date/time represented
* as CCYY-MM-DDThh:mm:ssZ is supported.
*
* @param dateTime
* Date/time string in UTC.
*
* @return local time representation of the given UTC time string.
*/
private Date fromUTCString(String dateTime) {
try {
ArrayList parts = new ArrayList();
int i, j;
for (i = 0, j = 0; i < dateTime.length(); i++) {
if ("-+:TZ.".indexOf(dateTime.charAt(i)) != -1
|| i == dateTime.length() - 1) {
parts.add(dateTime.substring(j, i));
j = i + 1;
}
}
// Check if all date/time components exist or not
int count = parts.size();
if (count < 6)
return null;
int year = Integer.parseInt((String) parts.get(0));
int month = Integer.parseInt((String) parts.get(1));
int day = Integer.parseInt((String) parts.get(2));
int hour = Integer.parseInt((String) parts.get(3));
int minute = Integer.parseInt((String) parts.get(4));
int second = Integer.parseInt((String) parts.get(5));
if (count == 8) {
int hourOffset = Integer.parseInt((String) parts.get(6));
int minOffset = Integer.parseInt((String) parts.get(7));
if (dateTime.indexOf("+") != -1) {
hour -= hourOffset;
minute -= minOffset;
} else {
hour += hourOffset;
minute += minOffset;
}
}
final Calendar c = Calendar
.getInstance(TimeZone.getTimeZone("GMT"));
c.clear();
// In Calendar class, January = 0
c.set(year, month - 1, day, hour, minute, second);
return c.getTime();
} catch (NumberFormatException nfe) {
return null;
}
}
}