package org.jentrata.ebms.as4.internal.routes; import org.apache.camel.Exchange; import org.apache.camel.LoggingLevel; import org.apache.camel.Message; import org.apache.camel.Processor; import org.apache.camel.builder.RouteBuilder; import org.jentrata.ebms.EbmsConstants; import org.jentrata.ebms.MessageStatusType; import org.jentrata.ebms.MessageType; import org.jentrata.ebms.cpa.InvalidPartnerAgreementException; import org.jentrata.ebms.cpa.PartnerAgreement; import org.jentrata.ebms.cpa.pmode.PayloadService; import org.jentrata.ebms.messaging.MessageStore; import org.jentrata.ebms.soap.SoapMessageDataFormat; import org.jentrata.ebms.utils.EbmsUtils; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.jentrata.ebms.utils.ExpressionHelper.headerWithDefault; /** * Pickup outbound messages generates the ebMS envelope * * @author aaronwalker */ public class EbmsOutboundMessageRouteBuilder extends RouteBuilder { private String deliveryQueue = "activemq:queue:jentrata_as4_outbound"; private String errorQueue = "activemq:queue:jentrata_as4_outbound_error"; private String outboundEbmsQueue = "activemq:queue:jentrata_internal_ebms_outbound"; private String messgeStoreEndpoint = MessageStore.DEFAULT_MESSAGE_STORE_ENDPOINT; private String messageInsertEndpoint = MessageStore.DEFAULT_MESSAGE_INSERT_ENDPOINT; private String wsseSecurityAddEndpoint = "direct:wsseAddSecurityToHeader"; private String defaultCPAId = null; @Override public void configure() throws Exception { from(deliveryQueue) .onException(Exception.class) .log(LoggingLevel.DEBUG, "headers:${headers}\nbody:\n${in.body}") .log(LoggingLevel.ERROR, "${exception.message}\n${exception.stacktrace}") .setHeader(EbmsConstants.MESSAGE_STATUS, constant(MessageStatusType.FAILED.name())) .setHeader(EbmsConstants.MESSAGE_STATUS_DESCRIPTION,simple("${exception.message}")) .to(errorQueue) .inOnly(EventNotificationRouteBuilder.SEND_NOTIFICATION_ENDPOINT) .handled(true) .end() .setHeader(EbmsConstants.DEFAULT_CPA_ID,constant(defaultCPAId)) .to("direct:lookupCpaId") .choice() .when(header(EbmsConstants.CPA_ID).isEqualTo(EbmsConstants.CPA_ID_UNKNOWN)) .throwException(new InvalidPartnerAgreementException("unable to find matching partner agreement")) .otherwise() .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { PartnerAgreement agreement = exchange.getIn().getHeader(EbmsConstants.CPA, PartnerAgreement.class); if (agreement == null) { throw new InvalidPartnerAgreementException("unable to find matching partner agreement"); } String body = exchange.getIn().getBody(String.class); String contentType = exchange.getIn().getHeader(EbmsConstants.CONTENT_TYPE, String.class); String contentCharset = exchange.getIn().getHeader(EbmsConstants.CONTENT_CHAR_SET, "UTF-8", String.class); String payloadId = exchange.getIn().getHeader(EbmsConstants.PAYLOAD_ID, String.class); PayloadService payloadService = PayloadService.DEFAULT_PAYLOAD_SERVICE; if (payloadId != null) { payloadService = agreement.getPayloadProfile(payloadId); } else { payloadId = payloadService.getPayloadId(); } if (contentType == null) { contentType = payloadService.getContentType(); } String schema = exchange.getIn().getHeader(EbmsConstants.MESSAGE_PAYLOAD_SCHEMA, String.class); String compressionType = exchange.getIn().getHeader(EbmsConstants.PAYLOAD_COMPRESSION, payloadService.getCompressionType().getType(), String.class); Map<String, String> mimeHeaders = extractMimeHeaders(contentType, exchange.getIn()); List<Map<String, Object>> partProperties = EbmsUtils.extractPartProperties(exchange.getIn().getHeader(EbmsConstants.MESSAGE_PART_PROPERTIES, String.class)); List<Map<String, Object>> payloads = new ArrayList<>(); Map<String, Object> payloadMap = new HashMap<>(); payloadMap.put("payloadId", payloadId); payloadMap.put("contentType", contentType); payloadMap.put("charset", contentCharset); payloadMap.put("partProperties", partProperties); payloadMap.put("schema", schema); payloadMap.put("compressionType", compressionType); if (compressionType != null && compressionType.length() > 0) { payloadMap.put("content", EbmsUtils.compress(compressionType, body.getBytes(contentCharset))); } else { payloadMap.put("content", body.getBytes(contentCharset)); } payloadMap.put("mimeHeaders", mimeHeaders); payloads.add(payloadMap); exchange.getIn().setBody(payloads); } }) .to("direct:setMessageDefaults") .setHeader(EbmsConstants.MESSAGE_TYPE, constant(MessageType.USER_MESSAGE.name())) .setHeader(EbmsConstants.MESSAGE_DIRECTION, constant(EbmsConstants.MESSAGE_DIRECTION_OUTBOUND)) .setHeader(EbmsConstants.MESSAGE_PAYLOADS, body()) .to("freemarker:templates/soap-envelope.ftl") .to(wsseSecurityAddEndpoint) .convertBodyTo(String.class) .marshal(new SoapMessageDataFormat()) .to(messgeStoreEndpoint) .to(messageInsertEndpoint) .to(outboundEbmsQueue) .routeId("_jentrataEbmsGenerateMessage"); from("direct:setMessageDefaults") .setHeader(EbmsConstants.MESSAGE_ID, headerWithDefault(EbmsConstants.MESSAGE_ID, simple("${bean:uuidGenerator.generateId}"))) .setHeader(EbmsConstants.MESSAGE_FROM, headerWithDefault(EbmsConstants.MESSAGE_FROM, simple("${headers.JentrataCPA?.initiator?.partyId}"))) .setHeader(EbmsConstants.MESSAGE_FROM_TYPE, headerWithDefault(EbmsConstants.MESSAGE_FROM_TYPE, simple("${headers.JentrataCPA?.initiator?.partyIdType}"))) .setHeader(EbmsConstants.MESSAGE_FROM_ROLE, headerWithDefault(EbmsConstants.MESSAGE_FROM_ROLE, simple("${headers.JentrataCPA?.initiator?.role}"))) .setHeader(EbmsConstants.MESSAGE_TO, headerWithDefault(EbmsConstants.MESSAGE_TO, simple("${headers.JentrataCPA?.responder?.partyId}"))) .setHeader(EbmsConstants.MESSAGE_TO_TYPE, headerWithDefault(EbmsConstants.MESSAGE_TO_TYPE, simple("${headers.JentrataCPA?.responder?.partyIdType}"))) .setHeader(EbmsConstants.MESSAGE_TO_ROLE, headerWithDefault(EbmsConstants.MESSAGE_TO_ROLE, simple("${headers.JentrataCPA?.responder?.role}"))) .setHeader(EbmsConstants.MESSAGE_AGREEMENT_REF, headerWithDefault(EbmsConstants.MESSAGE_AGREEMENT_REF, simple("${headers.JentrataCPA?.agreementRef}"))) .routeId("_jentrataSetMessageDefaults"); } private Map<String, String> extractMimeHeaders(String contentType, Message message) { Map<String,String> mimeHeaders = new HashMap<>(); mimeHeaders.put(EbmsConstants.CONTENT_TRANSFER_ENCODING,message.getHeader(EbmsConstants.CONTENT_TRANSFER_ENCODING,"binary",String.class)); String filename = message.getHeader(EbmsConstants.PAYLOAD_FILENAME,generateFilename(contentType),String.class); mimeHeaders.put(EbmsConstants.CONTENT_DISPOSITION,"attachment; filename=" + filename); return mimeHeaders; } private String generateFilename(String contentType) { StringBuilder filename = new StringBuilder(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); filename.append(sdf.format(new Date())); if(contentType == null || contentType.isEmpty()) { filename.append(".txt"); } else if(contentType.toLowerCase().contains("xml")) { filename.append(".xml"); } else if(contentType.toLowerCase().contains("text")) { filename.append(".txt"); } return filename.toString(); } public String getDeliveryQueue() { return deliveryQueue; } public void setDeliveryQueue(String deliveryQueue) { this.deliveryQueue = deliveryQueue; } public String getErrorQueue() { return errorQueue; } public void setErrorQueue(String errorQueue) { this.errorQueue = errorQueue; } public String getOutboundEbmsQueue() { return outboundEbmsQueue; } public void setOutboundEbmsQueue(String outboundEbmsQueue) { this.outboundEbmsQueue = outboundEbmsQueue; } public String getMessgeStoreEndpoint() { return messgeStoreEndpoint; } public void setMessgeStoreEndpoint(String messgeStoreEndpoint) { this.messgeStoreEndpoint = messgeStoreEndpoint; } public String getMessageInsertEndpoint() { return messageInsertEndpoint; } public void setMessageInsertEndpoint(String messageInsertEndpoint) { this.messageInsertEndpoint = messageInsertEndpoint; } public String getWsseSecurityAddEndpoint() { return wsseSecurityAddEndpoint; } public void setWsseSecurityAddEndpoint(String wsseSecurityAddEndpoint) { this.wsseSecurityAddEndpoint = wsseSecurityAddEndpoint; } public String getDefaultCPAId() { return defaultCPAId; } public void setDefaultCPAId(String defaultCPAId) { this.defaultCPAId = defaultCPAId; } }