This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 77205225b90 CAMEL-18110: DeliverSm message payload opt param fix
(#7618)
77205225b90 is described below
commit 77205225b90948bf68e8fc0d7afef91f563b592f
Author: Kalouris Gerasimos <[email protected]>
AuthorDate: Mon May 16 13:38:24 2022 +0300
CAMEL-18110: DeliverSm message payload opt param fix (#7618)
* CAMEL-18110: DeliverSm handle message_payload opt param
When the `message_payload` optional parameter is used then the short
message is set as the empty byte array (zero-length), but not to null as
the CAMEL-9356 anticipated, this is at least, what the jSMPP library is
doing when you try to send a deliverSm with empty content. With this
patch, we try to read from the deliverSm.shortMessage field and if it's
null or empty then fall back to the `message_payload` optional param
when possible.
Another fix is that the message payload is not retrieved as a string but
as a byte array. This way it's decoded with the same encoding that the
deliverSm message was encoded in the first place.
Finally, note that deliverSm contents are not decoded properly for cases
using something other than the default encoding. Specifically for
delivery receipts, this was not the case even for the default encoding
since it was using the
org.jsmpp.util.DefaultDecomposer#deliveryReceipt(byte[]) which is
oblivious of the data encoding used. This means that the
smscDeliveryReceipt.getText() was not properly decoded. With this
revision we at least try the default encoding for DLRs.
To make this issue obvious I created the `decodeBodyIfPossible`method
which currently supports the default data encoding and should be
extended to use all the alphabets.
* CAMEL-18110: Set optional parameter headers for deliverSM
* CAMEL-18110: Add basic encoding support
---
.../apache/camel/component/smpp/SmppBinding.java | 546 ++++++++++-----------
.../org/apache/camel/component/smpp/SmppUtils.java | 53 ++
.../camel/component/smpp/SmppBindingTest.java | 47 +-
.../apache/camel/component/smpp/SmppUtilsTest.java | 40 ++
4 files changed, 398 insertions(+), 288 deletions(-)
diff --git
a/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppBinding.java
b/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppBinding.java
index 238e8269d45..79889bd5169 100644
---
a/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppBinding.java
+++
b/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppBinding.java
@@ -1,287 +1,259 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF 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.
- */
-package org.apache.camel.component.smpp;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.Exchange;
-import org.jsmpp.bean.AlertNotification;
-import org.jsmpp.bean.Alphabet;
-import org.jsmpp.bean.Command;
-import org.jsmpp.bean.DataSm;
-import org.jsmpp.bean.DeliverSm;
-import org.jsmpp.bean.DeliveryReceipt;
-import org.jsmpp.bean.OptionalParameter;
-import org.jsmpp.bean.OptionalParameter.COctetString;
-import org.jsmpp.bean.OptionalParameter.Null;
-import org.jsmpp.bean.OptionalParameter.OctetString;
-import org.jsmpp.bean.OptionalParameter.Tag;
-import org.jsmpp.session.SMPPSession;
-import org.jsmpp.util.DefaultDecomposer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A Strategy used to convert between a Camel {@link Exchange} and {@link
SmppMessage} to and from a SMPP
- * {@link Command}
- */
-public class SmppBinding {
-
- private static final Logger LOG =
LoggerFactory.getLogger(SmppBinding.class);
-
- private SmppConfiguration configuration;
-
- public SmppBinding() {
- this.configuration = new SmppConfiguration();
- }
-
- public SmppBinding(SmppConfiguration configuration) {
- this.configuration = configuration;
- }
-
- /**
- * Create the SmppCommand object from the inbound exchange
- *
- * @throws UnsupportedEncodingException if the encoding is not supported
- */
- public SmppCommand createSmppCommand(SMPPSession session, Exchange
exchange) {
- SmppCommandType commandType = SmppCommandType.fromExchange(exchange);
- SmppCommand command = commandType.createCommand(session,
configuration);
-
- return command;
- }
-
- /**
- * Create a new SmppMessage from the inbound alert notification
- */
- public SmppMessage createSmppMessage(CamelContext camelContext,
AlertNotification alertNotification) {
- SmppMessage smppMessage = new SmppMessage(camelContext,
alertNotification, configuration);
-
- smppMessage.setHeader(SmppConstants.MESSAGE_TYPE,
SmppMessageType.AlertNotification.toString());
- smppMessage.setHeader(SmppConstants.SEQUENCE_NUMBER,
alertNotification.getSequenceNumber());
- smppMessage.setHeader(SmppConstants.COMMAND_ID,
alertNotification.getCommandId());
- smppMessage.setHeader(SmppConstants.COMMAND_STATUS,
alertNotification.getCommandStatus());
- smppMessage.setHeader(SmppConstants.SOURCE_ADDR,
alertNotification.getSourceAddr());
- smppMessage.setHeader(SmppConstants.SOURCE_ADDR_NPI,
alertNotification.getSourceAddrNpi());
- smppMessage.setHeader(SmppConstants.SOURCE_ADDR_TON,
alertNotification.getSourceAddrTon());
- smppMessage.setHeader(SmppConstants.ESME_ADDR,
alertNotification.getEsmeAddr());
- smppMessage.setHeader(SmppConstants.ESME_ADDR_NPI,
alertNotification.getEsmeAddrNpi());
- smppMessage.setHeader(SmppConstants.ESME_ADDR_TON,
alertNotification.getEsmeAddrTon());
-
- return smppMessage;
- }
-
- /**
- * Create a new SmppMessage from the inbound deliver sm or deliver receipt
- */
- public SmppMessage createSmppMessage(CamelContext camelContext, DeliverSm
deliverSm) throws Exception {
- SmppMessage smppMessage = new SmppMessage(camelContext, deliverSm,
configuration);
-
- String messagePayload = null;
-
- if (deliverSm.getShortMessage() == null &&
deliverSm.getOptionalParameters() != null) {
- List<OptionalParameter> oplist =
Arrays.asList(deliverSm.getOptionalParameters());
-
- for (OptionalParameter optPara : oplist) {
- if (OptionalParameter.Tag.MESSAGE_PAYLOAD.code() ==
optPara.tag && OctetString.class
- .isInstance(optPara)) {
- messagePayload = ((OctetString)
optPara).getValueAsString();
- break;
- }
- }
- }
-
- if (deliverSm.isSmscDeliveryReceipt()) {
- smppMessage.setHeader(SmppConstants.MESSAGE_TYPE,
SmppMessageType.DeliveryReceipt.toString());
-
- DeliveryReceipt smscDeliveryReceipt = null;
-
- if (deliverSm.getShortMessage() != null) {
- smscDeliveryReceipt =
deliverSm.getShortMessageAsDeliveryReceipt();
- } else if (messagePayload != null) {
- smscDeliveryReceipt =
DefaultDecomposer.getInstance().deliveryReceipt(messagePayload);
- }
-
- if (smscDeliveryReceipt != null) {
- smppMessage.setBody(smscDeliveryReceipt.getText());
-
- smppMessage.setHeader(SmppConstants.ID,
smscDeliveryReceipt.getId());
- smppMessage.setHeader(SmppConstants.DELIVERED,
smscDeliveryReceipt.getDelivered());
- smppMessage.setHeader(SmppConstants.DONE_DATE,
smscDeliveryReceipt.getDoneDate());
- if (!"000".equals(smscDeliveryReceipt.getError())) {
- smppMessage.setHeader(SmppConstants.ERROR,
smscDeliveryReceipt.getError());
- }
- smppMessage.setHeader(SmppConstants.SUBMIT_DATE,
smscDeliveryReceipt.getSubmitDate());
- smppMessage.setHeader(SmppConstants.SUBMITTED,
smscDeliveryReceipt.getSubmitted());
- smppMessage.setHeader(SmppConstants.FINAL_STATUS,
smscDeliveryReceipt.getFinalStatus());
- }
-
- if (deliverSm.getOptionalParameters() != null &&
deliverSm.getOptionalParameters().length > 0) {
- // the deprecated way
- Map<String, Object> optionalParameters =
createOptionalParameterByName(deliverSm);
- smppMessage.setHeader(SmppConstants.OPTIONAL_PARAMETERS,
optionalParameters);
-
- // the new way
- Map<Short, Object> optionalParameter =
createOptionalParameterByCode(deliverSm);
- smppMessage.setHeader(SmppConstants.OPTIONAL_PARAMETER,
optionalParameter);
- }
- } else {
- smppMessage.setHeader(SmppConstants.MESSAGE_TYPE,
SmppMessageType.DeliverSm.toString());
-
- if (deliverSm.getShortMessage() != null) {
- Alphabet alphabet =
Alphabet.parseDataCoding(deliverSm.getDataCoding());
- if (SmppUtils.is8Bit(alphabet)) {
- smppMessage.setBody(deliverSm.getShortMessage());
- } else {
- smppMessage.setBody(new
String(deliverSm.getShortMessage(), configuration.getEncoding()));
- }
- } else if (messagePayload != null) {
- smppMessage.setBody(messagePayload);
- }
-
- smppMessage.setHeader(SmppConstants.SEQUENCE_NUMBER,
deliverSm.getSequenceNumber());
- smppMessage.setHeader(SmppConstants.COMMAND_ID,
deliverSm.getCommandId());
- smppMessage.setHeader(SmppConstants.SOURCE_ADDR,
deliverSm.getSourceAddr());
- smppMessage.setHeader(SmppConstants.SOURCE_ADDR_NPI,
deliverSm.getSourceAddrNpi());
- smppMessage.setHeader(SmppConstants.SOURCE_ADDR_TON,
deliverSm.getSourceAddrTon());
- smppMessage.setHeader(SmppConstants.DATA_CODING,
deliverSm.getDataCoding());
- smppMessage.setHeader(SmppConstants.DEST_ADDR,
deliverSm.getDestAddress());
- smppMessage.setHeader(SmppConstants.DEST_ADDR_NPI,
deliverSm.getDestAddrNpi());
- smppMessage.setHeader(SmppConstants.DEST_ADDR_TON,
deliverSm.getDestAddrTon());
- smppMessage.setHeader(SmppConstants.SCHEDULE_DELIVERY_TIME,
deliverSm.getScheduleDeliveryTime());
- smppMessage.setHeader(SmppConstants.VALIDITY_PERIOD,
deliverSm.getValidityPeriod());
- smppMessage.setHeader(SmppConstants.SERVICE_TYPE,
deliverSm.getServiceType());
- }
-
- return smppMessage;
- }
-
- private Map<String, Object> createOptionalParameterByName(DeliverSm
deliverSm) {
- List<OptionalParameter> oplist =
Arrays.asList(deliverSm.getOptionalParameters());
-
- Map<String, Object> optParams = new HashMap<>();
- for (OptionalParameter optPara : oplist) {
- try {
- Tag valueOfTag = OptionalParameter.Tag.valueOf(optPara.tag);
- if (valueOfTag != null) {
- if (COctetString.class.isInstance(optPara)) {
- optParams.put(valueOfTag.toString(), ((COctetString)
optPara).getValueAsString());
- } else if
(org.jsmpp.bean.OptionalParameter.OctetString.class.isInstance(optPara)) {
- optParams.put(valueOfTag.toString(), ((OctetString)
optPara).getValueAsString());
- } else if
(org.jsmpp.bean.OptionalParameter.Byte.class.isInstance(optPara)) {
- optParams.put(valueOfTag.toString(),
-
Byte.valueOf(((org.jsmpp.bean.OptionalParameter.Byte) optPara).getValue()));
- } else if
(org.jsmpp.bean.OptionalParameter.Short.class.isInstance(optPara)) {
- optParams.put(valueOfTag.toString(),
-
Short.valueOf(((org.jsmpp.bean.OptionalParameter.Short) optPara).getValue()));
- } else if
(org.jsmpp.bean.OptionalParameter.Int.class.isInstance(optPara)) {
- optParams.put(valueOfTag.toString(),
-
Integer.valueOf(((org.jsmpp.bean.OptionalParameter.Int) optPara).getValue()));
- } else if (Null.class.isInstance(optPara)) {
- optParams.put(valueOfTag.toString(), null);
- }
- } else {
- LOG.debug("Skipping optional parameter with tag {} because
it was not recognized", optPara.tag);
- }
- } catch (IllegalArgumentException e) {
- LOG.debug("Skipping optional parameter with tag {} due to {}",
optPara.tag, e.getMessage());
- }
- }
-
- return optParams;
- }
-
- private Map<Short, Object> createOptionalParameterByCode(DeliverSm
deliverSm) {
- List<OptionalParameter> oplist =
Arrays.asList(deliverSm.getOptionalParameters());
-
- Map<Short, Object> optParams = new HashMap<>();
- for (OptionalParameter optPara : oplist) {
- if (COctetString.class.isInstance(optPara)) {
- optParams.put(Short.valueOf(optPara.tag), ((COctetString)
optPara).getValueAsString());
- } else if
(org.jsmpp.bean.OptionalParameter.OctetString.class.isInstance(optPara)) {
- optParams.put(Short.valueOf(optPara.tag), ((OctetString)
optPara).getValue());
- } else if
(org.jsmpp.bean.OptionalParameter.Byte.class.isInstance(optPara)) {
- optParams.put(Short.valueOf(optPara.tag),
- Byte.valueOf(((org.jsmpp.bean.OptionalParameter.Byte)
optPara).getValue()));
- } else if
(org.jsmpp.bean.OptionalParameter.Short.class.isInstance(optPara)) {
- optParams.put(Short.valueOf(optPara.tag),
-
Short.valueOf(((org.jsmpp.bean.OptionalParameter.Short) optPara).getValue()));
- } else if
(org.jsmpp.bean.OptionalParameter.Int.class.isInstance(optPara)) {
- optParams.put(Short.valueOf(optPara.tag),
-
Integer.valueOf(((org.jsmpp.bean.OptionalParameter.Int) optPara).getValue()));
- } else if (Null.class.isInstance(optPara)) {
- optParams.put(Short.valueOf(optPara.tag), null);
- }
- }
-
- return optParams;
- }
-
- public SmppMessage createSmppMessage(CamelContext camelContext, DataSm
dataSm, String smppMessageId) {
- SmppMessage smppMessage = new SmppMessage(camelContext, dataSm,
configuration);
-
- smppMessage.setHeader(SmppConstants.MESSAGE_TYPE,
SmppMessageType.DataSm.toString());
- smppMessage.setHeader(SmppConstants.ID, smppMessageId);
- smppMessage.setHeader(SmppConstants.SEQUENCE_NUMBER,
dataSm.getSequenceNumber());
- smppMessage.setHeader(SmppConstants.COMMAND_ID, dataSm.getCommandId());
- smppMessage.setHeader(SmppConstants.COMMAND_STATUS,
dataSm.getCommandStatus());
- smppMessage.setHeader(SmppConstants.SOURCE_ADDR,
dataSm.getSourceAddr());
- smppMessage.setHeader(SmppConstants.SOURCE_ADDR_NPI,
dataSm.getSourceAddrNpi());
- smppMessage.setHeader(SmppConstants.SOURCE_ADDR_TON,
dataSm.getSourceAddrTon());
- smppMessage.setHeader(SmppConstants.DEST_ADDR,
dataSm.getDestAddress());
- smppMessage.setHeader(SmppConstants.DEST_ADDR_NPI,
dataSm.getDestAddrNpi());
- smppMessage.setHeader(SmppConstants.DEST_ADDR_TON,
dataSm.getDestAddrTon());
- smppMessage.setHeader(SmppConstants.SERVICE_TYPE,
dataSm.getServiceType());
- smppMessage.setHeader(SmppConstants.REGISTERED_DELIVERY,
dataSm.getRegisteredDelivery());
- smppMessage.setHeader(SmppConstants.DATA_CODING,
dataSm.getDataCoding());
-
- return smppMessage;
- }
-
- /**
- * Returns the current date. Externalized for better test support.
- *
- * @return the current date
- */
- Date getCurrentDate() {
- return new Date();
- }
-
- /**
- * Returns the smpp configuration
- *
- * @return the configuration
- */
- public SmppConfiguration getConfiguration() {
- return configuration;
- }
-
- /**
- * Set the smpp configuration.
- *
- * @param configuration smppConfiguration
- */
- public void setConfiguration(SmppConfiguration configuration) {
- this.configuration = configuration;
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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.
+ */
+package org.apache.camel.component.smpp;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.jsmpp.bean.AlertNotification;
+import org.jsmpp.bean.Command;
+import org.jsmpp.bean.DataSm;
+import org.jsmpp.bean.DeliverSm;
+import org.jsmpp.bean.DeliveryReceipt;
+import org.jsmpp.bean.OptionalParameter;
+import org.jsmpp.bean.OptionalParameter.COctetString;
+import org.jsmpp.bean.OptionalParameter.Null;
+import org.jsmpp.bean.OptionalParameter.OctetString;
+import org.jsmpp.bean.OptionalParameter.Tag;
+import org.jsmpp.session.SMPPSession;
+import org.jsmpp.util.DefaultDecomposer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A Strategy used to convert between a Camel {@link Exchange} and {@link
SmppMessage} to and from a SMPP
+ * {@link Command}
+ */
+public class SmppBinding {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(SmppBinding.class);
+
+ private SmppConfiguration configuration;
+
+ public SmppBinding() {
+ this.configuration = new SmppConfiguration();
+ }
+
+ public SmppBinding(SmppConfiguration configuration) {
+ this.configuration = configuration;
+ }
+
+ /**
+ * Create the SmppCommand object from the inbound exchange
+ *
+ * @throws UnsupportedEncodingException if the encoding is not supported
+ */
+ public SmppCommand createSmppCommand(SMPPSession session, Exchange
exchange) {
+ SmppCommandType commandType = SmppCommandType.fromExchange(exchange);
+ SmppCommand command = commandType.createCommand(session,
configuration);
+
+ return command;
+ }
+
+ /**
+ * Create a new SmppMessage from the inbound alert notification
+ */
+ public SmppMessage createSmppMessage(CamelContext camelContext,
AlertNotification alertNotification) {
+ SmppMessage smppMessage = new SmppMessage(camelContext,
alertNotification, configuration);
+
+ smppMessage.setHeader(SmppConstants.MESSAGE_TYPE,
SmppMessageType.AlertNotification.toString());
+ smppMessage.setHeader(SmppConstants.SEQUENCE_NUMBER,
alertNotification.getSequenceNumber());
+ smppMessage.setHeader(SmppConstants.COMMAND_ID,
alertNotification.getCommandId());
+ smppMessage.setHeader(SmppConstants.COMMAND_STATUS,
alertNotification.getCommandStatus());
+ smppMessage.setHeader(SmppConstants.SOURCE_ADDR,
alertNotification.getSourceAddr());
+ smppMessage.setHeader(SmppConstants.SOURCE_ADDR_NPI,
alertNotification.getSourceAddrNpi());
+ smppMessage.setHeader(SmppConstants.SOURCE_ADDR_TON,
alertNotification.getSourceAddrTon());
+ smppMessage.setHeader(SmppConstants.ESME_ADDR,
alertNotification.getEsmeAddr());
+ smppMessage.setHeader(SmppConstants.ESME_ADDR_NPI,
alertNotification.getEsmeAddrNpi());
+ smppMessage.setHeader(SmppConstants.ESME_ADDR_TON,
alertNotification.getEsmeAddrTon());
+
+ return smppMessage;
+ }
+
+ /**
+ * Create a new SmppMessage from the inbound deliver sm or deliver receipt
+ */
+ public SmppMessage createSmppMessage(CamelContext camelContext, DeliverSm
deliverSm) throws Exception {
+ SmppMessage smppMessage = new SmppMessage(camelContext, deliverSm,
configuration);
+
+ byte[] body = SmppUtils.getMessageBody(deliverSm);
+ String decodedBody = SmppUtils.decodeBody(body,
deliverSm.getDataCoding(), configuration.getEncoding());
+
+ if (deliverSm.isSmscDeliveryReceipt()) {
+ smppMessage.setHeader(SmppConstants.MESSAGE_TYPE,
SmppMessageType.DeliveryReceipt.toString());
+
+ DeliveryReceipt smscDeliveryReceipt = null;
+ if (decodedBody != null) {
+ smscDeliveryReceipt =
DefaultDecomposer.getInstance().deliveryReceipt(decodedBody);
+ } else if (body != null) {
+ // fallback approach
+ smscDeliveryReceipt =
DefaultDecomposer.getInstance().deliveryReceipt(body);
+ }
+
+ if (smscDeliveryReceipt != null) {
+ smppMessage.setBody(smscDeliveryReceipt.getText());
+
+ smppMessage.setHeader(SmppConstants.ID,
smscDeliveryReceipt.getId());
+ smppMessage.setHeader(SmppConstants.DELIVERED,
smscDeliveryReceipt.getDelivered());
+ smppMessage.setHeader(SmppConstants.DONE_DATE,
smscDeliveryReceipt.getDoneDate());
+ if (!"000".equals(smscDeliveryReceipt.getError())) {
+ smppMessage.setHeader(SmppConstants.ERROR,
smscDeliveryReceipt.getError());
+ }
+ smppMessage.setHeader(SmppConstants.SUBMIT_DATE,
smscDeliveryReceipt.getSubmitDate());
+ smppMessage.setHeader(SmppConstants.SUBMITTED,
smscDeliveryReceipt.getSubmitted());
+ smppMessage.setHeader(SmppConstants.FINAL_STATUS,
smscDeliveryReceipt.getFinalStatus());
+ }
+ } else {
+ smppMessage.setHeader(SmppConstants.MESSAGE_TYPE,
SmppMessageType.DeliverSm.toString());
+
+ if (body != null) {
+ smppMessage.setBody((decodedBody != null) ? decodedBody :
body);
+ }
+
+ smppMessage.setHeader(SmppConstants.SEQUENCE_NUMBER,
deliverSm.getSequenceNumber());
+ smppMessage.setHeader(SmppConstants.COMMAND_ID,
deliverSm.getCommandId());
+ smppMessage.setHeader(SmppConstants.SOURCE_ADDR,
deliverSm.getSourceAddr());
+ smppMessage.setHeader(SmppConstants.SOURCE_ADDR_NPI,
deliverSm.getSourceAddrNpi());
+ smppMessage.setHeader(SmppConstants.SOURCE_ADDR_TON,
deliverSm.getSourceAddrTon());
+ smppMessage.setHeader(SmppConstants.DATA_CODING,
deliverSm.getDataCoding());
+ smppMessage.setHeader(SmppConstants.DEST_ADDR,
deliverSm.getDestAddress());
+ smppMessage.setHeader(SmppConstants.DEST_ADDR_NPI,
deliverSm.getDestAddrNpi());
+ smppMessage.setHeader(SmppConstants.DEST_ADDR_TON,
deliverSm.getDestAddrTon());
+ smppMessage.setHeader(SmppConstants.SCHEDULE_DELIVERY_TIME,
deliverSm.getScheduleDeliveryTime());
+ smppMessage.setHeader(SmppConstants.VALIDITY_PERIOD,
deliverSm.getValidityPeriod());
+ smppMessage.setHeader(SmppConstants.SERVICE_TYPE,
deliverSm.getServiceType());
+ }
+
+ if (deliverSm.getOptionalParameters() != null &&
deliverSm.getOptionalParameters().length > 0) {
+ // the deprecated way
+ Map<String, Object> optionalParameters =
createOptionalParameterByName(deliverSm);
+ smppMessage.setHeader(SmppConstants.OPTIONAL_PARAMETERS,
optionalParameters);
+
+ // the new way
+ Map<Short, Object> optionalParameter =
createOptionalParameterByCode(deliverSm);
+ smppMessage.setHeader(SmppConstants.OPTIONAL_PARAMETER,
optionalParameter);
+ }
+ return smppMessage;
+ }
+
+ private Map<String, Object> createOptionalParameterByName(DeliverSm
deliverSm) {
+ Map<String, Object> optParams = new HashMap<>();
+ for (OptionalParameter optPara : deliverSm.getOptionalParameters()) {
+ try {
+ Tag valueOfTag = OptionalParameter.Tag.valueOf(optPara.tag);
+ if (valueOfTag != null) {
+ if (optPara instanceof COctetString) {
+ optParams.put(valueOfTag.toString(), ((COctetString)
optPara).getValueAsString());
+ } else if (optPara instanceof OctetString) {
+ optParams.put(valueOfTag.toString(), ((OctetString)
optPara).getValueAsString());
+ } else if (optPara instanceof OptionalParameter.Byte) {
+ optParams.put(valueOfTag.toString(),
+ ((OptionalParameter.Byte) optPara).getValue());
+ } else if (optPara instanceof OptionalParameter.Short) {
+ optParams.put(valueOfTag.toString(),
+ ((OptionalParameter.Short)
optPara).getValue());
+ } else if (optPara instanceof OptionalParameter.Int) {
+ optParams.put(valueOfTag.toString(),
+ ((OptionalParameter.Int) optPara).getValue());
+ } else if (optPara instanceof Null) {
+ optParams.put(valueOfTag.toString(), null);
+ }
+ } else {
+ LOG.debug("Skipping optional parameter with tag {} because
it was not recognized", optPara.tag);
+ }
+ } catch (IllegalArgumentException e) {
+ LOG.debug("Skipping optional parameter with tag {} due to {}",
optPara.tag, e.getMessage());
+ }
+ }
+ return optParams;
+ }
+
+ private Map<Short, Object> createOptionalParameterByCode(DeliverSm
deliverSm) {
+ Map<Short, Object> optParams = new HashMap<>();
+ for (OptionalParameter optPara : deliverSm.getOptionalParameters()) {
+ if (optPara instanceof COctetString) {
+ optParams.put(optPara.tag, ((COctetString)
optPara).getValueAsString());
+ } else if (optPara instanceof OctetString) {
+ optParams.put(optPara.tag, ((OctetString) optPara).getValue());
+ } else if (optPara instanceof OptionalParameter.Byte) {
+ optParams.put(optPara.tag,
+ ((OptionalParameter.Byte) optPara).getValue());
+ } else if (optPara instanceof OptionalParameter.Short) {
+ optParams.put(optPara.tag,
+ ((OptionalParameter.Short) optPara).getValue());
+ } else if (optPara instanceof OptionalParameter.Int) {
+ optParams.put(optPara.tag,
+ ((OptionalParameter.Int) optPara).getValue());
+ } else if (optPara instanceof Null) {
+ optParams.put(optPara.tag, null);
+ }
+ }
+ return optParams;
+ }
+
+ public SmppMessage createSmppMessage(CamelContext camelContext, DataSm
dataSm, String smppMessageId) {
+ SmppMessage smppMessage = new SmppMessage(camelContext, dataSm,
configuration);
+
+ smppMessage.setHeader(SmppConstants.MESSAGE_TYPE,
SmppMessageType.DataSm.toString());
+ smppMessage.setHeader(SmppConstants.ID, smppMessageId);
+ smppMessage.setHeader(SmppConstants.SEQUENCE_NUMBER,
dataSm.getSequenceNumber());
+ smppMessage.setHeader(SmppConstants.COMMAND_ID, dataSm.getCommandId());
+ smppMessage.setHeader(SmppConstants.COMMAND_STATUS,
dataSm.getCommandStatus());
+ smppMessage.setHeader(SmppConstants.SOURCE_ADDR,
dataSm.getSourceAddr());
+ smppMessage.setHeader(SmppConstants.SOURCE_ADDR_NPI,
dataSm.getSourceAddrNpi());
+ smppMessage.setHeader(SmppConstants.SOURCE_ADDR_TON,
dataSm.getSourceAddrTon());
+ smppMessage.setHeader(SmppConstants.DEST_ADDR,
dataSm.getDestAddress());
+ smppMessage.setHeader(SmppConstants.DEST_ADDR_NPI,
dataSm.getDestAddrNpi());
+ smppMessage.setHeader(SmppConstants.DEST_ADDR_TON,
dataSm.getDestAddrTon());
+ smppMessage.setHeader(SmppConstants.SERVICE_TYPE,
dataSm.getServiceType());
+ smppMessage.setHeader(SmppConstants.REGISTERED_DELIVERY,
dataSm.getRegisteredDelivery());
+ smppMessage.setHeader(SmppConstants.DATA_CODING,
dataSm.getDataCoding());
+
+ return smppMessage;
+ }
+
+ /**
+ * Returns the current date. Externalized for better test support.
+ *
+ * @return the current date
+ */
+ Date getCurrentDate() {
+ return new Date();
+ }
+
+ /**
+ * Returns the smpp configuration
+ *
+ * @return the configuration
+ */
+ public SmppConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ /**
+ * Set the smpp configuration.
+ *
+ * @param configuration smppConfiguration
+ */
+ public void setConfiguration(SmppConfiguration configuration) {
+ this.configuration = configuration;
+ }
+}
diff --git
a/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppUtils.java
b/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppUtils.java
index 44867e01e20..904f9d2422e 100644
---
a/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppUtils.java
+++
b/components/camel-smpp/src/main/java/org/apache/camel/component/smpp/SmppUtils.java
@@ -16,6 +16,8 @@
*/
package org.apache.camel.component.smpp;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Calendar;
import java.util.Date;
@@ -31,6 +33,10 @@ import org.apache.camel.support.task.Tasks;
import org.apache.camel.support.task.budget.Budgets;
import org.jsmpp.bean.Alphabet;
import org.jsmpp.bean.DataSm;
+import org.jsmpp.bean.DeliverSm;
+import org.jsmpp.bean.OptionalParameter;
+import org.jsmpp.bean.OptionalParameter.OctetString;
+import org.jsmpp.bean.OptionalParameter.Tag;
import org.jsmpp.bean.SubmitMulti;
import org.jsmpp.bean.SubmitSm;
import org.jsmpp.extra.SessionState;
@@ -127,6 +133,24 @@ public final class SmppUtils {
}
}
+ /**
+ * Returns the payload of a deliverSm
+ *
+ * @param deliverSm
+ * @return the shortMessage, by first looking in the
shortMessage field of the deliver_sm and if its null
+ * or empty, fallbacks to the optional parameter
"MESSAGE_PAYLOAD".
+ */
+ public static byte[] getMessageBody(DeliverSm deliverSm) {
+ byte[] body = deliverSm.getShortMessage();
+ if (body == null || body.length == 0) {
+ OptionalParameter param =
deliverSm.getOptionalParameter(Tag.MESSAGE_PAYLOAD);
+ if (param instanceof OctetString) {
+ body = ((OctetString) param).getValue();
+ }
+ }
+ return body;
+ }
+
public static boolean is8Bit(Alphabet alphabet) {
return alphabet == Alphabet.ALPHA_UNSPECIFIED_2 || alphabet ==
Alphabet.ALPHA_8_BIT;
}
@@ -319,4 +343,33 @@ public final class SmppUtils {
service.shutdownNow();
}
}
+
+ /**
+ * This method would try to decode the bytes provided a dataCoding.
+ *
+ * Supports: US_ASCII, ISO_8859_1, UTF_16_BE alphabet values
+ *
+ * @param body Body of the message in bytes
+ * @param dataCoding The data coding value
+ * @param defaultEncoding The default encoding
+ * @return null if body is null or 8bit
encoded, or the decoded body on success
+ * @throws UnsupportedEncodingException when the default encoding is
unsupported
+ */
+ public static String decodeBody(byte[] body, byte dataCoding, String
defaultEncoding)
+ throws UnsupportedEncodingException {
+ Alphabet alphabet = Alphabet.parseDataCoding(dataCoding);
+ if (body == null || SmppUtils.is8Bit(alphabet)) {
+ return null;
+ }
+ switch (alphabet) {
+ case ALPHA_IA5:
+ return new String(body, StandardCharsets.US_ASCII);
+ case ALPHA_LATIN1:
+ return new String(body, StandardCharsets.ISO_8859_1);
+ case ALPHA_UCS2:
+ return new String(body, StandardCharsets.UTF_16BE);
+ default:
+ return new String(body, defaultEncoding);
+ }
+ }
}
diff --git
a/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppBindingTest.java
b/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppBindingTest.java
index 9aa6eace93f..6a86d3e2201 100644
---
a/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppBindingTest.java
+++
b/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppBindingTest.java
@@ -26,10 +26,14 @@ import org.apache.camel.Exchange;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.support.DefaultExchange;
import org.jsmpp.bean.AlertNotification;
+import org.jsmpp.bean.Alphabet;
import org.jsmpp.bean.DataSm;
import org.jsmpp.bean.DeliverSm;
+import org.jsmpp.bean.DeliveryReceipt;
+import org.jsmpp.bean.GeneralDataCoding;
import org.jsmpp.bean.NumberingPlanIndicator;
import org.jsmpp.bean.OptionalParameter;
+import org.jsmpp.bean.OptionalParameter.Message_payload;
import org.jsmpp.bean.OptionalParameter.OctetString;
import org.jsmpp.bean.OptionalParameter.Tag;
import org.jsmpp.bean.TypeOfNumber;
@@ -53,6 +57,7 @@ public class SmppBindingTest {
private SmppBinding binding;
private CamelContext camelContext;
+ private String defaultEncoding;
@BeforeEach
public void setUp() {
@@ -62,6 +67,7 @@ public class SmppBindingTest {
}
};
camelContext = new DefaultCamelContext();
+ defaultEncoding = binding.getConfiguration().getEncoding();
}
@Test
@@ -264,7 +270,7 @@ public class SmppBindingTest {
SmppMessage smppMessage = binding.createSmppMessage(camelContext,
deliverSm);
assertEquals("Hello SMPP world!", smppMessage.getBody());
- assertEquals(13, smppMessage.getHeaders().size());
+ assertEquals(15, smppMessage.getHeaders().size());
assertEquals(1, smppMessage.getHeader(SmppConstants.SEQUENCE_NUMBER));
assertEquals(1, smppMessage.getHeader(SmppConstants.COMMAND_ID));
assertEquals("1818", smppMessage.getHeader(SmppConstants.SOURCE_ADDR));
@@ -313,6 +319,45 @@ public class SmppBindingTest {
assertEquals(SmppMessageType.DataSm.toString(),
smppMessage.getHeader(SmppConstants.MESSAGE_TYPE));
}
+ @Test
+ void deliverSmWithEmptyBodyAndPayloadInOptionalParameter() throws
Exception {
+ DeliverSm deliverSm = new DeliverSm();
+ String payload = "Hellö SMPP wörld!";
+ deliverSm.setShortMessage(new byte[] {});
+ deliverSm.setDataCoding(new
GeneralDataCoding(Alphabet.ALPHA_DEFAULT).toByte());
+ deliverSm.setOptionalParameters(new
Message_payload(payload.getBytes(defaultEncoding)));
+ SmppMessage smppMessage = binding.createSmppMessage(camelContext,
deliverSm);
+
+ assertEquals(payload, smppMessage.getBody());
+ assertEquals(SmppMessageType.DeliverSm.toString(),
smppMessage.getHeader(SmppConstants.MESSAGE_TYPE));
+ }
+
+ @Test
+ void deliverSmDlrWithEmptyBodyAndPayloadInOptionalParameter() throws
Exception {
+
+ DeliveryReceipt dlr = new DeliveryReceipt();
+ dlr.setId("4");
+ dlr.setSubmitted(1);
+ dlr.setSubmitDate(binding.getCurrentDate());
+ dlr.setDoneDate(binding.getCurrentDate());
+ dlr.setFinalStatus(DeliveryReceiptState.UNDELIV);
+ dlr.setDelivered(1);
+ dlr.setError("000");
+ dlr.setText("Hellö SMPP wörld!");
+
+ DeliverSm deliverSm = new DeliverSm();
+ deliverSm.setShortMessage(new byte[] {});
+ deliverSm.setSmscDeliveryReceipt();
+ deliverSm.setDataCoding(new
GeneralDataCoding(Alphabet.ALPHA_DEFAULT).toByte());
+ deliverSm.setOptionalParameters(new
Message_payload(dlr.toString().getBytes(defaultEncoding)));
+
+ SmppMessage smppMessage = binding.createSmppMessage(camelContext,
deliverSm);
+ assertEquals(dlr.getText(), smppMessage.getBody(String.class));
+ assertEquals(dlr.getId(), smppMessage.getHeader(SmppConstants.ID));
+ assertEquals(dlr.getFinalStatus(),
smppMessage.getHeader(SmppConstants.FINAL_STATUS));
+ assertEquals(SmppMessageType.DeliveryReceipt.toString(),
smppMessage.getHeader(SmppConstants.MESSAGE_TYPE));
+ }
+
@Test
public void
createSmppMessageFrom8bitDataCodingDeliverSmShouldNotModifyBody() throws
Exception {
final Set<String> encodings = Charset.availableCharsets().keySet();
diff --git
a/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppUtilsTest.java
b/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppUtilsTest.java
index 1a2f5f39bde..fe5479486b8 100644
---
a/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppUtilsTest.java
+++
b/components/camel-smpp/src/test/java/org/apache/camel/component/smpp/SmppUtilsTest.java
@@ -16,13 +16,22 @@
*/
package org.apache.camel.component.smpp;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
+import java.util.stream.Stream;
+import org.jsmpp.bean.Alphabet;
import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -63,4 +72,35 @@ public class SmppUtilsTest {
assertEquals(10, calendar.get(Calendar.MINUTE));
assertEquals(0, calendar.get(Calendar.SECOND));
}
+
+ @ParameterizedTest
+ @MethodSource("decodeBodyProvider")
+ void testDecodeBodyWhenBodyIsNot8bitAlphabetTheContentShouldBeDecoded(
+ String content, Charset encoding, byte dataCoding, String
defaultEncoding)
+ throws UnsupportedEncodingException {
+ byte[] body = content.getBytes(encoding);
+ Assertions.assertEquals(content, SmppUtils.decodeBody(body,
dataCoding, defaultEncoding));
+ }
+
+ @Test
+ void testDecodeBodyWhenBodyIs8bitShouldReturnNull() throws
UnsupportedEncodingException {
+ byte[] body = new byte[] { 0, 1, 2, 3, 4 };
+ Assertions.assertNull(SmppUtils.decodeBody(body,
Alphabet.ALPHA_8_BIT.value(), "X-Gsm7Bit"));
+ }
+
+ @Test
+ void testDecodeBodyWithUnsupportedDefaultEncodingShouldThrow() throws
UnsupportedEncodingException {
+ Assertions.assertThrows(UnsupportedEncodingException.class, () -> {
+ SmppUtils.decodeBody(new byte[] { 0 },
Alphabet.ALPHA_DEFAULT.value(), "X-Gsm7Bit");
+ });
+ }
+
+ private static Stream<Arguments> decodeBodyProvider() {
+ return Stream.of(
+ Arguments.of("This is an ascii test !",
StandardCharsets.US_ASCII, Alphabet.ALPHA_IA5.value(), "X-Gsm7Bit"),
+ Arguments.of("This is a latin1 test ®",
StandardCharsets.ISO_8859_1, Alphabet.ALPHA_LATIN1.value(),
+ "X-Gsm7Bit"),
+ Arguments.of("This is a utf-16 test \uD83D\uDE00",
StandardCharsets.UTF_16BE, Alphabet.ALPHA_UCS2.value(),
+ "X-Gsm7Bit"));
+ }
}