--- /dev/null
+/*
+ * Copyright (c) 2017 Bell Canada. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netconf.api;
+
+/**
+ * FailedNetconfMessage represents a wrapper around NetconfMessage.
+ */
+public class FailedNetconfMessage extends NetconfMessage {
+
+ private Throwable exception;
+
+ public FailedNetconfMessage(final Throwable exception) {
+ this.exception = exception;
+ }
+
+ public Throwable getException() {
+ return this.exception;
+ }
+}
private final Document doc;
+ public NetconfMessage() {
+ // Required for FailedNetconfMessage
+ this.doc = null;
+ }
+
public NetconfMessage(final Document doc) {
this.doc = doc;
}
import java.io.IOException;
import java.util.List;
import org.opendaylight.controller.config.util.xml.XmlUtil;
+import org.opendaylight.netconf.api.FailedNetconfMessage;
import org.opendaylight.netconf.api.NetconfMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
public final class NetconfXMLToMessageDecoder extends ByteToMessageDecoder {
private static final Logger LOG = LoggerFactory.getLogger(NetconfXMLToMessageDecoder.class);
}
}
if (in.isReadable()) {
- out.add(new NetconfMessage(XmlUtil.readXmlToDocument(new ByteBufInputStream(in))));
+ NetconfMessage msg;
+
+ try {
+ msg = new NetconfMessage(XmlUtil.readXmlToDocument(new ByteBufInputStream(in)));
+ } catch (SAXParseException exception) {
+ LOG.error("Failed to parse received message", exception);
+ msg = new FailedNetconfMessage(exception);
+ }
+
+ out.add(msg);
} else {
LOG.debug("No more content in incoming buffer.");
}
package org.opendaylight.netconf.nettyutil.handler;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import com.google.common.collect.Lists;
import io.netty.buffer.Unpooled;
import java.util.ArrayList;
import org.junit.Test;
+import org.opendaylight.netconf.api.FailedNetconfMessage;
+import org.opendaylight.netconf.api.NetconfMessage;
import org.xml.sax.SAXParseException;
public class NetconfXMLToMessageDecoderTest {
assertEquals(1, out.size());
}
- @Test(expected=SAXParseException.class)
+ @Test
public void testDecodeGibberish() throws Exception {
/* Test that we reject inputs where we cannot find the xml start '<' character */
final ArrayList<Object> out = Lists.newArrayList();
new NetconfXMLToMessageDecoder().decode(null, Unpooled.wrappedBuffer("\r\n?xml version>".getBytes()), out);
assertEquals(1, out.size());
+ assertTrue(FailedNetconfMessage.class.isInstance(out.get(0)));
+ assertTrue(((FailedNetconfMessage) out.get(0)).getException().getClass().isAssignableFrom(SAXParseException.class));
}
@Test
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+
+import org.opendaylight.controller.config.util.xml.DocumentedException;
import org.opendaylight.controller.config.util.xml.XmlElement;
import org.opendaylight.controller.config.util.xml.XmlUtil;
+import org.opendaylight.netconf.api.FailedNetconfMessage;
import org.opendaylight.netconf.api.NetconfDocumentedException;
import org.opendaylight.netconf.api.NetconfMessage;
import org.opendaylight.netconf.api.NetconfTerminationReason;
if( request != null ) {
+ if (FailedNetconfMessage.class.isInstance(message)) {
+ request.future.set(NetconfMessageTransformUtil.toRpcResult((FailedNetconfMessage) message));
+ return;
+ }
+
LOG.debug("{}: Message received {}", id, message);
if(LOG.isTraceEnabled()) {
}
private static boolean isNotification(final NetconfMessage message) {
+ if (message.getDocument() == null) {
+ // We have no message, which mean we have a FailedNetconfMessage
+ return false;
+ }
final XmlElement xmle = XmlElement.fromDomDocument(message.getDocument());
return XmlNetconfConstants.NOTIFICATION_ELEMENT_NAME.equals(xmle.getName()) ;
}
import org.opendaylight.controller.config.util.xml.DocumentedException;
import org.opendaylight.controller.config.util.xml.XmlElement;
import org.opendaylight.controller.config.util.xml.XmlUtil;
+import org.opendaylight.netconf.api.FailedNetconfMessage;
import org.opendaylight.netconf.api.NetconfDocumentedException;
import org.opendaylight.netconf.api.NetconfMessage;
import org.opendaylight.netconf.notifications.NetconfNotification;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.RpcError;
import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
+import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
import org.opendaylight.yangtools.yang.data.api.ModifyAction;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
}
}
}
+
+ public static RpcResult<NetconfMessage> toRpcResult(final FailedNetconfMessage message) {
+ return RpcResultBuilder.<NetconfMessage>failed()
+ .withRpcError(
+ toRpcError(
+ new NetconfDocumentedException(
+ message.getException().getMessage(),
+ DocumentedException.ErrorType.APPLICATION,
+ DocumentedException.ErrorTag.MALFORMED_MESSAGE,
+ DocumentedException.ErrorSeverity.ERROR)))
+ .build();
+ }
}