diff --git a/features/poller/api/pom.xml b/features/poller/api/pom.xml
old mode 100644
new mode 100755
index c230467d2447..cff70d4519b2
--- a/features/poller/api/pom.xml
+++ b/features/poller/api/pom.xml
@@ -45,5 +45,24 @@
hibernate-jpa-2.0-api
provided
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+
+ org.eclipse.persistence
+ org.eclipse.persistence.core
+ ${eclipselinkVersion}
+ test
+
+
+ org.eclipse.persistence
+ org.eclipse.persistence.moxy
+ ${eclipselinkVersion}
+ test
+
-
+
\ No newline at end of file
diff --git a/features/poller/api/src/main/java/org/opennms/netmgt/poller/DeviceConfig.java b/features/poller/api/src/main/java/org/opennms/netmgt/poller/DeviceConfig.java
old mode 100644
new mode 100755
index f46f2c6509e8..ae1a644fc3fc
--- a/features/poller/api/src/main/java/org/opennms/netmgt/poller/DeviceConfig.java
+++ b/features/poller/api/src/main/java/org/opennms/netmgt/poller/DeviceConfig.java
@@ -32,6 +32,7 @@
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name="device-config")
@XmlAccessorType(XmlAccessType.NONE)
@@ -44,6 +45,7 @@ public class DeviceConfig {
private String filename;
@XmlAttribute(name="scriptOutput")
+ @XmlJavaTypeAdapter(EscapeSequenceAdapter.class)
private String scriptOutput;
public DeviceConfig(String scriptOutput) {
diff --git a/features/poller/api/src/main/java/org/opennms/netmgt/poller/EscapeSequenceAdapter.java b/features/poller/api/src/main/java/org/opennms/netmgt/poller/EscapeSequenceAdapter.java
new file mode 100755
index 000000000000..a810457fc67c
--- /dev/null
+++ b/features/poller/api/src/main/java/org/opennms/netmgt/poller/EscapeSequenceAdapter.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * This file is part of OpenNMS(R).
+ *
+ * Copyright (C) 2023 The OpenNMS Group, Inc.
+ * OpenNMS(R) is Copyright (C) 1999-2023 The OpenNMS Group, Inc.
+ *
+ * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
+ *
+ * OpenNMS(R) is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * OpenNMS(R) is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with OpenNMS(R). If not, see:
+ * http://www.gnu.org/licenses/
+ *
+ * For more information contact:
+ * OpenNMS(R) Licensing
+ * http://www.opennms.org/
+ * http://www.opennms.com/
+ *******************************************************************************/
+
+package org.opennms.netmgt.poller;
+
+import org.eclipse.persistence.exceptions.XMLMarshalException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+public class EscapeSequenceAdapter extends XmlAdapter {
+ private static final Logger LOG = LoggerFactory.getLogger(EscapeSequenceAdapter.class);
+
+ public EscapeSequenceAdapter() {
+
+ }
+
+ @Override
+ public String unmarshal(String v) throws Exception {
+ if (v != null) {
+ v = v.replace("
", "\r")
+ .replace("
", "\n");
+ }
+ try {
+ return v;
+ } catch (XMLMarshalException e) {
+ LOG.warn("Unable to unmarshal escape sequences value '{}' to a script output. Returning null instead.", v);
+ return null;
+ }
+ }
+
+ @Override
+ public String marshal(String v) throws Exception {
+ if (v != null) {
+ v = v.replace("\r", "
")
+ .replace("\n", "
");
+ }
+ try {
+ return v;
+ } catch (XMLMarshalException e) {
+ LOG.warn("Unable to marshal escape sequences value '{}' to a script output. Returning null instead.", v);
+ return null;
+ }
+ }
+}
diff --git a/features/poller/api/src/test/java/org/opennms/netmgt/poller/DeviceConfigTest.java b/features/poller/api/src/test/java/org/opennms/netmgt/poller/DeviceConfigTest.java
new file mode 100644
index 000000000000..ff3fb3c2ae5f
--- /dev/null
+++ b/features/poller/api/src/test/java/org/opennms/netmgt/poller/DeviceConfigTest.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * This file is part of OpenNMS(R).
+ *
+ * Copyright (C) 2023 The OpenNMS Group, Inc.
+ * OpenNMS(R) is Copyright (C) 1999-2023 The OpenNMS Group, Inc.
+ *
+ * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
+ *
+ * OpenNMS(R) is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * OpenNMS(R) is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with OpenNMS(R). If not, see:
+ * http://www.gnu.org/licenses/
+ *
+ * For more information contact:
+ * OpenNMS(R) Licensing
+ * http://www.opennms.org/
+ * http://www.opennms.com/
+ *******************************************************************************/
+
+package org.opennms.netmgt.poller;
+
+import org.eclipse.persistence.jaxb.JAXBContext;
+import org.eclipse.persistence.jaxb.JAXBContextFactory;
+import org.junit.Test;
+
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+
+public class DeviceConfigTest {
+
+ @Test
+ public void testMarshalling() throws javax.xml.bind.JAXBException {
+ String scriptOutput = "HP J8692A Switch 3500yl-24G\r\r\nSoftware revision K.16.02.0026\r\r\n\r\r\n" +
+ " (C) Copyright 2018 Hewlett Packard Enterprise Development LP\r\n" +
+ "RESTRICTED RIGHTS LEGEND\r\n Confidential computer software. Valid license from Hewlett Packard Enterprise\r\n" +
+ "Development LP required for possession, use or copying. Consistent with FAR\r\n" +
+ "12.211 and 12.212, Commercial Computer Software, Computer Software\r\n" +
+ "Documentation, and Technical Data for Commercial Items are licensed to the\r\n" +
+ "U.S. Government under vendor's standard commercial license.\r\n" +
+ "^[[1;13r^[[1;1H^[[24;1HPress any key to continue\r\n" +
+ "^[[13;1H^[[?25h^[[24;27H^[[?6l^[[1;24r^[[?7h^[[2J^[[1;1H^[[1920;1920H^[[6n^[[1;1H";
+
+ DeviceConfig deviceConfig = new DeviceConfig(scriptOutput);
+ JAXBContext jaxbContext = (JAXBContext) JAXBContextFactory.createContext(new Class[]{DeviceConfig.class}, null);
+
+ Marshaller marshaller = jaxbContext.createMarshaller();
+ StringWriter stringWriter = new StringWriter();
+ marshaller.marshal(deviceConfig, stringWriter);
+ String xmlOutput = stringWriter.toString();
+
+ assertNotNull(xmlOutput);
+ assertEquals("",xmlOutput);
+
+ }
+
+ @Test
+ public void testUnmarshalling() throws javax.xml.bind.JAXBException {
+
+ String xmlInput = "";
+
+ JAXBContext jaxbContext = (JAXBContext) JAXBContextFactory.createContext(new Class[]{DeviceConfig.class}, null);
+ Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+
+ StringReader stringReader = new StringReader(xmlInput);
+ DeviceConfig deviceConfig = (DeviceConfig) unmarshaller.unmarshal(stringReader);
+
+ String expectedOutputStartWith = "HP J8692A Switch 3500yl-24G\r\r\nSoftware revision K.16.02.0026\r\r\n\r\r\n" +
+ " (C) Copyright 2018 Hewlett Packard Enterprise Development LP\r\n" ;
+ String expectedOutputEndWith = "^[[1;13r^[[1;1H^[[24;1HPress any key to continue^[[13;1H^[[?25h^[[24;27H^[[?6l^[[1;24r^[[?7h^[[2J^[[1;1H^[[1920;1920H^[[6n^[[1;1H";
+ String expectedOutputMiddleString = "12.211 and 12.212, Commercial Computer Software, Computer Software\r\n" +
+ "Documentation, and Technical Data for Commercial Items are licensed to the\r\n" ;
+
+ assertNotNull(deviceConfig);
+ assertTrue(deviceConfig.getScriptOutput().contains(expectedOutputStartWith));
+ assertTrue(deviceConfig.getScriptOutput().contains(expectedOutputMiddleString));
+ assertTrue(deviceConfig.getScriptOutput().contains(expectedOutputEndWith));
+ }
+}
diff --git a/features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java b/features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java
new file mode 100755
index 000000000000..7228c69a4b03
--- /dev/null
+++ b/features/poller/api/src/test/java/org/opennms/netmgt/poller/EscapeSequenceAdapterTest.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * This file is part of OpenNMS(R).
+ *
+ * Copyright (C) 2023 The OpenNMS Group, Inc.
+ * OpenNMS(R) is Copyright (C) 1999-2023 The OpenNMS Group, Inc.
+ *
+ * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
+ *
+ * OpenNMS(R) is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * OpenNMS(R) is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with OpenNMS(R). If not, see:
+ * http://www.gnu.org/licenses/
+ *
+ * For more information contact:
+ * OpenNMS(R) Licensing
+ * http://www.opennms.org/
+ * http://www.opennms.com/
+ *******************************************************************************/
+
+package org.opennms.netmgt.poller;
+
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+
+
+public class EscapeSequenceAdapterTest {
+
+ private EscapeSequenceAdapter adapter;
+
+ @Before
+ public void setUp() {
+ adapter = new EscapeSequenceAdapter();
+ }
+
+ @Test
+ public void testUnmarshalWithEscapeSequences() throws Exception {
+ String input = "Hello
World
Test";
+ String expected = "Hello\rWorld\nTest";
+ String result = adapter.unmarshal(input);
+ assertNotNull(result, "Result should not be null");
+ assertEquals("Escape sequences should be replaced correctly", expected, result);
+ }
+
+ @Test
+ public void testUnmarshalWithNullValue() throws Exception {
+ String result = adapter.unmarshal(null);
+ assertNull("Null input should return null", result);
+ }
+
+ @Test
+ public void testMarshalWithSpecialCharacters() throws Exception {
+ String input = "Hello\rWorld\nTest";
+ String expected = "Hello
World
Test";
+ String result = adapter.marshal(input);
+ assertNotNull(result,"Result should not be null");
+ assertEquals("Special characters should be converted to escape sequences",expected, result);
+ }
+ @Test
+ public void testMarshalWithNullValue() throws Exception {
+ String result = adapter.marshal(null);
+ assertNull("Null input should return null",result);
+ }
+
+ @Test
+ public void testUnmarshalWithNoEscapeSequences() throws Exception {
+ String input = "NoEscapeSequenceHere";
+ String expected = "NoEscapeSequenceHere";
+ String result = adapter.unmarshal(input);
+ assertNotNull( "Result should not be null",result);
+ assertEquals("Input without escape sequences should remain unchanged",expected, result);
+ }
+
+ @Test
+ public void testMarshalWithNoSpecialCharacters() throws Exception {
+ String input = "NormalString";
+ String expected = "NormalString";
+ String result = adapter.marshal(input);
+ assertNotNull( "Result should not be null",result);
+ assertEquals( "Input without special characters should remain unchanged",expected, result);
+ }
+}