/**
* Active Task to query the database which message need to fire the acknowledgment request. Then send an acknowledgment to
* receiver to enquiry the status of SFRM message in the receiver side.
* @auther Patrick Yip
* @version 2.0.0
* @since 2.0.0
*/
package hk.hku.cecid.edi.sfrm.task;
import hk.hku.cecid.edi.sfrm.spa.SFRMException;
import hk.hku.cecid.edi.sfrm.spa.SFRMLog;
import hk.hku.cecid.edi.sfrm.spa.SFRMProcessor;
import hk.hku.cecid.piazza.commons.dao.DAOException;
import hk.hku.cecid.piazza.commons.module.ActiveTaskAdaptor;
import hk.hku.cecid.piazza.commons.security.KeyStoreManager;
import hk.hku.cecid.piazza.commons.io.IOHandler;
import hk.hku.cecid.edi.sfrm.dao.SFRMMessageDVO;
import hk.hku.cecid.edi.sfrm.dao.SFRMMessageSegmentDVO;
import hk.hku.cecid.edi.sfrm.dao.SFRMPartnershipDVO;
import hk.hku.cecid.edi.sfrm.handler.AcknowledgementHandler;
import hk.hku.cecid.edi.sfrm.handler.OutgoingMessageHandler;
import hk.hku.cecid.edi.sfrm.handler.SFRMMessageFactory;
import hk.hku.cecid.edi.sfrm.pkg.SFRMAcknowledgementBuilder;
import hk.hku.cecid.edi.sfrm.pkg.SFRMConstant;
import hk.hku.cecid.edi.sfrm.pkg.SFRMMessage;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.util.List;
import javax.mail.MessagingException;
/**
* Active task responsible for handling the action of sending the acknowledgement request to receiver
* @author Patrick Yip
* @since 2.0.0
*/
public class AcknowledgementTask extends ActiveTaskAdaptor {
private final SFRMMessageDVO messageDVO;
private final SFRMPartnershipDVO partnershipDVO;
public AcknowledgementTask(SFRMMessageDVO messageDVO, SFRMPartnershipDVO partenershipDVO){
this.messageDVO = messageDVO;
this.partnershipDVO = partenershipDVO;
}
public void execute() throws Exception{
String ackContent = buildAckContent();
SFRMMessage ackMessage = SFRMMessageFactory
.getInstance()
.createAcknowledgement(messageDVO, partnershipDVO, SFRMConstant.MSGT_ACK_REQUEST, ackContent);
//Send the acknowledgement
//TODO: To refactor or add a method that can receive the response message from acknowledgement
SFRMMessage responseMessage = OutgoingMessageHandler.getInstance().sendMessageWithMessageResponse(
ackMessage, messageDVO.getPartnerEndpoint(), messageDVO.getIsHostnameVerified(),
messageDVO.getSignAlgorithm(), messageDVO.getEncryptAlgorithm(), messageDVO.getPartnerX509Certificate());
unpackIncomingMessage(responseMessage, partnershipDVO);
BufferedReader ackReader = new BufferedReader(new InputStreamReader(responseMessage.getBodyPart().getInputStream()));
String ackResponseContent = IOHandler.readString(ackReader);
ackReader.close();
AcknowledgementHandler ackHandler = SFRMProcessor.getInstance().getAcknowledgementHandler();
ackHandler.processAcknowledgementResponse(ackResponseContent);
}
private String buildAckContent() throws DAOException{
SFRMAcknowledgementBuilder builder = new SFRMAcknowledgementBuilder();
builder.setMessage(messageDVO.getMessageId(), messageDVO.getStatus());
if(messageDVO.getStatus().equalsIgnoreCase(SFRMConstant.MSGS_PROCESSING) || messageDVO.getStatus().equalsIgnoreCase(SFRMConstant.MSGS_SEGMENTING)){
List segDVOs = SFRMProcessor.getInstance()
.getMessageSegmentHandler()
.retrieveDeliveredSegmentForMessage(messageDVO.getMessageId());
for(int i=0; segDVOs.size() > i ; i++){
SFRMMessageSegmentDVO segDVO = (SFRMMessageSegmentDVO) segDVOs.get(i);
builder.setSegment(messageDVO.getMessageId(), segDVO.getSegmentNo(), segDVO.getStatus());
}
}
return builder.toString();
}
/**
* Invoke when failure occur
* @param e
*/
public void onFaulure(Throwable e){
SFRMProcessor.getInstance().getLogger().error(SFRMLog.AT_CALLER + "Unknown Error", e);
}
// Philip 2009-07-31
// same as IncomingMessageHandler.unpackIncomingMessage
public void unpackIncomingMessage(SFRMMessage message, SFRMPartnershipDVO partnershipDVO) throws SFRMException {
KeyStoreManager keyman = SFRMProcessor.getInstance().getKeyStoreManager();
// Encryption enforcement check and decrypt
if (partnershipDVO.getEncryptAlgorithm() != null) {
if (!message.isEncryptedContentType()) {
SFRMProcessor.getInstance().getLogger().error(
SFRMLog.AT_CALLER + "Encryption enforcement check failed: "
+ message);
throw new SFRMException("Insufficient message security");
} else {
try {
message.decrypt(keyman.getX509Certificate(), keyman.getPrivateKey());
} catch (SFRMException e) {
SFRMProcessor.getInstance().getLogger().error(
SFRMLog.AT_CALLER + "Unable to decrypt "
+ message, e);
throw e;
} catch (NoSuchAlgorithmException e) {
SFRMProcessor.getInstance().getLogger().error(
SFRMLog.AT_CALLER + "Unable to decrypt "
+ message, e);
throw new SFRMException(e.getMessage(), e);
} catch (UnrecoverableKeyException e) {
SFRMProcessor.getInstance().getLogger().error(
SFRMLog.AT_CALLER + "Unable to decrypt "
+ message, e);
throw new SFRMException(e.getMessage(), e);
}
}
}
// Signing enforcement check and unpack verified signature
if (partnershipDVO.getSignAlgorithm() != null) {
if (!message.isSignedContentType()) {
SFRMProcessor.getInstance().getLogger().error(
SFRMLog.AT_CALLER + "Signature enforcement check failed: "
+ message);
throw new SFRMException("Insufficient message security");
} else {
try {
message.verify(partnershipDVO.getVerifyX509Certificate());
} catch (SFRMException e) {
SFRMProcessor.getInstance().getLogger().error(
SFRMLog.AT_CALLER + "Unable to verify "
+ message, e);
throw e;
}
}
}
// Log information
try {
SFRMProcessor.getInstance().getLogger().info(
SFRMLog.AT_CALLER + SFRMLog.UNPACK_SGT
+ " msg id: " + message.getMessageID()
+ " with payload size : "
+ message.getBodyPart().getSize());
} catch (MessagingException e) {
throw new SFRMException("Unable to get body part size");
}
}
}