Fix checkstyle
[netconf.git] / netconf / netconf-util / src / main / java / org / opendaylight / netconf / util / messages / SendErrorExceptionUtil.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.netconf.util.messages;
10
11 import com.google.common.base.Preconditions;
12 import io.netty.channel.Channel;
13 import io.netty.channel.ChannelFuture;
14 import io.netty.channel.ChannelFutureListener;
15 import javax.xml.XMLConstants;
16 import org.opendaylight.netconf.api.DocumentedException;
17 import org.opendaylight.netconf.api.NetconfMessage;
18 import org.opendaylight.netconf.api.NetconfSession;
19 import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
20 import org.opendaylight.netconf.api.xml.XmlUtil;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23 import org.w3c.dom.Attr;
24 import org.w3c.dom.Document;
25 import org.w3c.dom.Element;
26 import org.w3c.dom.NamedNodeMap;
27
28 public final class SendErrorExceptionUtil {
29     private static final Logger LOG = LoggerFactory.getLogger(SendErrorExceptionUtil.class);
30
31     private SendErrorExceptionUtil() {
32
33     }
34
35     public static void sendErrorMessage(final NetconfSession session,
36             final DocumentedException sendErrorException) {
37         LOG.trace("Sending error", sendErrorException);
38         final Document errorDocument = createDocument(sendErrorException);
39         ChannelFuture channelFuture = session.sendMessage(new NetconfMessage(errorDocument));
40         channelFuture.addListener(new SendErrorVerifyingListener(sendErrorException));
41     }
42
43     public static void sendErrorMessage(final Channel channel, final DocumentedException sendErrorException) {
44         LOG.trace("Sending error", sendErrorException);
45         final Document errorDocument = createDocument(sendErrorException);
46         ChannelFuture channelFuture = channel.writeAndFlush(new NetconfMessage(errorDocument));
47         channelFuture.addListener(new SendErrorVerifyingListener(sendErrorException));
48     }
49
50     public static void sendErrorMessage(final NetconfSession session, final DocumentedException sendErrorException,
51             final NetconfMessage incommingMessage) {
52         final Document errorDocument = createDocument(sendErrorException);
53         if (LOG.isTraceEnabled()) {
54             LOG.trace("Sending error {}", XmlUtil.toString(errorDocument));
55         }
56
57         tryToCopyAttributes(incommingMessage.getDocument(), errorDocument, sendErrorException);
58         ChannelFuture channelFuture = session.sendMessage(new NetconfMessage(errorDocument));
59         channelFuture.addListener(new SendErrorVerifyingListener(sendErrorException));
60     }
61
62     @SuppressWarnings("checkstyle:IllegalCatch")
63     private static void tryToCopyAttributes(final Document incommingDocument, final Document errorDocument,
64             final DocumentedException sendErrorException) {
65         try {
66             final Element incommingRpc = incommingDocument.getDocumentElement();
67             Preconditions.checkState(
68                 XmlNetconfConstants.RPC_KEY.equals(incommingRpc.getLocalName())
69                 && XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0.equals(incommingRpc.getNamespaceURI()),
70                     "Missing %s element", XmlNetconfConstants.RPC_KEY);
71
72             final Element rpcReply = errorDocument.getDocumentElement();
73             Preconditions.checkState(rpcReply.getTagName().equals(XmlNetconfConstants.RPC_REPLY_KEY),
74                     "Missing %s element", XmlNetconfConstants.RPC_REPLY_KEY);
75
76             final NamedNodeMap incomingAttributes = incommingRpc.getAttributes();
77             for (int i = 0; i < incomingAttributes.getLength(); i++) {
78                 final Attr attr = (Attr) incomingAttributes.item(i);
79                 // skip namespace
80                 if (attr.getNodeName().equals(XMLConstants.XMLNS_ATTRIBUTE)) {
81                     continue;
82                 }
83                 rpcReply.setAttributeNode((Attr) errorDocument.importNode(attr, true));
84             }
85         } catch (final Exception e) {
86             LOG.warn("Unable to copy incomming attributes to {}, returned rpc-error might be invalid for client",
87                     sendErrorException, e);
88         }
89     }
90
91     private static Document createDocument(final DocumentedException sendErrorException) {
92         return sendErrorException.toXMLDocument();
93     }
94
95     /**
96      * Checks if netconf error was sent successfully.
97      */
98     private static final class SendErrorVerifyingListener implements ChannelFutureListener {
99         private final DocumentedException sendErrorException;
100
101         SendErrorVerifyingListener(final DocumentedException sendErrorException) {
102             this.sendErrorException = sendErrorException;
103         }
104
105         @Override
106         public void operationComplete(final ChannelFuture channelFuture) {
107             Preconditions.checkState(channelFuture.isSuccess(), "Unable to send exception %s", sendErrorException,
108                     channelFuture.cause());
109         }
110     }
111 }